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

Range.setEndBefore()

Methode

Setzt das Ende eines <code>Range</code> unmittelbar vor den angegebenen Knoten, also in dessen Elternknoten am Index des Knotens.

seit JavaScript DOM Level 2 – Baseline: alle Browser Kategorie: webapi

Signatur

Range.prototype.setEndBefore(referenceNode)

Beschreibung

setEndBefore() legt das Ende eines Range-Objekts auf die Stelle direkt vor dem übergebenen Knoten. Dabei wird endContainer auf den Elternknoten von referenceNode gesetzt und endOffset auf die Position (den Index) von referenceNode in dessen childNodes. Der Referenzknoten selbst gehört damit nicht mehr zum Bereich.

Die Methode ist eine bequeme Kurzform für range.setEnd(node.parentNode, index). Den Index des Knotens musst du dabei nicht selbst berechnen. Nützlich ist das immer dann, wenn du Bereiche an Elementgrenzen ausrichten willst, etwa „alles vom Anfang des Absatzes bis vor die Überschrift“ oder „alle Knoten zwischen zwei Markierungen“.

Liegt das neue Ende vor dem aktuellen Anfang des Bereichs oder in einem anderen Dokument bzw. Baum, fällt der Bereich zusammen: Auch der Anfang wird dann auf die neue Endposition gesetzt, sodass range.collapsed den Wert true hat.

Passende Gegenstücke sind setEndAfter() (Ende direkt hinter dem Knoten), setStartBefore() und setStartAfter().

Parameter

Name Typ Default Beschreibung
$referenceNode Pflicht Node Knoten, vor dem der Bereich enden soll. Er muss einen Elternknoten haben (parentNode !== null).

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Das Range-Objekt wird direkt verändert.

Beispiele

Bereich vom Listenanfang bis vor ein bestimmtes Element

document.body.innerHTML = `
  <ul id="liste">
    <li>Eins</li><li>Zwei</li><li id="stop">Drei</li><li>Vier</li>
  </ul>`;

const liste = document.getElementById('liste');
const stop = document.getElementById('stop');

const range = document.createRange();
range.setStart(liste, 0);
range.setEndBefore(stop); // Ende = (liste, Index von #stop)

console.log(range.endContainer === liste);
console.log(range.endOffset);
console.log(range.toString());
true 2 EinsZwei

Inhalt zwischen zwei Markierungen löschen

document.body.innerHTML = `
  <article>
    <h2 id="von">Start</h2>
    <p>Veralteter Absatz 1</p>
    <p>Veralteter Absatz 2</p>
    <h2 id="bis">Ende</h2>
  </article>`;

const range = document.createRange();
range.setStartAfter(document.getElementById('von'));
range.setEndBefore(document.getElementById('bis'));

// Entfernt alles zwischen den beiden Überschriften
range.deleteContents();

console.log(document.querySelectorAll('article p').length);

Textauswahl bis vor ein Element setzen

document.body.innerHTML = `
  <p id="absatz">Bitte <strong>diesen Teil</strong> <em>nicht</em> markieren.</p>`;

const absatz = document.getElementById('absatz');
const range = document.createRange();
range.setStart(absatz, 0);
range.setEndBefore(absatz.querySelector('em'));

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

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

Zusammenfallen, wenn das Ende vor dem Anfang liegt

document.body.innerHTML = '<div id="box"><span>A</span><span>B</span><span>C</span></div>';
const [a, b, c] = document.querySelectorAll('#box span');

const range = document.createRange();
range.setStartAfter(b);   // Anfang hinter B
range.setEndBefore(a);    // Ende vor A – liegt vor dem Anfang!

console.log(range.collapsed);
console.log(range.startOffset, range.endOffset);
true 0 0

// Wichtig · Fallstricke

  • Kein Elternknoten: Ist referenceNode.parentNode gleich null (z. B. bei document selbst oder bei einem frisch erzeugten, noch nicht eingehängten Element), wirft die Methode eine DOMException vom Typ InvalidNodeTypeError.
  • Automatisches Zusammenfallen: Liegt die neue Endposition vor dem Anfang oder in einem anderen Wurzelbaum, wird der Bereich ohne Fehlermeldung auf die Endposition zusammengezogen. Setze deshalb möglichst zuerst den Anfang und dann das Ende, oder prüfe hinterher range.collapsed.
  • Nicht mit setEnd() verwechseln: setEndBefore(node) verwendet den Elternknoten als endContainer, nicht node selbst. Um innerhalb eines Textknotens zu enden, brauchst du setEnd(textNode, offset).
  • Live-Verhalten: Ein Range passt sich an spätere DOM-Änderungen an. Wird der Referenzknoten verschoben, bleibt das Ende nicht automatisch „vor“ ihm.
  • Kompatibilität: Wird seit Jahren von allen modernen Browsern unterstützt (Chrome, Firefox, Safari, Edge), ebenso von DOM-Implementierungen wie jsdom.