Start · Sprachen · JavaScript · Referenz · NodeIterator.previousNode()

NodeIterator.previousNode()

Methode

Gibt den vorhergehenden Knoten der von einem <code>NodeIterator</code> dargestellten Menge zurück und bewegt den Iterator rückwärts. Gibt es keinen, liefert die Methode <code>null</code>.

seit JavaScript DOM Level 2 – Baseline: alle Browser Kategorie: webapi

Signatur

NodeIterator.prototype.previousNode()

Beschreibung

previousNode() ist das Gegenstück zu nextNode(). Die Methode geht in Dokumentreihenfolge rückwärts durch alle Knoten unterhalb von root, die zu whatToShow passen und vom Filter mit NodeFilter.FILTER_ACCEPT angenommen werden. Sie gibt den ersten solchen Knoten zurück und setzt den Iterator auf diese Position. Gibt es davor keinen passenden Knoten mehr, liefert sie null. Die Position bleibt dann unverändert.

Ein NodeIterator merkt sich seine Position über zwei Werte: den Referenzknoten (referenceNode) und die Angabe, ob der Zeiger vor oder hinter diesem Knoten steht (pointerBeforeReferenceNode). Steht der Zeiger hinter dem Referenzknoten, zum Beispiel direkt nach einem nextNode(), gibt previousNode() genau diesen Referenzknoten noch einmal zurück. Wer nextNode() und previousNode() abwechselnd aufruft, bekommt also immer wieder denselben Knoten.

Typische Einsatzfälle sind das rückwärtige Durchsuchen eines Teilbaums, etwa nach der letzten Überschrift vor einem Element oder nach dem vorhergehenden Textknoten, und Navigation mit Vor- und Zurück-Schritten in Editoren oder Barrierefreiheits-Werkzeugen. Anders als beim TreeWalker gibt es keine Bewegung zu Eltern- oder Geschwisterknoten. Der Iterator kennt nur die flache Liste in Dokumentreihenfolge.

Rückgabewert

Typ
Node | null
Beschreibung
Der vorhergehende angenommene Knoten, oder null, wenn es vor der aktuellen Position keinen passenden Knoten mehr gibt.

Beispiele

Liste zuerst vorwärts, dann rückwärts durchlaufen

const liste = document.createElement('ul');
liste.innerHTML = '<li>A</li><li>B</li><li>C</li>';

const it = document.createNodeIterator(liste, NodeFilter.SHOW_ELEMENT);

// Bis ans Ende vorspulen
while (it.nextNode()) {}

// Rückwärts ausgeben
let node;
while ((node = it.previousNode())) {
  console.log(node.nodeName, node.textContent);
}
LI C LI B LI A UL ABC

Fallstrick: previousNode() direkt nach nextNode()

const div = document.createElement('div');
div.innerHTML = '<p>Eins</p><p>Zwei</p>';

const it = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, (n) =>
  n.nodeName === 'P' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
);

console.log(it.previousNode());           // Zeiger steht am Anfang
console.log(it.nextNode().textContent);    // Eins
console.log(it.nextNode().textContent);    // Zwei
console.log(it.previousNode().textContent); // noch einmal Zwei!
console.log(it.previousNode().textContent); // Eins
null Eins Zwei Zwei Eins

Letzte Überschrift vor einem Element finden

document.body.innerHTML = `
  <h1>Einleitung</h1>
  <p>Text</p>
  <h2>Installation</h2>
  <p id="ziel">Hier stehen wir.</p>
`;

const vorherigeUeberschrift = (ziel) => {
  const it = document.createNodeIterator(
    document.body,
    NodeFilter.SHOW_ELEMENT,
    (n) => (/^H[1-6]$/.test(n.nodeName) || n === ziel)
      ? NodeFilter.FILTER_ACCEPT
      : NodeFilter.FILTER_SKIP
  );

  // Bis zum Zielelement vorlaufen
  let n;
  while ((n = it.nextNode()) && n !== ziel) {}
  if (!n) return null;

  it.previousNode();        // liefert zuerst das Ziel selbst
  return it.previousNode(); // danach die vorherige Überschrift
};

console.log(vorherigeUeberschrift(document.getElementById('ziel'))?.textContent);
Installation

// Wichtig · Fallstricke

  • Zeigerposition: Nach nextNode() gibt der erste Aufruf von previousNode() denselben Knoten zurück. Wer wirklich einen Schritt zurück will, muss previousNode() zweimal aufrufen.
  • Startposition: Ein frisch erzeugter Iterator steht vor root. Ein sofortiger Aufruf von previousNode() liefert deshalb null. root selbst gehört zur Menge, wenn er zu whatToShow und zum Filter passt.
  • FILTER_REJECT wirkt bei NodeIterator genauso wie FILTER_SKIP: Nur der Knoten selbst wird übergangen, seine Nachfahren nicht. Das ist anders als beim TreeWalker.
  • Fehler: Ruft der Filter während seiner Ausführung wieder denselben Iterator auf, wirft die Methode eine InvalidStateError-DOMException. Ausnahmen, die im Filter entstehen, werden an den Aufrufer weitergereicht.
  • Live-Verhalten: Der Iterator arbeitet auf dem echten DOM, nicht auf einer Momentaufnahme. Wird der Referenzknoten entfernt, verschiebt der Browser die Position automatisch.
  • Kompatibilität: Wird seit Langem von allen modernen Browsern unterstützt. detach() ist veraltet und tut nichts mehr.