Start · Sprachen · JavaScript · Referenz · CaretPosition.offsetNode

CaretPosition.offsetNode

Eigenschaft

Schreibgeschützte Eigenschaft, die den DOM-Knoten (meist ein <code>Text</code>-Knoten) liefert, in dem die über <code>caretPositionFromPoint()</code> ermittelte Cursorposition liegt.

seit JavaScript Baseline 2024 (Chrome 128+, Edge 128+, Firefox 20+ Kategorie: webapi

Signatur

CaretPosition.offsetNode

Beschreibung

Die schreibgeschützte Eigenschaft offsetNode eines CaretPosition-Objekts gibt den Node zurück, in dem die Einfügemarke (Caret) an einer bestimmten Bildschirmkoordinate liegen würde. Ein CaretPosition-Objekt bekommst du über document.caretPositionFromPoint(x, y).

Zusammen mit CaretPosition.offset beschreibt offsetNode eine exakte Position im Dokument: Ist offsetNode ein Text-Knoten, steht offset für den Zeichenindex innerhalb des Textes, bei einem Element dagegen für den Index des Kindknotens. So lässt sich zum Beispiel ermitteln, auf welches Wort geklickt wurde, wo ein per Drag & Drop gezogenes Element eingefügt werden soll oder wo eine eigene Textauswahl beginnen soll.

Typische Einsatzfälle sind eigene Editoren, „Wort unter dem Mauszeiger nachschlagen“, Annotationswerkzeuge und das Positionieren eines Range-Objekts mit range.setStart(pos.offsetNode, pos.offset).

Rückgabewert

Typ
Node
Beschreibung
Der Knoten, in dem die Cursorposition liegt – meist ein Text-Knoten, teils aber auch ein Element (z. B. ein <input> oder ein Container zwischen Kindknoten).

Beispiele

Geklicktes Wort ermitteln

document.addEventListener('click', (event) => {
  const pos = document.caretPositionFromPoint(event.clientX, event.clientY);
  if (!pos) return;

  const node = pos.offsetNode;
  if (node.nodeType !== Node.TEXT_NODE) return;

  const text = node.textContent;
  let start = pos.offset;
  let end = pos.offset;
  // Wortgrenzen links und rechts suchen
  while (start > 0 && /\S/.test(text[start - 1])) start--;
  while (end < text.length && /\S/.test(text[end])) end++;

  console.log('Geklicktes Wort:', text.slice(start, end));
});
Geklicktes Wort: Referenz

Browserübergreifend mit Fallback auf caretRangeFromPoint

const getCaretAt = (x, y) => {
  if (document.caretPositionFromPoint) {
    const pos = document.caretPositionFromPoint(x, y);
    return pos ? { node: pos.offsetNode, offset: pos.offset } : null;
  }
  // Ältere WebKit-/Blink-Versionen
  if (document.caretRangeFromPoint) {
    const range = document.caretRangeFromPoint(x, y);
    return range ? { node: range.startContainer, offset: range.startOffset } : null;
  }
  return null;
};

const caret = getCaretAt(100, 50);
console.log(caret?.node.nodeName, caret?.offset);
#text 12

Element an der Drop-Position in den Text einfügen

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

editor.addEventListener('dragover', (e) => e.preventDefault());

editor.addEventListener('drop', (e) => {
  e.preventDefault();
  const pos = document.caretPositionFromPoint(e.clientX, e.clientY);
  if (!pos || !editor.contains(pos.offsetNode)) return;

  const range = document.createRange();
  range.setStart(pos.offsetNode, pos.offset);
  range.collapse(true);

  const marker = document.createElement('mark');
  marker.textContent = e.dataTransfer.getData('text/plain');
  range.insertNode(marker);
});

// Wichtig · Fallstricke

  • Kompatibilität: caretPositionFromPoint() und damit offsetNode gibt es in Firefox schon lange, in Chromium erst ab Version 128 und in Safari ab 18.2. Für ältere Browser brauchst du den Fallback auf das nicht standardisierte document.caretRangeFromPoint().
  • caretPositionFromPoint() kann null liefern, z. B. wenn die Koordinaten außerhalb des Viewports liegen. Prüfe das immer, bevor du auf offsetNode zugreifst.
  • Der Knoten ist nicht immer ein Text-Knoten: Bei <input>/<textarea> wird meist das Formularelement selbst geliefert, und offset bezieht sich dann auf dessen value. Prüfe deshalb nodeType.
  • Knoten in Shadow DOM werden standardmäßig nicht offengelegt. Moderne Browser nehmen dafür ein Optionsobjekt { shadowRoots: [...] } als dritten Parameter an.
  • Die Koordinaten sind Viewport-Koordinaten (clientX/clientY), keine Seitenkoordinaten (pageX/pageY).