W3docs

API JavaScript Selection et Range

Apprenez à manipuler la sélection de texte et les plages dans le DOM avec les interfaces JavaScript Selection et Range.

Lorsqu'un utilisateur fait glisser le curseur sur du texte dans une page, le navigateur enregistre ce qui a été sélectionné. JavaScript expose ces informations — et vous permet de créer vous-même des sélections — à travers deux interfaces DOM liées :

  • Un Range est une paire de points de délimitation (un début et une fin) à l'intérieur du document. Il décrit quelle partie du document vous visez, jusqu'à un décalage de caractère précis à l'intérieur d'un nœud texte. Un range peut exister purement en mémoire sans que l'utilisateur en ait conscience.
  • Une Selection correspond à ce que l'utilisateur a actuellement surligné. Il s'agit essentiellement d'un wrapper autour d'un ou plusieurs ranges, lié au surlignage à l'écran et au curseur de texte (caret).

Ces API sont utiles lorsque vous devez construire un éditeur de texte enrichi, une fonctionnalité « surligner et commenter », un remplacement personnalisé ou tout ce qui lit, déplace ou stylise du texte sélectionné par programmation. Ce chapitre couvre la construction de ranges, la lecture et la modification de la sélection de l'utilisateur, ainsi que leur combinaison pour surligner et insérer du contenu.

Ce chapitre s'appuie sur la structure du DOM. Si les types de nœuds et les décalages vous sont inconnus, lisez d'abord Propriétés des nœuds : type, balise et contenu et Modifier le document.

Comprendre l'interface Selection

L'interface Selection représente le texte que l'utilisateur a surligné, ou la position actuelle du caret lorsque rien n'est surligné. Vous y accédez avec la méthode globale window.getSelection() (souvent simplement getSelection()). En interne, une sélection contient zéro ou plusieurs objets Range ; en pratique, la plupart des navigateurs ne conservent qu'un seul range, donc getRangeAt(0) est la façon courante de le lire.

La manière la plus rapide de voir ce qui est sélectionné est toString(), qui retourne le texte sélectionné sous forme de string :

// After the user highlights something on the page:
const selectedText = window.getSelection().toString();
console.log(selectedText); // whatever the user highlighted

Propriétés et méthodes utiles de Selection

  • rangeCount : Le nombre de ranges dans la sélection — 0 lorsque rien n'est sélectionné. Vérifiez toujours cela avant d'appeler getRangeAt.
  • toString() : Retourne le texte sélectionné sous forme de string.
  • getRangeAt(index) : Retourne le Range à l'index donné (utilisez 0 pour la sélection actuelle).
  • addRange(range) : Ajoute un Range à la sélection, en le surlignant à l'écran.
  • removeAllRanges() : Efface entièrement la sélection.
  • removeRange(range) : Supprime un range spécifique. La plupart des navigateurs ne conservent qu'un seul range, donc removeAllRanges() est le choix pratique.
  • collapse(node, offset) : Réduit la sélection à un seul point (un caret vide) à l'intérieur de node.

Un pattern courant consiste à lire la sélection actuelle, la modifier, puis écrire une nouvelle sélection — removeAllRanges() suivi de addRange().

Exemple pratique : surligner du texte

Pour surligner ce que l'utilisateur a sélectionné, récupérez son range, extrayez les nœuds sélectionnés du document, enveloppez-les dans un <span> stylisé, et remettez ce span à l'emplacement du contenu.

extractContents() retire le contenu sélectionné du DOM et le retourne sous forme de fragment de document, laissant le range vide (réduit) à cet endroit — ce qui est exactement là où nous insérons ensuite le span.

<div id="text">Select some of this text and press the button.</div>
<button onclick="highlightText()">Highlight</button>

<script>
function highlightText() {
  const selection = window.getSelection();
  if (!selection.rangeCount) return false;
  const range = selection.getRangeAt(0);
  const span = document.createElement('span');
  span.style.backgroundColor = 'yellow';
  const fragment = range.extractContents();
  span.appendChild(fragment);
  range.insertNode(span);
}
</script>

Explorer l'interface Range

Un Range marque un fragment du document avec deux points de délimitation — un début et une fin — chacun défini par un nœud et un décalage. La signification du décalage dépend du nœud :

  • Dans un nœud texte, le décalage est un index de caractère (par ex. le décalage 5 se situe entre le 5e et le 6e caractère).
  • Dans un nœud élément, le décalage compte les nœuds enfants (par ex. le décalage 0 est avant le premier enfant).

Créez un range vide avec document.createRange(), puis positionnez ses délimitations. Vous pouvez trouver les nœuds à cibler avec getElementById / querySelector.

Définir les délimitations

const p = document.querySelector('p');
const textNode = p.firstChild;        // the text inside <p>

