Ottieni il testo selezionato e i nodes selezionati su una pagina?

Quando si seleziona un blocco di testo (possibilmente esteso su molti nodes DOM), è ansible estrarre il testo e i nodes selezionati usando Javascript?

Immagina questo codice HTML:

Hello World

Hi there!

Se l’utente ha avviato un evento mouseDown che inizia da “World …” e poi un mouseUp anche dopo “there!”, Spero che possa tornare:

 Text : { selectedText: "WorldHi there!" }, Nodes: [ { node: "h1", offset: 6, length: 5 }, { node: "p", offset: 0, length: 16 }, { node: "p > b", offset: 0, length: 6 } ] 

Ho provato a inserire l’HTML in una textarea, ma mi otterrà solo il testo selezionato. Non ho provato l’elemento ma potrebbe essere un’altra opzione.

Se non JavaScript, esiste un modo in cui è ansible utilizzare un’estensione per Firefox?

Sei in una corsa sconnessa, ma questo è abbastanza ansible. Il problema principale è che IE e W3C espongono interfacce completamente diverse alle selezioni, quindi se si desidera la funzionalità cross-browser allora è necessario scrivere l’intera cosa due volte. Inoltre, alcune funzionalità di base mancano da entrambe le interfacce.

La connessione sviluppatore di Mozilla ha la storia sulle selezioni del W3C . Microsoft ha il proprio sistema documentato su MSDN . Consiglio di iniziare dall’introduzione di PPK alle gamme .

Ecco alcune funzioni di base che credo funzionino:

 // selection objects will differ between browsers function getSelection () { return ( msie ) ? document.selection : ( window.getSelection || document.getSelection )(); } // range objects will differ between browsers function getRange () { return ( msie ) ? getSelection().createRange() : getSelection().getRangeAt( 0 ) } // abstract getting a parent container from a range function parentContainer ( range ) { return ( msie ) ? range.parentElement() : range.commonAncestorContainer; } 

La mia libreria di Rangy ti farà ottenere la tua parte unificando le diverse API in IE <9 e tutti gli altri principali browser e fornendo una funzione getNodes() sui suoi oggetti Range:

 function getSelectedNodes() { var selectedNodes = []; var sel = rangy.getSelection(); for (var i = 0; i < sel.rangeCount; ++i) { selectedNodes = selectedNodes.concat( sel.getRangeAt(i).getNodes() ); } return selectedNodes; } 

Ottenere il testo selezionato è abbastanza semplice in tutti i browser. A Rangy è solo

 var selectedText = rangy.getSelection().toString(); 

Senza Rangy:

 function getSelectedText() { var sel, text = ""; if (window.getSelection) { text = "" + window.getSelection(); } else if ( (sel = document.selection) && sel.type == "Text") { text = sel.createRange().text; } return text; } 

Per quanto riguarda gli offset di caratteri, puoi fare qualcosa di simile a qualsiasi nodo node nella selezione. Nota che questo non rappresenta necessariamente il testo visibile nel documento perché non tiene conto degli spazi compressi, del testo nascosto tramite CSS, del testo posizionato al di fuori del normale stream del documento tramite CSS, delle interruzioni di linea implicite dagli elementi
e di blocco, oltre ad altre sottigliezze .

 var sel = rangy.getSelection(); var selRange = sel.getRangeAt(0); var rangePrecedingNode = rangy.createRange(); rangePrecedingNode.setStart(selRange.startContainer, selRange.startOffset); rangePrecedingNode.setEndBefore(node); var startIndex = rangePrecedingNode.toString().length; rangePrecedingNode.setEndAfter(node); var endIndex = rangePrecedingNode.toString().length; alert(startIndex + ", " + endIndex); 

Questo restituisce i nodes selezionati come ho capito: quando ho

 

...

...

...

...

...

...

...

...

...

...

...

un sacco di nodes e seleziono solo alcuni poi voglio solo che questi nodes siano nella lista.

 function getSelectedNodes() { // from https://developer.mozilla.org/en-US/docs/Web/API/Selection var selection = window.getSelection(); if (selection.isCollapsed) { return []; }; var node1 = selection.anchorNode; var node2 = selection.focusNode; var selectionAncestor = get_common_ancestor(node1, node2); if (selectionAncestor == null) { return []; } return getNodesBetween(selectionAncestor, node1, node2); } function get_common_ancestor(a, b) { // from http://stackoverflow.com/questions/3960843/how-to-find-the-nearest-common-ancestors-of-two-or-more-nodes $parentsa = $(a).parents(); $parentsb = $(b).parents(); var found = null; $parentsa.each(function() { var thisa = this; $parentsb.each(function() { if (thisa == this) { found = this; return false; } }); if (found) return false; }); return found; } function isDescendant(parent, child) { // from http://stackoverflow.com/questions/2234979/how-to-check-in-javascript-if-one-element-is-a-child-of-another var node = child; while (node != null) { if (node == parent) { return true; } node = node.parentNode; } return false; } function getNodesBetween(rootNode, node1, node2) { var resultNodes = []; var isBetweenNodes = false; for (var i = 0; i < rootNode.childNodes.length; i+= 1) { if (isDescendant(rootNode.childNodes[i], node1) || isDescendant(rootNode.childNodes[i], node2)) { if (resultNodes.length == 0) { isBetweenNodes = true; } else { isBetweenNodes = false; } resultNodes.push(rootNode.childNodes[i]); } else if (resultNodes.length == 0) { } else if (isBetweenNodes) { resultNodes.push(rootNode.childNodes[i]); } else { return resultNodes; } }; if (resultNodes.length == 0) { return [rootNode]; } else if (isDescendant(resultNodes[resultNodes.length - 1], node1) || isDescendant(resultNodes[resultNodes.length - 1], node2)) { return resultNodes; } else { // same child node for both should never happen return [resultNodes[0]]; } } 

Il codice dovrebbe essere disponibile all'indirizzo: https://github.com/niccokunzmann/spiele-mit-kindern/blob/gh-pages/javascripts/feedback.js

Ho postato questa risposta qui perché mi sarebbe piaciuto trovarla qui.

C’è un modo molto più breve se vuoi solo la gamma.

 function getRange(){ return (navigator.appName=="Microsoft Internet Explorer") ? document.selection.createRange().parentElement() : (getSelection||document.getSelection)().getRangeAt(0).commonAncestorContainer } 

Tutti i codici conformi agli standard che funzionano in IE11 +.

Stringa di testo

 window.getSelection().getRangeAt(0).toString() 

Il nodo iniziale (anche se il testo è selezionato all’indietro):

 window.getSelection().anchorNode 

Il nodo finale (anche se il testo è selezionato all’indietro):

 window.getSelection().focusNode 

Volete saperne di più? Seleziona un testo ed esegui il seguente codice JavaScript nella console:

 console.log(window.getSelection()); console.log(window.getSelection().getRangeAt(0));