Signatur
Beschreibung
Die Eigenschaft focusOffset gibt die Position des Fokus einer Auswahl innerhalb ihres focusNode an. Der Fokus ist das Ende der Auswahl, an dem der Nutzer das Markieren beendet hat, also dort, wo die Maus losgelassen wurde oder wohin die Umschalttaste mit Pfeiltasten die Auswahl erweitert hat. Das Gegenstück dazu ist der Anker (anchorNode/anchorOffset).
Wie der Wert zu lesen ist, hängt vom Knotentyp ab:
- Bei
Text-,Comment- undCDATASection-Knoten ist es die Anzahl der Zeichen (UTF-16-Codeeinheiten) vor dem Fokus. - Bei Elementknoten ist es die Anzahl der Kindknoten vor dem Fokus.
Typische Einsatzfälle sind eigene Editoren, Erwähnungs- oder Autovervollständigungs-Funktionen in contenteditable-Bereichen, das Ermitteln der Cursorposition und Werkzeugleisten, die sich nach der Laufrichtung der Auswahl richten. Bei einer eingeklappten Auswahl (einem einfachen Cursor) sind focusOffset und anchorOffset gleich.
Rückgabewert
rangeCount === 0) ist der Wert 0.Beispiele
Fokusposition beim Markieren ausgeben
document.addEventListener('selectionchange', () => {
const sel = document.getSelection();
if (!sel || sel.rangeCount === 0) return;
console.log('Fokus-Knoten:', sel.focusNode?.nodeName, 'Offset:', sel.focusOffset);
});
Laufrichtung der Auswahl bestimmen
const isBackward = (sel) => {
if (sel.isCollapsed) return false;
if (sel.anchorNode === sel.focusNode) {
return sel.focusOffset < sel.anchorOffset;
}
// DOCUMENT_POSITION_PRECEDING: Fokus liegt vor dem Anker
return Boolean(
sel.anchorNode.compareDocumentPosition(sel.focusNode) & Node.DOCUMENT_POSITION_PRECEDING
);
};
document.addEventListener('mouseup', () => {
const sel = window.getSelection();
console.log(isBackward(sel) ? 'rückwärts markiert' : 'vorwärts markiert');
});
Wort vor dem Cursor in contenteditable ermitteln (z. B. für @-Erwähnungen)
const editor = document.querySelector('[contenteditable]');
editor.addEventListener('input', () => {
const sel = window.getSelection();
const node = sel.focusNode;
if (!sel.isCollapsed || node?.nodeType !== Node.TEXT_NODE) return;
const textBefore = node.textContent.slice(0, sel.focusOffset);
const match = textBefore.match(/@(\w*)$/);
if (match) console.log('Erwähnung wird getippt:', match[1]);
});
Fokus gezielt setzen und auslesen
const p = document.createElement('p');
p.textContent = 'Hallo Welt';
document.body.append(p);
const sel = window.getSelection();
sel.setBaseAndExtent(p.firstChild, 0, p.firstChild, 5);
console.log(sel.focusOffset, sel.toString());
// Wichtig · Fallstricke
- Schreibgeschützt: Eine Zuweisung an
focusOffsethat keine Wirkung. Zum Verschieben des Fokus nutzt manSelection.extend(),setBaseAndExtent()odercollapse(). - Knotentyp prüfen: Ist
focusNodeein Element, ist der Wert ein Kindindex und keine Zeichenposition. EintextContent.slice(0, focusOffset)liefert dann ein falsches Ergebnis. - Fokus ist nicht immer das Ende: Markiert der Nutzer rückwärts, liegt der Fokus vor dem Anker. Für Start und Ende in Dokumentreihenfolge verwendet man besser
getRangeAt(0).startOffset/endOffset. - UTF-16: Der Offset zählt Codeeinheiten. Emojis und Zeichen außerhalb der BMP belegen daher 2 Einheiten.
- Formularfelder: In
<input>und<textarea>liefertfocusOffsetnicht die Cursorposition im Text. Dort sindselectionStart/selectionEndzu verwenden. - Shadow DOM: Liegt die Auswahl in einem Shadow Tree, geben viele Browser den Host als
focusNodezurück, und der Offset bezieht sich dann darauf.getComposedRanges()ist hier zuverlässiger, wird aber nicht überall unterstützt. - Die Eigenschaft wird von allen modernen Browsern unterstützt. Das Verhalten beim Markieren über Elementgrenzen hinweg kann sich zwischen den Browsern leicht unterscheiden.