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

Range.setStart()

Methode

Setzt die Startposition eines <code>Range</code> auf einen Knoten und einen Offset innerhalb dieses Knotens.

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

Signatur

Range.prototype.setStart(startNode, startOffset)

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());
schöne

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);
1 2

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

// Wichtig · Fallstricke

  • Ausnahmen: Ist startOffset größer als die Knotenlänge (Zeichenanzahl bzw. childNodes.length) oder negativ, wird eine IndexSizeError-DOMException ausgelöst. Bei einem DocumentType-Knoten gibt es einen InvalidNodeTypeError.
  • Offset-Falle: Bei Elementen zählen alle Kindknoten, also auch Leerzeichen-Textknoten aus der HTML-Formatierung. Verwende childNodes, nicht children, 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() und setStartAfter() 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.