const range = document.createRange();
range.setStart(textNode, 0);          // start at the first character
range.setEnd(textNode, 5);            // end before the 6th character
console.log(range.toString());        // first 5 characters of the paragraph

Deux raccourcis couvrent les cas les plus courants pour éviter de calculer manuellement les décalages :

  • selectNode(node) — le range englobe le nœud et ses balises environnantes.
  • selectNodeContents(node) — le range englobe uniquement ce qui est à l'intérieur du nœud.

Méthodes utiles de Range

  • setStart(node, offset) / setEnd(node, offset) : Positionne les délimitations de début et de fin.
  • selectNode(node) / selectNodeContents(node) : Définit les deux délimitations autour d'un nœud ou de son contenu.
  • toString() : Le texte à l'intérieur du range.
  • cloneContents() : Retourne une copie du contenu du range sous forme de fragment de document, sans toucher au document.
  • extractContents() : Déplace le contenu hors du document dans un fragment et le retourne.
  • deleteContents() : Supprime le contenu du range et ne retourne rien.
  • cloneRange() : Retourne une copie de l'objet range lui-même (pas de son contenu).
  • insertNode(node) : Insère un nœud au début du range.
  • surroundContents(node) : Enveloppe le contenu du range à l'intérieur de node — pratique pour le surlignage, mais lève une exception si le range coupe partiellement un élément non-texte.

Retenez la différence : cloneContents() copie, extractContents() déplace et retourne, deleteContents() supprime et abandonne.

Exemple pratique : extraction de texte

Cet exemple lit tout ce qui se trouve à l'intérieur d'un élément avec un range et transforme le texte sans toucher au DOM original :

<div id="content">This is some sample text for extraction.</div>
<button onclick="extractText()">Extract and Manipulate</button>

<script>
function extractText() {
  const range = document.createRange();
  const content = document.getElementById('content');
  range.selectNodeContents(content);
  const extractedText = range.toString();
  const manipulatedText = extractedText.replace('sample', 'example'); // Manipulating text
  alert(manipulatedText);
}
</script>

Dans l'exemple ci-dessus, le script remplace le mot « sample » par « example » dans le texte extrait avant de l'afficher dans une boîte d'alerte. Il s'agit d'une manipulation basique, mais elle montre comment commencer à travailler avec le texte une fois extrait.

Opérations avancées sur le texte

Au-delà de la manipulation de texte de base, les interfaces Selection et Range permettent des opérations plus complexes comme l'insertion de nœuds directement dans le document.

Exemple : Insérer du texte

Cet exemple utilise un div contenteditable : l'utilisateur clique pour placer le caret, et le bouton insère 'Hello World' à cet endroit précis. Notez comment deleteContents() supprime d'abord tout ce qui est sélectionné, puis le nouveau nœud texte est inséré et re-sélectionné pour que le caret se positionne après.

<div id="editable" contenteditable="true" style="border: 1px solid #ccc; padding: 10px; min-height: 50px;">
  Click here and set the cursor position.
</div>
<button onclick="insertText()">Insert 'Hello World'</button>

<script>
function insertText() {
  const editableDiv = document.getElementById('editable');
  const sel = window.getSelection();
  
  // Check if the selection is within the editable div
  if (!sel.rangeCount || !editableDiv.contains(sel.getRangeAt(0).commonAncestorContainer)) return;
  
  const range = sel.getRangeAt(0);
  range.deleteContents();  // Clears any selected text

  const textNode = document.createTextNode('Hello World');
  range.insertNode(textNode);

  sel.removeAllRanges();   // Clear the previous selection
  sel.addRange(range);     // Re-select the new text node
}
</script>

Résumé

  • Un Range est deux points de délimitation (nœud + décalage) décrivant un fragment du document ; créez-en un avec document.createRange() et positionnez-le avec setStart/setEnd ou les raccourcis selectNode/selectNodeContents.
  • Une Selection, obtenue via window.getSelection(), encapsule le surlignage à l'écran de l'utilisateur. Lisez-la avec toString() et getRangeAt(0) ; réécrivez-la avec removeAllRanges() + addRange().
  • Pour le contenu : cloneContents() copie, extractContents() déplace et retourne, deleteContents() supprime, et insertNode / surroundContents remettent des nœuds en place.

Ensemble, ces méthodes permettent de surligner, extraire et insérer du contenu avec précision — la base des éditeurs de texte enrichi et des outils d'annotation.

Continuer : Modifier le document · Propriétés des nœuds : type, balise et contenu · Recherche : getElement* et querySelector

Pratique

Pratique
Lesquelles des affirmations suivantes sont vraies concernant les interfaces JavaScript Range et Selection ?
Lesquelles des affirmations suivantes sont vraies concernant les interfaces JavaScript Range et Selection ?
Was this page helpful?