Signatur
Beschreibung
Die schreibgeschützte Eigenschaft startOffset gibt zusammen mit startContainer die genaue Startposition eines Bereichs im DOM an. AbstractRange ist die gemeinsame Basis von Range und StaticRange, deshalb steht die Eigenschaft bei beiden zur Verfügung.
Was der Wert bedeutet, hängt vom Knotentyp des startContainer ab:
- Bei Text-, Comment- und CDATASection-Knoten ist es die Anzahl der Zeichen, genauer der UTF-16-Codeeinheiten, vom Anfang des Knotens bis zum Startpunkt.
- Bei allen anderen Knoten, zum Beispiel
ElementoderDocument, ist es der Index des Kindknotens, vor dem der Bereich beginnt.0steht also für „vor dem ersten Kind“.
Typische Einsatzfälle sind Texteditoren, das Auswerten einer Benutzerauswahl (Selection.getRangeAt()), Hervorhebungen und Anmerkungen sowie die Auswertung von InputEvent.getTargetRanges(). Ändern lässt sich die Startposition nur bei einem Range, und zwar mit setStart() oder ähnlichen Methoden. Eine direkte Zuweisung an startOffset ist nicht möglich.
Rückgabewert
childNodes.Beispiele
Zeichen-Versatz in einem Textknoten
const p = document.createElement('p');
p.textContent = 'Hallo Welt';
document.body.append(p);
const range = document.createRange();
// Start nach "Hallo " im Textknoten
range.setStart(p.firstChild, 6);
range.setEnd(p.firstChild, 10);
console.log(range.startContainer.nodeName); // #text
console.log(range.startOffset);
console.log(range.toString());
Kindindex bei einem Element-Container
const ul = document.createElement('ul');
ul.innerHTML = '<li>A</li><li>B</li><li>C</li>';
const range = document.createRange();
// Bereich beginnt vor dem zweiten <li>
range.setStart(ul, 1);
range.setEnd(ul, 3);
console.log(range.startOffset);
console.log(ul.childNodes[range.startOffset].textContent);
Cursorposition aus der Benutzerauswahl lesen
document.addEventListener('selectionchange', () => {
const sel = document.getSelection();
if (!sel || sel.rangeCount === 0) return;
const { startContainer, startOffset } = sel.getRangeAt(0);
if (startContainer.nodeType === Node.TEXT_NODE) {
const vorher = startContainer.data.slice(0, startOffset);
console.log(`Cursor nach ${startOffset} Zeichen: "${vorher}"`);
}
});
StaticRange bei beforeinput auswerten
const editor = document.querySelector('[contenteditable]');
editor.addEventListener('beforeinput', (event) => {
for (const r of event.getTargetRanges()) {
// r ist ein StaticRange, erbt startOffset von AbstractRange
console.log(event.inputType, r.startOffset, r.endOffset);
}
});
// Wichtig · Fallstricke
- Die Bedeutung hängt vom Knotentyp ab: Prüfe immer den
nodeTypevonstartContainer, bevor dustartOffsetals Zeichenposition oder als Kindindex auswertest. - UTF-16: Bei Emojis und anderen Zeichen außerhalb der BMP zählt ein sichtbares Zeichen als zwei Einheiten. Der Versatz entspricht daher nicht unbedingt der Anzahl der sichtbaren Zeichen.
- Live oder statisch: Bei einem
Rangepasst der BrowserstartOffsetautomatisch an, wenn sich das DOM ändert. Bei einemStaticRangepassiert das nicht. Der Wert kann dann veraltet oder sogar größer als die Länge des Knotens sein. - Schreibgeschützt: Eine Zuweisung wird stillschweigend ignoriert, im Strict Mode löst sie einen
TypeErroraus. Verwende stattdessenRange.setStart(). - Kompatibilität:
startOffsetgibt es beiRangein allen Browsern schon seit Langem. Die gemeinsame BasisAbstractRangeundStaticRangestehen ungefähr seit Chrome 90, Firefox 69 und Safari 14.1 zur Verfügung.