Start · Sprachen · JavaScript · Referenz · Range.commonAncestorContainer

Range.commonAncestorContainer

Eigenschaft

Schreibgeschützte Eigenschaft, die den tiefsten <code>Node</code> liefert, der sowohl den Start- als auch den Endpunkt eines <code>Range</code> enthält.

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

Signatur

Range.commonAncestorContainer

Beschreibung

Die schreibgeschützte Eigenschaft commonAncestorContainer eines Range-Objekts gibt den tiefsten gemeinsamen Vorfahren von startContainer und endContainer zurück. Das ist der am weitesten unten im Dokumentbaum liegende Knoten, der beide Grenzpunkte des Bereichs umschließt.

Liegen Start und Ende im selben Knoten, zum Beispiel beide im selben Textknoten, dann ist commonAncestorContainer genau dieser Knoten. Das Ergebnis kann also auch ein Text-Knoten sein und muss kein Element sein. Umfasst der Bereich dagegen mehrere Absätze, bekommt man meist ein Container-Element wie <div> oder <article>.

In der Praxis braucht man die Eigenschaft oft bei Texteditoren, Markierungs- und Annotationswerkzeugen sowie bei Kontextmenüs. Damit lässt sich prüfen, ob eine Benutzerauswahl innerhalb eines bestimmten Bereichs liegt (z. B. in einem contenteditable-Editor). Außerdem kann man den umgebenden Block ermitteln, um Formatierungen anzuwenden.

Der Wert wird jedes Mal neu berechnet, wenn sich die Grenzpunkte ändern, etwa durch setStart(), setEnd(), selectNode() oder durch Änderungen am DOM.

Rückgabewert

Typ
Node
Beschreibung
Der tiefste Node, der beide Grenzpunkte enthält. Das kann ein Element, ein Text-Knoten, ein DocumentFragment oder das Document selbst sein.

Beispiele

Gemeinsamen Vorfahren zweier Absätze ermitteln

// HTML: <article id="post"><p id="a">Erster Absatz</p><p id="b">Zweiter Absatz</p></article>
const range = document.createRange();
range.setStart(document.getElementById('a').firstChild, 3);
range.setEnd(document.getElementById('b').firstChild, 5);

console.log(range.commonAncestorContainer.id);
post

Start und Ende im selben Textknoten

const p = document.createElement('p');
p.textContent = 'Hallo Welt';
document.body.append(p);

const range = document.createRange();
range.setStart(p.firstChild, 0);
range.setEnd(p.firstChild, 5);

const ancestor = range.commonAncestorContainer;
console.log(ancestor.nodeType === Node.TEXT_NODE, ancestor.nodeName);
true "#text"

Prüfen, ob die Auswahl im Editor liegt

const editor = document.querySelector('[contenteditable]');

document.addEventListener('selectionchange', () => {
  const selection = document.getSelection();
  if (!selection || selection.rangeCount === 0) return;

  const ancestor = selection.getRangeAt(0).commonAncestorContainer;
  const insideEditor = editor.contains(ancestor);
  console.log(insideEditor ? 'Auswahl im Editor' : 'Auswahl außerhalb');
});
Auswahl im Editor

Nächstes umgebendes Element finden (Textknoten berücksichtigen)

const getAncestorElement = (range) => {
  const node = range.commonAncestorContainer;
  return node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
};

const range = document.getSelection()?.rangeCount
  ? document.getSelection().getRangeAt(0)
  : null;

if (range) {
  const block = getAncestorElement(range).closest('p, li, h1, h2, h3');
  console.log('Umgebender Block:', block?.tagName);
}
Umgebender Block: P

// Wichtig · Fallstricke

  • Häufiger Fehler: Textknoten. Das Ergebnis ist oft ein Text-Knoten. Der hat keine Methoden wie closest(), classList oder querySelector(). Prüfe deshalb vorher nodeType oder weiche auf parentElement aus.
  • Zugeklappter Bereich: Bei einem leeren Bereich (collapsed === true) ist der Wert einfach der startContainer.
  • Schreibgeschützt: Eine Zuweisung hat keine Wirkung, im Strict Mode wirft sie einen TypeError. Um den Bereich zu ändern, nutze setStart()/setEnd() oder selectNode().
  • Shadow DOM: Innerhalb von Shadow Roots liefert document.getSelection() je nach Browser Bereiche, die an der Shadow-Grenze angepasst sind. Der gemeinsame Vorfahre kann dann der Host statt des eigentlichen inneren Knotens sein. Für solche Fälle gibt es Selection.getComposedRanges(), das aber noch nicht überall unterstützt wird.
  • StaticRange (z. B. aus InputEvent.getTargetRanges()) hat keine Eigenschaft commonAncestorContainer.
  • Kompatibilität: Wird von allen modernen Browsern und seit dem Internet Explorer 9 unterstützt.