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

Range.setEnd()

Methode

Setzt die Endposition eines <code>Range</code> auf den angegebenen Offset innerhalb des Knotens <code>endNode</code>.

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

Signatur

Range.prototype.setEnd(endNode, endOffset)

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- und CDATASection-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 2 heiß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());
schöne

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());
2 AB

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'));
true

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);
true 3 3

// Wichtig · Fallstricke

  • Ausnahmen: Ein endOffset größer als die Länge des Knotens löst eine IndexSizeError-DOMException aus. Ist endNode ein DocumentType, wird ein InvalidNodeTypeError ausgelöst.
  • Häufiger Fehler: Wer ein Element statt dessen Textknoten übergibt (z. B. setEnd(p, 5) statt setEnd(p.firstChild, 5)), meint Zeichen, bekommt aber Kindknoten gezählt, was meist zu IndexSizeError fü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() und setEndAfter() oft einfacher.
  • Die Methode wird von allen modernen Browsern unterstützt. Für Ranges, die sich nicht automatisch anpassen sollen, gibt es alternativ StaticRange.