Signatur
Beschreibung
setEnd() legt fest, wo ein Range endet. Die Endposition besteht immer aus einem Knoten und einem Offset. Welche Bedeutung der Offset hat, hängt vom Knotentyp ab:
- Bei Text-,
Comment- undCDATASection-Knoten zählt der Offset Zeichen (genauer: UTF-16-Codeeinheiten). - Bei allen anderen Knoten (z. B. Elementen) zählt der Offset Kindknoten. Ein Offset von
2heißt also: nach dem zweiten Kindknoten.
Liegt die neue Endposition vor der aktuellen Startposition oder in einem anderen Dokument bzw. Baum, wird der Range auf die neue Endposition zusammengezogen. Start und Ende sind danach gleich (collapsed === true).
Meist verwendet man die Methode zusammen mit setStart(), um Textabschnitte gezielt zu markieren, hervorzuheben, zu löschen oder mit Selection.addRange() sichtbar auszuwählen. Häufige Einsatzfälle sind Editoren, Suchtreffer-Hervorhebung und das Messen von Textpositionen mit getBoundingClientRect().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $endNode Pflicht | Node | Knoten, in dem der Range enden soll. Ein DocumentType-Knoten ist nicht erlaubt. |
|
| $endOffset Pflicht | number | Position innerhalb von endNode: Zeichenoffset bei Text-, Comment- und CDATA-Knoten, sonst Index des Kindknotens. Muss zwischen 0 und der Länge des Knotens liegen (einschließlich). |
Beispiele
Teil eines Textknotens markieren
// <p id="intro">Hallo schöne Welt</p>
const text = document.getElementById('intro').firstChild;
const range = document.createRange();
range.setStart(text, 6);
range.setEnd(text, 12);
console.log(range.toString());
Offset als Kindknoten-Index bei Elementen
// <ul id="liste"><li>A</li><li>B</li><li>C</li></ul>
const liste = document.getElementById('liste');
const range = document.createRange();
range.setStart(liste, 0);
range.setEnd(liste, 2); // nach dem zweiten <li>
console.log(range.cloneContents().childNodes.length);
console.log(range.toString());
Suchbegriff finden und im Browser auswählen
const markiereBegriff = (element, begriff) => {
const text = element.firstChild;
const start = text.textContent.indexOf(begriff);
if (start === -1) return false;
const range = document.createRange();
range.setStart(text, start);
range.setEnd(text, start + begriff.length);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
return true;
};
console.log(markiereBegriff(document.querySelector('p'), 'Welt'));
Ende vor dem Start zieht den Range zusammen
const text = document.createTextNode('Beispieltext');
document.body.append(text);
const range = document.createRange();
range.setStart(text, 8);
range.setEnd(text, 3); // liegt vor dem Start
console.log(range.collapsed, range.startOffset, range.endOffset);
// Wichtig · Fallstricke
- Ausnahmen: Ein
endOffsetgrößer als die Länge des Knotens löst eineIndexSizeError-DOMExceptionaus. IstendNodeeinDocumentType, wird einInvalidNodeTypeErrorausgelöst. - Häufiger Fehler: Wer ein Element statt dessen Textknoten übergibt (z. B.
setEnd(p, 5)stattsetEnd(p.firstChild, 5)), meint Zeichen, bekommt aber Kindknoten gezählt, was meist zuIndexSizeErrorführt. - Offsets zählen UTF-16-Codeeinheiten. Emojis und andere Zeichen außerhalb der BMP belegen deshalb 2 Einheiten, sodass beim Trennen Surrogatpaare zerbrechen können.
- Wird das DOM nach dem Setzen verändert, passt der Browser die Grenzen des Range automatisch an. Zwischengespeicherte Offsets können dann veraltet sein.
- Um ein Ende relativ zu einem Knoten zu setzen, sind
setEndBefore()undsetEndAfter()oft einfacher. - Die Methode wird von allen modernen Browsern unterstützt. Für Ranges, die sich nicht automatisch anpassen sollen, gibt es alternativ
StaticRange.