Signatur
Beschreibung
setStart() legt fest, wo ein Range-Objekt beginnt. Die Position wird durch zwei Angaben beschrieben: einen Knoten (startNode) und einen Offset (startOffset) innerhalb dieses Knotens. Zusammen mit setEnd() lassen sich damit beliebige Dokumentbereiche genau abgrenzen, etwa um Text hervorzuheben, eine Auswahl zu erzeugen oder Inhalte zu extrahieren.
Wie der Offset gedeutet wird, hängt vom Knotentyp ab:
- Bei Text-, Comment- und CDATASection-Knoten ist er die Anzahl der Zeichen (UTF-16-Codeeinheiten) vom Anfang der Knotendaten.
- Bei allen anderen Knoten (z. B. Elementen) ist er die Anzahl der Kindknoten vor der Startposition.
Liegt der neue Startpunkt hinter dem aktuellen Endpunkt oder in einem anderen Wurzelbaum, klappt der Range zusammen: Der Endpunkt wird dann ebenfalls auf die neue Startposition gesetzt (collapsed === true).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $startNode Pflicht | Node | Knoten, in dem der Range beginnen soll. Darf kein DocumentType-Knoten sein. |
|
| $startOffset Pflicht | number | Offset innerhalb von startNode: Zeichenposition bei Text-/Kommentarknoten, sonst Index des Kindknotens. Muss zwischen 0 und der Länge des Knotens liegen. |
Beispiele
Teil eines Textknotens markieren
// <p id="satz">Hallo schöne Welt</p>
const text = document.getElementById('satz').firstChild;
const range = document.createRange();
range.setStart(text, 6); // vor „schöne“
range.setEnd(text, 12); // nach „schöne“
console.log(range.toString());
Start auf Kindknoten-Index eines Elements setzen
// <ul id="liste"><li>A</li><li>B</li><li>C</li></ul>
const liste = document.getElementById('liste');
const range = document.createRange();
// Beginn vor dem zweiten <li> (Index 1), Ende nach dem letzten
range.setStart(liste, 1);
range.setEnd(liste, liste.childNodes.length);
const fragment = range.extractContents(); // entfernt B und C
console.log(liste.children.length, fragment.childNodes.length);
Textstelle als Benutzerauswahl setzen und hervorheben
const highlight = (element, suchwort) => {
const text = element.firstChild;
const index = text.data.indexOf(suchwort);
if (index === -1) return;
const range = document.createRange();
range.setStart(text, index);
range.setEnd(text, index + suchwort.length);
// Als sichtbare Auswahl setzen
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
// Zusätzlich in <mark> einwickeln
range.surroundContents(document.createElement('mark'));
};
highlight(document.querySelector('p'), 'Welt');
Zusammenklappen, wenn Start hinter Ende liegt
const p = document.createElement('p');
p.textContent = 'Beispieltext';
const text = p.firstChild;
const range = document.createRange();
range.setStart(text, 0);
range.setEnd(text, 4);
range.setStart(text, 8); // hinter dem aktuellen Ende
console.log(range.collapsed, range.endOffset);
// Wichtig · Fallstricke
- Ausnahmen: Ist
startOffsetgrößer als die Knotenlänge (Zeichenanzahl bzw.childNodes.length) oder negativ, wird eineIndexSizeError-DOMExceptionausgelöst. Bei einemDocumentType-Knoten gibt es einenInvalidNodeTypeError. - Offset-Falle: Bei Elementen zählen alle Kindknoten, also auch Leerzeichen-Textknoten aus der HTML-Formatierung. Verwende
childNodes, nichtchildren, um den Index zu bestimmen. - Unicode: Offsets in Textknoten zählen UTF-16-Codeeinheiten. Emojis oder andere Zeichen außerhalb der BMP belegen zwei Einheiten. Ein Offset in der Mitte eines Surrogatpaars zerschneidet das Zeichen.
- Ändert sich das DOM (z. B. durch
normalize()oder Einfügen von Knoten), passen Browser die Range-Grenzen automatisch an. Zwischengespeicherte Offsets können danach nicht mehr stimmen. - Für Positionen relativ zu einem Knoten sind
setStartBefore()undsetStartAfter()oft einfacher und weniger fehleranfällig. - Kompatibilität: Wird von allen modernen Browsern unterstützt. Für Positionen, die sich beim DOM-Umbau nicht verändern sollen, gibt es
StaticRange.