Start · Sprachen · JavaScript · Referenz · Selection.setBaseAndExtent()

Selection.setBaseAndExtent()

Methode

Ersetzt die aktuelle Auswahl durch einen Bereich zwischen zwei Punkten (Anker und Fokus), einschließlich aller dazwischenliegenden Inhalte.

seit JavaScript Baseline: alle modernen Browser Kategorie: webapi

Signatur

Selection.prototype.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset)

Beschreibung

setBaseAndExtent() legt die Textauswahl des Dokuments in einem Schritt neu fest. Du übergibst zwei Randpunkte, jeweils als Knoten mit Offset: den Anker (Startpunkt der Auswahl) und den Fokus (Endpunkt, an dem der Cursor steht). Eine vorhandene Auswahl wird dabei vollständig ersetzt. Vorher removeAllRanges() aufzurufen ist nicht nötig.

Welche Bedeutung der Offset hat, hängt vom Knotentyp ab. Bei Textknoten (und Comment/CDATASection) zählt er die Zeichen, genauer gesagt UTF-16-Codeeinheiten. Bei Elementknoten zählt er die Kindknoten. setBaseAndExtent(p, 0, p, p.childNodes.length) wählt also den gesamten Inhalt von p aus.

Anders als bei Range und addRange() darf der Fokus im Dokument vor dem Anker liegen. Dann entsteht eine rückwärts gerichtete Auswahl, so als hätte man mit der Maus von rechts nach links gezogen. Das wirkt sich auf das Verhalten aus, wenn danach die Umschalttaste und eine Pfeiltaste gedrückt werden oder Selection.extend() aufgerufen wird. Die Methode eignet sich deshalb für Editoren, Funktionen zum Hervorheben von Suchtreffern, „Alles markieren“-Schaltflächen und für Tests, die Auswahlen simulieren.

Parameter

Name Typ Default Beschreibung
$anchorNode Pflicht Node Knoten, in dem die Auswahl beginnt (Anker).
$anchorOffset Pflicht number Position innerhalb von anchorNode: bei Textknoten die Zahl der Zeichen, bei Elementen die Zahl der Kindknoten vor dem Startpunkt.
$focusNode Pflicht Node Knoten, in dem die Auswahl endet (Fokus). Er darf im Dokument vor dem Anker liegen.
$focusOffset Pflicht number Position innerhalb von focusNode, gezählt wie bei anchorOffset.

Beispiele

Gesamten Inhalt eines Absatzes markieren

const p = document.querySelector('#intro');
const selection = window.getSelection();

// Offsets zählen hier Kindknoten, weil p ein Element ist
selection.setBaseAndExtent(p, 0, p, p.childNodes.length);

console.log(selection.toString());
Der vollständige Text des Absatzes #intro

Teil eines Textknotens auswählen

// <p id="satz">Hallo schöne Welt</p>
const text = document.querySelector('#satz').firstChild; // Textknoten
const sel = document.getSelection();

// Zeichen 6 bis 12 → "schöne"
sel.setBaseAndExtent(text, 6, text, 12);

console.log(sel.toString());
console.log(sel.anchorOffset, sel.focusOffset);
schöne 6 12

Rückwärts gerichtete Auswahl über zwei Elemente

// <p id="a">Erster Absatz</p><p id="b">Zweiter Absatz</p>
const a = document.querySelector('#a').firstChild;
const b = document.querySelector('#b').firstChild;
const sel = getSelection();

// Anker am Ende von #b, Fokus am Anfang von #a
sel.setBaseAndExtent(b, b.length, a, 0);

console.log(sel.direction ?? 'direction nicht unterstützt');
console.log(sel.getRangeAt(0).startContainer === a);
backward true

Suchtreffer markieren und in den sichtbaren Bereich scrollen

const markiereTreffer = (container, begriff) => {
  const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT);
  for (let node = walker.nextNode(); node; node = walker.nextNode()) {
    const index = node.data.indexOf(begriff);
    if (index !== -1) {
      getSelection().setBaseAndExtent(node, index, node, index + begriff.length);
      node.parentElement.scrollIntoView({ block: 'center' });
      return true;
    }
  }
  return false;
};

console.log(markiereTreffer(document.body, 'JavaScript'));
true (falls der Begriff gefunden wurde)

// Wichtig · Fallstricke

  • Ein Offset, der größer ist als die Länge des Knotens (Zeichen bzw. childNodes.length), löst eine IndexSizeError-DOMException aus.
  • Knoten, die zu einem anderen Dokument gehören, werden ignoriert. Knoten, die mit dem Dokument nicht verbunden sind, können je nach Browser zu einer leeren Auswahl führen.
  • Ein DocumentType-Knoten als Anker oder Fokus führt zu einem InvalidNodeTypeError.
  • Die Offsets zählen UTF-16-Codeeinheiten. Emojis und andere Zeichen außerhalb der BMP belegen jeweils zwei Einheiten. Wählst du nur eine davon aus, wird das Zeichen zerteilt.
  • Die Methode wirkt nicht auf den Text in <input>- oder <textarea>-Feldern. Dafür gibt es setSelectionRange().
  • Nach dem Aufruf wird asynchron das Ereignis selectionchange ausgelöst. Die Eigenschaft Selection.direction ist neuer und wird noch nicht von allen Browsern unterstützt. setBaseAndExtent() selbst funktioniert in allen modernen Browsern.
  • Innerhalb eines Shadow DOM verhalten sich Auswahlen je nach Browser unterschiedlich. Erwäge dort getComposedRanges().