Start · Sprachen · JavaScript · Referenz · Selection.focusNode

Selection.focusNode

Eigenschaft

Schreibgeschützte Eigenschaft, die den Knoten (<code>Node</code>) liefert, in dem die aktuelle Auswahl endet – also dort, wo der Nutzer das Markieren beendet hat.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

Selection.focusNode

Beschreibung

Selection.focusNode gibt den Knoten zurück, in dem der Fokus der Auswahl liegt. Der Fokus ist das Ende, das beim Markieren „bewegt“ wird. Das Gegenstück ist der Anker (anchorNode), also der Punkt, an dem das Markieren begonnen hat. Zusammen mit focusOffset lässt sich die Endposition genau bestimmen.

Wichtig: Der Fokus liegt nicht zwingend hinter dem Anker im Dokument. Wer von rechts nach links oder von unten nach oben markiert, erzeugt eine „rückwärts“ gerichtete Auswahl. Dann steht focusNode im Dokument vor anchorNode. Wenn du die Auswahl unabhängig von der Richtung brauchst, nimm getRangeAt(0) und dort startContainer bzw. endContainer.

Meist ist focusNode ein Textknoten (Text). Dann zählt focusOffset Zeichen. Ist es ein Elementknoten, zählt focusOffset Kindknoten. Gibt es keine Auswahl (rangeCount === 0), ist der Wert null.

Typische Einsatzfälle sind Editoren mit contenteditable, Werkzeugleisten für markierten Text, die Richtung einer Auswahl erkennen oder die Cursorposition merken und später wiederherstellen.

Rückgabewert

Typ
Node | null
Beschreibung
Der Knoten, in dem die Auswahl endet (oft ein Text-Knoten), oder null, wenn es keine Auswahl gibt.

Beispiele

Anfang und Ende der Auswahl ausgeben

document.addEventListener('selectionchange', () => {
  const sel = document.getSelection();
  if (!sel || !sel.focusNode) return;
  console.log('Anker:', sel.anchorNode.nodeName, sel.anchorOffset);
  console.log('Fokus:', sel.focusNode.nodeName, sel.focusOffset);
});
Anker: #text 3 Fokus: #text 17

Auswahlrichtung erkennen (vorwärts/rückwärts)

const isBackward = (sel) => {
  if (!sel.anchorNode || !sel.focusNode) return false;
  if (sel.anchorNode === sel.focusNode) {
    return sel.focusOffset < sel.anchorOffset;
  }
  const pos = sel.anchorNode.compareDocumentPosition(sel.focusNode);
  return Boolean(pos & Node.DOCUMENT_POSITION_PRECEDING);
};

document.addEventListener('mouseup', () => {
  const sel = window.getSelection();
  console.log(isBackward(sel) ? 'rückwärts markiert' : 'vorwärts markiert');
});
rückwärts markiert

Element am Cursor in einem contenteditable-Editor finden

const editor = document.querySelector('#editor');

const currentBlock = () => {
  const { focusNode } = document.getSelection();
  if (!focusNode || !editor.contains(focusNode)) return null;
  // Textknoten haben kein closest() – daher zum Elternelement wechseln
  const el = focusNode.nodeType === Node.TEXT_NODE ? focusNode.parentElement : focusNode;
  return el.closest('p, h1, h2, h3, li');
};

editor.addEventListener('keyup', () => {
  console.log('Cursor in:', currentBlock()?.tagName);
});
Cursor in: P

Auswahl bis zum Ende eines Absatzes erweitern

const sel = window.getSelection();
const para = document.querySelector('p');
if (sel.rangeCount > 0) {
  // extend() verschiebt nur den Fokus, der Anker bleibt
  sel.extend(para, para.childNodes.length);
  console.log(sel.focusNode === para, sel.focusOffset);
}
true 1

// Wichtig · Fallstricke

  • Richtung beachten: focusNode ist nicht unbedingt das Ende im Dokument. Wenn die Richtung egal sein soll, nutze getRangeAt(0).endContainer.
  • Offset-Bedeutung: Bei Textknoten zählt focusOffset Zeichen (UTF-16-Einheiten), bei Elementknoten zählt es Kindknoten.
  • Textknoten: focusNode ist oft ein Text-Knoten. Methoden wie closest() oder classList gibt es dort nicht. Wechsle vorher über parentElement zum Element.
  • Formularfelder: In <input> und <textarea> zeigt focusNode nicht auf den Text im Feld. Dort nutzt du selectionStart/selectionEnd.
  • Shadow DOM: Liegt die Auswahl in einem Shadow Root, liefert document.getSelection() je nach Browser den Host-Knoten. Neuere Browser bieten dafür getComposedRanges() an.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Ohne Auswahl ist der Wert null, also vor dem Zugriff prüfen.