Start · Sprachen · JavaScript · Referenz · Range.compareNode()

Range.compareNode()

Methode

Gibt eine Konstante zurück, die angibt, ob ein Knoten vor, nach, um oder vollständig innerhalb eines <code>Range</code> liegt. Veraltet und nicht standardisiert.

seit JavaScript Veraltet und nicht standardisiert (frühere Mozilla deprecated seit ja Kategorie: webapi

Signatur

Range.prototype.compareNode(referenceNode)

Beschreibung

compareNode() vergleicht die Lage eines DOM-Knotens mit den Grenzpunkten eines Range. Das Ergebnis ist eine von vier Zahlenkonstanten. Sie sagen aus, ob der Knoten vor dem Anfang des Bereichs beginnt, hinter seinem Ende aufhört, den Bereich ganz umschließt oder vollständig in ihm liegt.

  • 0 – NODE_BEFORE: Der Knoten beginnt vor dem Anfang des Range.
  • 1 – NODE_AFTER: Der Knoten endet hinter dem Ende des Range.
  • 2 – NODE_BEFORE_AND_AFTER: Der Knoten beginnt vorher und endet nachher, umschließt den Range also.
  • 3 – NODE_INSIDE: Der Knoten liegt vollständig innerhalb des Range.

Die Methode war eine proprietäre Erweiterung (zuerst in Gecko, später in WebKit/Blink) und gehört nicht zum DOM-Standard. Firefox hat sie schon früh entfernt, Chromium ebenfalls. Nutzen Sie sie deshalb in neuem Code nicht. Die standardisierten Ersatz-Methoden sind Range.prototype.compareBoundaryPoints(), Range.prototype.comparePoint() und Range.prototype.intersectsNode().

Gebraucht wird so ein Vergleich vor allem in Editoren und bei der Auswertung einer Textauswahl, etwa wenn man herausfinden will, welche Absätze eine Auswahl ganz oder nur teilweise erfasst. Weiter unten steht ein standardkonformer Nachbau, der dieselben Werte liefert.

Parameter

Name Typ Default Beschreibung
$referenceNode Pflicht Node Der Knoten, der mit dem Range verglichen wird. Er braucht einen Elternknoten, sonst wird ein Fehler geworfen.

Rückgabewert

Typ
number
Beschreibung
Eine der Konstanten 0 (NODE_BEFORE), 1 (NODE_AFTER), 2 (NODE_BEFORE_AND_AFTER) oder 3 (NODE_INSIDE).

Beispiele

Standardkonformer Nachbau mit compareBoundaryPoints()

// Liefert dieselben Werte wie das veraltete compareNode()
const NODE_BEFORE = 0;
const NODE_AFTER = 1;
const NODE_BEFORE_AND_AFTER = 2;
const NODE_INSIDE = 3;

const compareNode = (range, node) => {
  const nodeRange = document.createRange();
  nodeRange.selectNode(node); // wirft einen Fehler, wenn node keinen Elternknoten hat

  // 1 = Range-Anfang liegt hinter dem Knotenanfang, der Knoten beginnt also vorher
  const startsBefore = range.compareBoundaryPoints(Range.START_TO_START, nodeRange) === 1;
  // -1 = Range-Ende liegt vor dem Knotenende, der Knoten endet also nachher
  const endsAfter = range.compareBoundaryPoints(Range.END_TO_END, nodeRange) === -1;

  if (startsBefore && endsAfter) return NODE_BEFORE_AND_AFTER;
  if (startsBefore) return NODE_BEFORE;
  if (endsAfter) return NODE_AFTER;
  return NODE_INSIDE;
};

document.body.innerHTML = '<p id="a">Eins</p><p id="b">Zwei</p><p id="c">Drei</p>';
const range = document.createRange();
range.setStartBefore(document.getElementById('b'));
range.setEndAfter(document.getElementById('b'));

console.log(compareNode(range, document.getElementById('b')));
console.log(compareNode(range, document.body));
3 2

Absätze finden, die vollständig in der Auswahl liegen

// Nutzt die Funktion compareNode aus dem ersten Beispiel
const getFullySelectedParagraphs = () => {
  const selection = window.getSelection();
  if (!selection || selection.rangeCount === 0) return [];
  const range = selection.getRangeAt(0);

  return [...document.querySelectorAll('p')]
    .filter((p) => range.intersectsNode(p)) // Knoten ohne Überschneidung aussortieren
    .filter((p) => compareNode(range, p) === 3); // nur vollständig enthaltene behalten
};

document.addEventListener('mouseup', () => {
  const paragraphs = getFullySelectedParagraphs();
  console.log(`${paragraphs.length} Absatz/Absätze vollständig markiert`);
});
z. B. "2 Absatz/Absätze vollständig markiert"

Funktionsprüfung mit Rückfall auf den Nachbau

const range = document.createRange();
range.selectNodeContents(document.body);
const node = document.body.firstElementChild ?? document.body;

// Die native Methode nur verwenden, wenn der Browser sie noch hat
const result = typeof range.compareNode === 'function'
  ? range.compareNode(node)
  : compareNode(range, node); // Nachbau aus dem ersten Beispiel

console.log(result);
3

// Wichtig · Fallstricke

Veraltet und nicht standardisiert: compareNode() steht nicht in der DOM-Spezifikation. Firefox hat die Methode schon vor langer Zeit entfernt, und in Chromium-Browsern gibt es sie ebenfalls nicht mehr. Ob ältere Safari-Versionen sie noch anbieten, ist unsicher. Verwenden Sie daher compareBoundaryPoints(), comparePoint() oder intersectsNode().

  • Doppeldeutige Werte: NODE_BEFORE (0) bedeutet nicht zwingend, dass der Knoten ganz vor dem Range liegt. Er kann sich auch nur teilweise mit ihm überschneiden. Ob es überhaupt eine Überschneidung gibt, prüfen Sie zusätzlich mit intersectsNode().
  • Knoten ohne Elternknoten: Hat der Knoten keinen Elternknoten (zum Beispiel ein abgetrenntes Element oder document), löst das einen Fehler aus. Das gilt auch für den Nachbau über selectNode().
  • Konstanten: Range.NODE_BEFORE und die anderen Konstanten sind in modernen Browsern meist undefined. Definieren Sie die Zahlenwerte deshalb selbst, wie in den Beispielen.
  • Wenn Sie große Mengen von Knoten vergleichen, erzeugen Sie für jeden einen eigenen Range. Das kostet Zeit. Filtern Sie deshalb vorher mit intersectsNode().