Signatur
Beschreibung
setStartAfter() verschiebt den Startpunkt eines Range-Objekts an die Stelle direkt nach dem übergebenen Knoten. Intern entspricht das range.setStart(referenceNode.parentNode, index + 1), wobei index die Position des Knotens unter den Kindern seines Elternknotens ist. Du musst den Index also nicht selbst ermitteln.
Nützlich ist die Methode, wenn ein Bereich hinter einem bestimmten Element beginnen soll, etwa um alle Geschwister nach einer Überschrift auszuwählen, Inhalte hinter einem Marker-Element zu löschen oder den Cursor in einem contenteditable-Bereich hinter ein gerade eingefügtes Element zu setzen.
Liegt der neue Startpunkt hinter dem aktuellen Endpunkt (oder in einem anderen Dokument bzw. Baum), wird der Range auf den neuen Startpunkt zusammengeklappt (collapsed === true), d. h. auch der Endpunkt wird dorthin verschoben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $referenceNode Pflicht | Node | Knoten, hinter dem der Range beginnen soll. Muss einen Elternknoten besitzen. |
Beispiele
Alle Absätze nach einer Überschrift auswählen
// HTML: <article><h2 id="titel">Titel</h2><p>Eins</p><p>Zwei</p></article>
const titel = document.getElementById('titel');
const range = document.createRange();
range.setStartAfter(titel); // Start direkt hinter <h2>
range.setEndAfter(titel.parentNode.lastChild); // Ende hinter dem letzten Kind
console.log(range.toString());
console.log(range.startContainer.tagName, range.startOffset);
Inhalt hinter einem Marker entfernen
// HTML: <ul id="liste"><li>A</li><li id="marker">B</li><li>C</li><li>D</li></ul>
const marker = document.getElementById('marker');
const liste = document.getElementById('liste');
const range = document.createRange();
range.setStartAfter(marker);
range.setEnd(liste, liste.childNodes.length);
range.deleteContents();
console.log(liste.textContent);
Cursor hinter eingefügtes Element setzen (contenteditable)
const insertEmoji = (emoji) => {
const selection = window.getSelection();
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
const span = document.createElement('span');
span.textContent = emoji;
range.deleteContents();
range.insertNode(span);
// Cursor hinter das neue <span> setzen
range.setStartAfter(span);
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
};
document.querySelector('#emoji-btn')
.addEventListener('click', () => insertEmoji('😀'));
Automatisches Zusammenklappen
const range = document.createRange();
const p = document.createElement('p');
p.innerHTML = '<b>1</b><i>2</i>';
range.selectNode(p.firstChild); // Range umfasst <b>
range.setStartAfter(p.lastChild); // Start liegt hinter dem Ende
console.log(range.collapsed, range.startOffset, range.endOffset);
// Wichtig · Fallstricke
- Kein Elternknoten: Hat
referenceNodekeinenparentNode(z. B. ein losgelöstes Element oder dasdocumentselbst), wird eineDOMExceptionvom TypInvalidNodeTypeErrorausgelöst. - Doctype: Auch ein
DocumentType-Knoten als Elternknoten führt zu einemInvalidNodeTypeError. - Zusammenklappen: Liegt der neue Start hinter dem aktuellen Ende, wird auch das Ende verschoben – bei Bedarf danach mit
setEnd()/setEndAfter()neu setzen. - Offsets: Der Startcontainer ist danach immer der Elternknoten, nicht der Referenzknoten selbst. Bei Textknoten als Ziel für zeichengenaue Positionen stattdessen
setStart(textNode, offset)verwenden. - Live-Verhalten: Ranges passen sich bei späteren DOM-Änderungen automatisch an; ein
StaticRangetut das nicht. - Wird von allen modernen Browsern unterstützt.