Start · Sprachen · JavaScript · Referenz · Range.selectNode()

Range.selectNode()

Methode

Setzt den Range so, dass er den angegebenen Knoten samt seinem gesamten Inhalt umschließt. Start und Ende liegen dabei im Elternknoten.

seit JavaScript Baseline: alle Browser (DOM Level 2) Kategorie: webapi

Signatur

Range.prototype.selectNode(referenceNode)

Beschreibung

selectNode() setzt Start- und Endpunkt eines Range-Objekts so, dass der übergebene Knoten vollständig im Bereich liegt, also mit Start-Tag, End-Tag und allen Nachfahren. Der Container von Start und Ende ist danach der Elternknoten von referenceNode. Der Start-Offset ist der Index des Knotens unter den Geschwistern (childNodes), der End-Offset ist dieser Index plus 1.

Wichtig ist der Unterschied zu Range.selectNodeContents(): Diese Methode erfasst nur den Inhalt des Knotens, also ohne den Knoten selbst. Wenn du ein Element komplett kopieren, entfernen, hervorheben oder markieren willst, nimmst du selectNode(). Wenn du nur seinen Text bzw. seine Kindknoten brauchst, nimmst du selectNodeContents().

Typische Einsatzfälle sind: ein Element programmatisch markieren (zusammen mit window.getSelection().addRange()), ein Element per range.extractContents() oder range.cloneContents() als DocumentFragment herauslösen oder kopieren, oder mit range.getBoundingClientRect() die Position eines Knotens ermitteln. Letzteres funktioniert auch bei Textknoten, die selbst kein getBoundingClientRect() haben.

Parameter

Name Typ Default Beschreibung
$referenceNode Pflicht Node Der Knoten, der samt Inhalt ausgewählt werden soll. Er muss einen Elternknoten haben, sonst wird ein Fehler geworfen. Möglich sind z. B. Element, Text oder Comment.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Der Range wird direkt verändert.

Beispiele

Element im Dokument markieren

// HTML: <p>Bitte <strong id="wichtig">diesen Teil</strong> lesen.</p>
const el = document.getElementById('wichtig');
const range = document.createRange();
range.selectNode(el);

const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);

console.log(selection.toString());
diesen Teil

Unterschied zu selectNodeContents() über Container und Offsets

// HTML: <ul id="liste"><li>A</li><li id="b">B</li><li>C</li></ul>
const li = document.getElementById('b');

const r1 = document.createRange();
r1.selectNode(li);
console.log(r1.startContainer.id, r1.startOffset, r1.endOffset);

const r2 = document.createRange();
r2.selectNodeContents(li);
console.log(r2.startContainer.id, r2.startOffset, r2.endOffset);
liste 1 2 b 0 1

Element als Fragment kopieren und in die Zwischenablage legen

const copyElementHtml = async (el) => {
  const range = document.createRange();
  range.selectNode(el);
  const fragment = range.cloneContents(); // enthält das Element selbst
  const wrapper = document.createElement('div');
  wrapper.append(fragment);
  await navigator.clipboard.writeText(wrapper.innerHTML);
  return wrapper.innerHTML;
};

const html = await copyElementHtml(document.querySelector('h1'));
console.log(html);
<h1>Überschrift</h1>

Position eines Textknotens bestimmen

// Textknoten haben kein getBoundingClientRect() – ein Range hilft
const textNode = document.querySelector('p').firstChild;
const range = document.createRange();
range.selectNode(textNode);
const rect = range.getBoundingClientRect();
console.log(`Text beginnt bei x=${Math.round(rect.left)}, y=${Math.round(rect.top)}`);
Text beginnt bei x=8, y=16

// Wichtig · Fallstricke

  • Kein Elternknoten: Hat referenceNode keinen Elternknoten, z. B. ein frisch erzeugtes, noch nicht eingefügtes Element oder das document selbst, wirft die Methode einen DOMException vom Typ InvalidNodeTypeError.
  • Container ist der Elternknoten: range.startContainer ist nach dem Aufruf nicht der ausgewählte Knoten, sondern sein Elternknoten. Code, der den Knoten über startContainer wiederfinden will, braucht stattdessen startContainer.childNodes[startOffset].
  • Leerzeichen-Textknoten zwischen Elementen zählen bei den Offsets mit. Im HTML-Quelltext formatierte Listen ergeben deshalb oft andere Indizes als erwartet.
  • range.extractContents() bzw. range.deleteContents() entfernen nach selectNode() den ganzen Knoten aus dem DOM, nicht nur seinen Inhalt.
  • Formularfelder: Bei <input> und <textarea> markiert eine Auswahl über Selection.addRange() nicht den eingegebenen Text. Dafür gibt es element.select() bzw. setSelectionRange().
  • Kompatibilität: Wird von allen modernen Browsern seit Langem unterstützt. StaticRange hat diese Methode nicht.