In questo articolo affronteremo la selezione nel documento, così come quella nei campi dei form, come gli <input>.
JavaScript può accedere a una selezione esistente, selezionare/deselezionare nodi DOM, interamente o parzialmente, rimuovere il contenuto selezionato dal documento, racchiuderlo in un tag e così via.
Puoi trovare degli script già pronti per le azioni più comuni, alla fine del capitolo, nel âRiepilogoâ. Forse faranno fronte alle tue esigenze, ma otterrai molte più informazioni leggendo tutto il capitolo. Gli oggetti sottostanti Range e Selection sono di facile comprensione, e potrai quindi farne ciò che vuoi senza dover utilizzare script già pronti.
Range
Il concetto alla base della selezione è il Range, il quale definisce una coppia di âpunti limiteâ: inizio e fine del range.
Un oggetto Range viene creato senza parametri:
let range = new Range();
Possiamo quindi impostare i limiti della nostra selezione usando range.setStart(node, offset) e range.setEnd(node, offset).
Come puoi immaginare, più avanti useremo gli oggetti Range per la selezione, ma prima proviamo a creare alcuni di questi oggetti.
Selezione parziale del testo
la cosa interessante è che il primo argomento node in entrambi i metodi, può essere sia uno nodo di testo che uno nodo-elemento, ed lâinterpretazione del secondo elemento dipende da questo.
Se node è un nodo di testo, allora offset deve essere la posizione nel testo.
Ad esempio, dato lâelemento <p>Hello</p>, possiamo creare il range contenente le lettere âllâ nel seguente modo:
<p id="p">Hello</p>
<script>
let range = new Range();
range.setStart(p.firstChild, 2);
range.setEnd(p.firstChild, 4);
// toString di un range, restituisce il suo contenuto come testo
console.log(range); // ll
</script>
Qui prendiamo il primo elemento figlio di <p> (che è il nodo di testo) e specifichiamo la posizione del testo al suo interno:
Selezione nei nodi elemento
In alternativa, se node è un nodo elemento, allora offset deve essere il numero dellâelemento figlio.
Questo è utile per creare selezioni che contengono nodi completi, senza limitarsi al solo testo contenuto.
Ad esempio, qui abbiamo una parte di un documento più complesso:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
Ecco la struttura del DOM con sia nodi testo che nodi elemento:
Creiamo un range per "Example: <i>italic</i>".
Come possiamo vedere, questa frase è composta esattamente dal primo e dal secondo figlio di <p>, con indici 0 e 1:
-
Lâinizio contiene
<p>comenodogenitore, e0come offset. Quindi possiamo impostarlo conrange.setStart(p, 0). -
La fine contiene anchâessa
<p>comenodogenitore, ma2come offset (specifica il range fino aoffset, ma senza includerlo). Quindi possiamo impostarlo conrange.setEnd(p, 2).
Eseguendo la demo potrai vedere il testo che viene selezionato:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<script>
let range = new Range();
range.setStart(p, 0);
range.setEnd(p, 2);
// toString di un range restituisce il suo contenuto come testo senza i tags
console.log(range); // Example: italic
// applichiamo questo range per la selezione del documento (verrà spiegato in seguito)
document.getSelection().addRange(range);
</script>
Ecco esempio più flessibile, dove provare più varianti:
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
From <input id="start" type="number" value=1> â To <input id="end" type="number" value=4>
<button id="button">Click to select</button>
<script>
button.onclick = () => {
let range = new Range();
range.setStart(p, start.value);
range.setEnd(p, end.value);
// applica la selezione, verrà spiegato in seguito
document.getSelection().removeAllRanges();
document.getSelection().addRange(range);
};
</script>
Ad esempio, la selezione allâinterno della stesso <p> da offset 1 a 4, ci restituisce il range <i>italic</i> and <b>bold</b>:
Non dobbiamo necessariamente usare lo stesso nodo in setStart e setEnd. Un range può spaziare attraverso un serie di nodi non necessariamente correlati. La sola cosa che importa è che la fine sia effettivamente dopo lâinizio.
Selezionare porzioni più estese
Creiamo una selezione più estesa a partire dal nostro esempio, in questo modo:
Sappiamo già come farlo. Abbiamo solo bisogno di impostare lâinizio e la fine come offset relativo nei nodi testuali.
Dobbiamo creare un range che:
- cominci dalla posizione 2 in
<p>primo figlio (prendendo tutto tranne le prime due lettere di "Example: ") - finisca alla posizione 3 in
<b>primo figlio (prendendo le prime tre lettere di âboldâ, e nientâaltro):
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<script>
let range = new Range();
range.setStart(p.firstChild, 2);
range.setEnd(p.querySelector('b').firstChild, 3);
console.log(range); // ample: italic and bol
// usa questo range per la selezione (spiegato dopo)
window.getSelection().addRange(range);
</script>
Come puoi vedere, è abbastanza facile creare una selezione di qualsiasi cosa ci serva.
Se vogliamo selezionare nodi completi, possiamo passare gli elementi in setStart / setEnd. Altrimenti, possiamo lavorare a livello di testo.
proprietà di range
Lâoggetto range che abbiamo creato nellâesempio ha le seguenti proprietà :
startContainer,startOffsetâ nodo e offset di inizio,- nellâesempio sopra: primo nodo testuale allâinterno di
<p>e2.
- nellâesempio sopra: primo nodo testuale allâinterno di
endContainer,endOffsetâ nodo e offset della fine,- nellâesempio sopra: primo nodo testuale allâinterno di
<b>e3.
- nellâesempio sopra: primo nodo testuale allâinterno di
collapsedâ booleano,truese il range comincia e finisce nello stesso punto (quindi non câè contenuto nel range),- nellâesempio sopra:
false
- nellâesempio sopra:
commonAncestorContainerâ il più vicino genitore tra tutti i nodi allâinterno del range,- nellâesempio sopra:
<p>
- nellâesempio sopra:
Metodi di range
Ci sono una serie di metodi utili per manipolare i range.
Abbiamo già visto setStart e setEnd, di seguito alcuni metodi utili agli stessi scopi.
Impostare lâinizio del range:
setStart(node, offset)imposta lâinizio: alla posizioneoffsetdelnodesetStartBefore(node)imposta lâinizio: appena prima dinodesetStartAfter(node)imposta lâinizio: appena dopo dinode
Impostare la fine del range (metodi simili):
setEnd(node, offset)imposta la fine: alla posizioneoffsetnelnodesetEndBefore(node)imposta la fine: appena prima dinodesetEndAfter(node)imposta la fine: appena doponode
Tecnicamente, setStart/setEnd può fare tutto, ma più metodi possono rivelarsi utili.
Come visto, node può essere sia un nodo testuale che un nodo elemento: per i nodi testuali offset salta il numero di caratteri specificato, mentre per i nodi elemento salta i nodi figlio specificati.
Altri metodi per creare ranges:
selectNode(node)Imposta un range per selezionare lâinteronodo.selectNodeContents(node)Imposta un range per selezionare lâintero contenuto delnodo.collapse(toStart)setoStart=trueimpostaend=start, altrimenti impostastart=end, collassando così il range.cloneRange()crea un nuovo range con lo stesso inizio e fine
metodi per la modifica di range
Una volta creato il range, possiamo manipolare il contenuto con i seguenti metodi:
deleteContents()â rimuove il contenuto del range dal documentoextractContents()â rimuove il contenuto del range dal documento e lo ritorna come DocumentFragmentcloneContents()â clona un contenuto del range e lo restituisce come DocumentFragmentinsertNode(node)â inseriscenodenel documento allâinizio del rangesurroundContents(node)â avvolgenodeattorno al contenuto range. Per questa azione, il range deve contenere i tag di apertura e chiusura per tutti gli elementi dentro di esso: non possono esserci range del tipo<i>abc.
Fondamentalmente, con questi metodi possiamo fare qualunque cosa con i nodi selezionati.
Ecco il banco di prova per vederli in azione:
Clicca sui pulsanti per eseguire i metodi nella selezione, "resetExample" per resettare.
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<p id="result"></p>
<script>
let range = new Range();
// Ogni metodo mostrato è rappresentato qui:
let methods = {
deleteContents() {
range.deleteContents()
},
extractContents() {
let content = range.extractContents();
result.innerHTML = "";
result.append("extracted: ", content);
},
cloneContents() {
let content = range.cloneContents();
result.innerHTML = "";
result.append("cloned: ", content);
},
insertNode() {
let newNode = document.createElement('u');
newNode.innerHTML = "NEW NODE";
range.insertNode(newNode);
},
surroundContents() {
let newNode = document.createElement('u');
try {
range.surroundContents(newNode);
} catch(e) { console.log(e) }
},
resetExample() {
p.innerHTML = `Example: <i>italic</i> and <b>bold</b>`;
result.innerHTML = "";
range.setStart(p.firstChild, 2);
range.setEnd(p.querySelector('b').firstChild, 3);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
};
for(let method in methods) {
document.write(`<div><button onclick="methods.${method}()">${method}</button></div>`);
}
methods.resetExample();
</script>
Ci sono anche metodi per confrontare i range, ma vengono usati raramente. Nel caso in cui ne avessi bisogno puoi fare riferimento alle specifiche o sul manuale MDN.
Selection
Range è un oggetto generico per la gestione di selezioni. Comunque, creare un Range non significa che vedremo la selezione sullo schermo.
Possiamo creare oggetti Range, passarli in giro, ma visivamente non avranno alcun effetto.
La selezione del documento è rappresentata da un oggetto Selection, che si può ottenere come window.getSelection() o tramite document.getSelection(). Una selezione può includere zero o più range. Almeno così dice la Specifica della API Selection.
In pratica, tuttavia, solamente Firefox permette di selezionare range multipli nel documento, attraverso la combinazione di tasti Ctrl+click (Cmd+click su Mac).
Qui potete vedere uno screenshot di una selezione con 3 range, fatta su Firefox:
Gli altri browser supportano al massimo 1 range. Come vedremo, alcuni dei metodi di Selection implicano la possibilità di avere più range, ma di nuovo, tutti i browser eccetto Firefox, ne possono avere massimo 1.
Questo è un piccolo esempio che mostra la selezione corrente come testo. Seleziona qualcosa e clicca:
Proprietà di Selection
Come detto, una selection può in teoria contenere più ranges. Possiamo ottenere questi renge usando il seguente metodo:
getRangeAt(i)â recupera il range numeroi, partendo da0. In tutti i browser, ad eccezione di Firefox, viene usato solo il numero0.
Inoltre, esistono proprietà che spesso sono più comode da usare.
In modo simile a un range, una selezione ha un inizio, chiamato âanchorâ, e una fine, chiamata âfocusâ.
Le proprietà principali di selection sono:
anchorNodeâ il nodo dove comincia la selezione,anchorOffsetâ lâoffset inanchorNodedove comincia la selezione,focusNodeâ il nodo in cui termina la selezione,focusOffsetâ lâoffset difocusNodein cui termina la selezione,isCollapsedâtruese la selezione non seleziona nulla (range vuoto), o non esiste.rangeCountâ conto del numero di selezioni, massimo1su tutti i browser, eccetto Firefox.
Esiste unâimportante differenza tra una selection anchor/focus e un Range start/end.
Come sappiamo, lâ oggetto Range ha il suo inizio prima della fine.
Per le selections, questo non è sempre vero.
le selezione tramite il mouse, può avvenire in entrambe le direzioni: sia da sinistra verso destra, che da destra verso sinistra.
In altre parole, se mentre il pulsante del mouse è premuto ci muoviamo avanti nel documento, la fine (focus) sarà dopo lâinizio (anchor)
Ad esempio, se lâutente comincia la selezione con il mouse andando da âExampleâ a âitalicâ:
Ma la stessa selezione potrebbe essere effettuata anche a ritroso, partendo da âitalicâ a âExampleâ (direzione contraria), in questo caso la fine (focus) sarà prima dellâinizio (anchor):
Eventi di Selection
Ci sono eventi per tenere traccia della selezione:
elem.onselectstartâ quando una selezione inizia su specificatamente suelem(o al suo interno). Ad esempio, quando lâutente preme il pulsante del mouse sullâelemento e poi muove il puntatore.- Prevenire lâazione predefinita (prevent default), fa in modo che la selezione non cominci. Quindi iniziare una selezione dallâelemento diventa impossibile, ma lâelemento è ancora selezionabile. Il visitatore deve solo iniziare la selezione da altrove.
document.onselectionchangeâ ogni volta che una selezione viene modificata.- Nota bene: questo gestore può essere impostato solo su
document.
- Nota bene: questo gestore può essere impostato solo su
Demo di tracciamento per Selection
Ecco una piccola demo che tiene traccia della selezione corrente sul documento e mostra i suoi confini:
<p id="p">Select me: <i>italic</i> and <b>bold</b></p>
From <input id="from" disabled> â To <input id="to" disabled>
<script>
document.onselectionchange = function() {
let selection = document.getSelection();
let {anchorNode, anchorOffset, focusNode, focusOffset} = selection;
// anchorNode and focusNode are text nodes usually
from.value = `${anchorNode?.data}, offset ${anchorOffset}`;
to.value = `${focusNode?.data}, offset ${focusOffset}`;
};
</script>
Copiare una selezione
Ci sono due approcci alla copia del contenuto di una selezione:
- Possiamo usare
document.getSelection().toString()per avere il contenuto come testo. - Oppure possiamo copiare il DOM completo (ad esempio se volgiamo mantenere la formattazione) recuperando i ranges con
getRangesAt(...). Un oggettoRangepossiede il metodocloneContents()che clona il contenuto e lo ritorna come oggettoDocumentFragment, che può essere inserito dove necessario.
Ecco la demo per copiare il contenuto selezionato, sia come testo che come nodi del DOM:
<p id="p">Select me: <i>italic</i> and <b>bold</b></p>
Cloned: <span id="cloned"></span>
<br>
As text: <span id="astext"></span>
<script>
document.onselectionchange = function() {
let selection = document.getSelection();
cloned.innerHTML = astext.innerHTML = "";
// Clona i nodi a partire dal range (qui viene supportata la multiselezione)
for (let i = 0; i < selection.rangeCount; i++) {
cloned.append(selection.getRangeAt(i).cloneContents());
}
// Ottiene come testo
astext.innerHTML += selection;
};
</script>
Metodi per la selezione
Possiamo lavorare con la selezione aggiungendo/rimuovendo ranges:
getRangeAt(i)â legge il range alla posizione i, partendo da â0â. In tutti i browser, tranne Firefox, viene usato solo0.addRange(range)â aggiungerangealla selezione. Tutti i browser, eccetto Firefox, ignorano la chiamata, se la selezione ha già un range associato.removeRange(range)â Rimuoverangedalla selezione.removeAllRanges()â Rimuove tutti i range.empty()â alias perremoveAllRanges.
Inoltre, ci sono metodi di utilità per manipolare direttamente il range di selezione, senza Range:
collapse(node, offset)â rimpiazza il range selezionato con un nuovo range che comincia danode, alla posizioneoffset.setPosition(node, offset)â alias dicollapse.collapseToStart()â collassa (sostituisce con un nodo vuoto) allâinizio della selezione,collapseToEnd()â collassa alla fine della selezione,extend(node, offset)â muove il focus della selezione al nodonode, alla posizioneoffset,setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)â sostituisce il range selezionato con quello che ha inizio inanchorNode/anchorOffsete fine infocusNode/focusOffset. Tutto il contenuto in mezzo viene selezionato.selectAllChildren(node)â seleziona tutti i figli dinode.deleteFromDocument()â rimuove il contenuto selezionato dal documento.containsNode(node, allowPartialContainment = false)â controlla se la selezione contienenode(o una sua porzione, se il secondo argomento ètrue)
Nella maggior parte dei casi, quindi, possiamo semplicemente utilizzare i metodi offerti da Selection, senza dover accedere agli oggetti Range sottostanti.
Per esempio, per selezionare lâintero contenuto del paragrafo <p>:
<p id="p">Select me: <i>italic</i> and <b>bold</b></p>
<script>
// seleziona dal figlio #0 di <p> all'ultimo figlio
document.getSelection().setBaseAndExtent(p, 0, p, p.childNodes.length);
</script>
Stessa cosa, utilizzando però i range:
<p id="p">Select me: <i>italic</i> and <b>bold</b></p>
<script>
let range = new Range();
range.selectNodeContents(p); // oppure selectNode(p) per selezionare il tag <p>
document.getSelection().removeAllRanges(); // pulisce la selezione se esiste
document.getSelection().addRange(range);
</script>
Nel caso in cui ci fosse già una selezione attiva, va prima rimossa tramite removeAllRanges(). Una volta eliminata, sarà possibile aggiungere un nuovo Range. Diversamente, tutti i browser eccetto Firefox, ignoreranno i nuovi range.
Lâeccezione a questa regola sono i metodi di selezione, che sostituiscono la selezione esistente, come setBaseAndExtent.
Selezione nei controlli dei form
Gli elementi dei form, come input e textarea forniscono API speciali per la selezione, senza lâausilio degli oggetti Selection o Range. Dato che un valore di input è testo puro, e non HTML, non è necessario lâutilizzo di questi due oggetti, poiché è tutto più semplificato.
Proprietà :
input.selectionStartâ posizione dellâinizio della selezione (scrivibile),input.selectionEndâ posizione della fine della selezione (scrivibile),input.selectionDirectionâ direzione della selezione, un valore tra: âforwardâ, âbackwardâ o ânoneâ (ad esempio, la selezione attraverso il doppio click del mouse),
Eventi:
input.onselectâ viene innescato alla selezione di un elemento.
Metodi:
-
input.select()â seleziona lâintero contenuto dellâarea di testo (può essere unatextareainvece cheinput), -
input.setSelectionRange(start, end, [direction])â modifica la selezione, selezionando il contenuto compreso trastartfino aend, in una data direzione (opzionale). -
input.setRangeText(replacement, [start], [end], [selectionMode])â sostituisce un range di testo con nuovo testo.Se forniti, gli argomenti opzionali
startedend, impostano lâinizio e la fine del range, altrimenti viene usata la selezione dellâutente.Lâultimo argomento,
selectionMode, determina come la selezione verrà impostata dopo che il testo verrà rimpiazzato. I valori possibili sono:"select"â il nuovo testo inserito, verrà selezionato."start"â il range di selezione collasserà subito prima del testo inserito (il cursore verrà posizionato subito prima di esso)."end"â il range di selezione collassa subito dopo del testo inserito (il cursore verrà posizionato alla sua destra)."preserve"â tenta di preservare la selezione. Questo è il comportamento predefinito.
Vediamo questi metodi in azione.
Esempio: tenere traccia della selezione
Questo codice usa lâevento onselect per tenere traccia della selezione:
<textarea id="area" style="width:80%;height:60px">
Selecting in this text updates values below.
</textarea>
<br>
From <input id="from" disabled> â To <input id="to" disabled>
<script>
area.onselect = function() {
from.value = area.selectionStart;
to.value = area.selectionEnd;
};
</script>
Nota bene:
onselectviene innescato quando viene selezionato un elemento, ma non quando la selezione viene rimossa.- lâevento
document.onselectionchangenon dovrebbe essere innescato per selezioni dentro un controllo di un form, secondo le specifiche, dal momento che non è correlato alla selezione e range deldocument. Alcuni browser lo emettono in ogni caso, ma non possiamo farci affidamento.
Esempio: spostare il cursore
Possiamo modificare selectionStart e selectionEnd, che impostano la selezione.
Un importante caso limite è quando selectionStart and selectionEnd si equivalgono. Ciò rappresenta esattamente la posizione del cursore. Oppure, riformulando, quando non câè nulla di selezionato, la selezione è collassata nella posizione del cursore.
In questo modo, impostando selectionStart e selectionEnd allo stesso valore, spostiamo il cursore.
Ad esempio:
<textarea id="area" style="width:80%;height:60px">
Focus on me, the cursor will be at position 10.
</textarea>
<script>
area.onfocus = () => {
// setTimeout impostato a zero, per eseguirlo subito dopo il che il "focus" viene completato.
setTimeout(() => {
// Possiamo impostare qualunque selezione
// se start=end, il cursore è esattamente in quel punto
area.selectionStart = area.selectionEnd = 10;
});
};
</script>
Esempio: modifica della selezione
Per modificare il contenuto della selezione, possiamo usare il metodo input.setRangeText(). Di sicuro, possiamo leggere selectionStart/End e, conoscendo la selezione, possiamo cambiare la corrispondente sottostringa di value, ma setRangeText è molto più potente e spesso più conveniente.
Questo è un metodo in qualche maniera complesso. Nella sua forma più semplice con un solo argomento, sostituisce il range selezionato dallâutente e rimuove la selezione.
For example, here the user selection will be wrapped by *...*:
<input id="input" style="width:200px" value="Select here and click the button">
<button id="button">Avvolge la selezione tra asterischi *...*</button>
<script>
button.onclick = () => {
if (input.selectionStart == input.selectionEnd) {
return; // nessuna selezione
}
let selected = input.value.slice(input.selectionStart, input.selectionEnd);
input.setRangeText(`*${selected}*`);
};
</script>
With more arguments, we can set range start and end.
In this example we find "THIS" in the input text, replace it and keep the replacement selected:
<input id="input" style="width:200px" value="Replace THIS in text">
<button id="button">Sostituisce THIS</button>
<script>
button.onclick = () => {
let pos = input.value.indexOf("THIS");
if (pos >= 0) {
input.setRangeText("*THIS*", pos, pos + 4, "select");
input.focus(); // focus per mantenere la selezione visibile
}
};
</script>
Esempio: inserimento nella posizione del cursore
Se non câè nulla di selezionato, o se start ed end si equivalgono in setRangeText, allora il nuovo testo verrà solo inserito e non verrà rimosso nulla.
Possiamo anche inserire qualcosa ânella posizione del cursoreâ usando setRangeText.
Qui abbiamo un pulsante che inserisce "HELLO" sul cursore, posizionandolo immediatamente dopo. Se la selezione non è vuota, allora verrà sostituita (possiamo riconoscerla confrontando selectionStart!=selectionEnd o facendo qualcosâaltro):
<input id="input" style="width:200px" value="Text Text Text Text Text">
<button id="button">Inserisci "HELLO" al cursore</button>
<script>
button.onclick = () => {
input.setRangeText("HELLO", input.selectionStart, input.selectionEnd, "end");
input.focus();
};
</script>
Impedire la selezione
Per rendere qualcosa non selezionabile, ci sono tre modi:
-
Utilizzare la proprietà CSS
user-select: none.<style> #elem { user-select: none; } </style> <div>Selezionabile <div id="elem">Non selezionabile</div> Selezionabile</div>Questo non permette alla selezione di cominciare su
elem. Tuttavia lâutente può cominciare la selezione ovunque, ed includereelemal suo interno.Quindi
elemdiverrà parte didocument.getSelection(), e così la selezione câè, ma il suo contenuto viene generalmente ignorato nel copia-incolla. -
Prevenire lâazione predefinita sugli eventi
onselectstartomousedown.<div>Selezionabile <div id="elem">Non selezionabile</div> Selezionabile</div> <script> elem.onselectstart = () => false; </script>Questo impedisce la selezione su
elem, ma il visitatore può cominciare la selezione su un altro elemento e successivamente estendere la selezione suelem.Questo è comodo quando câè un altro gestore di eventi nella stessa azione, che innesca la selezione (ad esempio
mousedown). Facendo ciò, disabilitiamo la selezione evitando conflitti, lasciando che i contenutielempossano ancora essere copiati. -
Possiamo anche pulire la selezione successivamente dopo che sia avvenuta tramite
document.getSelection().empty(). Questa cosa è usata raramente, dato che causa intermittenze non volute sulla selezione che compare-scompare.
Riferimenti
- Specifiche DOM: Range
- API Selection
- Specifiche HTML: APIs per il controllo delle selezioni sul testo
Riepilogo
Abbiamo affrontato due differenti API per le selezioni:
- Per i documenti: oggetti
SelectioneRange. - Per gli
input,textarea: proprietà e metodi aggiuntivi.
La seconda API è molto semplice, dato che lavora con i testi.
I codici pronti più usati sono probabilmente:
- Ottenere la selezione:
let selection = document.getSelection(); let cloned = /* elemento nel quale clonare i nodi selezionati */; // quindi applica i metodi Range su selection.getRangeAt(0) // oppure a tutti i range per supportare la multiselezione, come in questo caso for (let i = 0; i < selection.rangeCount; i++) { cloned.append(selection.getRangeAt(i).cloneContents()); } - Impostare la selezione:
let selection = document.getSelection(); // direttamente: selection.setBaseAndExtent(...from...to...); // oppure possiamo creare una range e: selection.removeAllRanges(); selection.addRange(range);
Infine, relativamente al cursore. La posizione del cursore negli elementi editabili, come <textarea> è sempre allâinizio o alla fine della selezione. Possiamo usarla per ottenere la posizione corrente del cursore o per muovere il cursore impostando elem.selectionStart e elem.selectionEnd.
Commenti
<code>, per molte righe â includile nel tag<pre>, per più di 10 righe â utilizza una sandbox (plnkr, jsbin, codepenâ¦)