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

Selection.getRangeAt()

Methode

Gibt das <code>Range</code>-Objekt am angegebenen Index der aktuellen Auswahl zurück, meist den ersten und einzigen ausgewählten Bereich mit <code>getRangeAt(0)</code>.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

Selection.prototype.getRangeAt(index)

Beschreibung

getRangeAt() liefert einen der Bereiche (Range), aus denen eine Auswahl (Selection) besteht. Die Auswahl bekommt man über window.getSelection() oder document.getSelection(). Das zurückgegebene Range-Objekt gibt Start- und Endpunkt der Auswahl im DOM genau an. Damit lässt sich markierter Text auslesen, umschließen, löschen oder ausmessen.

In der Praxis ruft man fast immer getRangeAt(0) auf. Nur Firefox unterstützt mehrere gleichzeitige Bereiche, etwa durch Strg-Klick oder die Auswahl von Tabellenzellen. Chromium und WebKit kennen höchstens einen Bereich. Ob überhaupt ein Bereich vorhanden ist, zeigt selection.rangeCount. Das sollte man vor dem Aufruf prüfen.

Typische Einsatzfälle:

  • Rich-Text-Editoren mit contenteditable, zum Beispiel um markierten Text fett zu setzen oder hervorzuheben
  • Kontextmenüs oder Tooltips an der Position der Auswahl anzeigen (range.getBoundingClientRect())
  • Die Cursorposition merken und später wiederherstellen

Das zurückgegebene Objekt ist eine Referenz auf den aktiven Bereich. Wer es verändert (setStart(), collapse() usw.), ändert je nach Browser direkt die sichtbare Auswahl. Wer den Zustand dauerhaft speichern will, nimmt eine Kopie mit range.cloneRange().

Parameter

Name Typ Default Beschreibung
$index Pflicht number Nullbasierter Index des gewünschten Bereichs. Er muss zwischen 0 und selection.rangeCount - 1 liegen, sonst wird ein IndexSizeError geworfen.

Rückgabewert

Typ
Range
Beschreibung
Das Range-Objekt am angegebenen Index. Es verweist auf den aktiven Auswahlbereich und ist keine Kopie.

Beispiele

Markierten Text und Container auslesen

document.addEventListener('mouseup', () => {
  const selection = window.getSelection();
  // Ohne Bereich würde getRangeAt(0) einen Fehler werfen
  if (selection.rangeCount === 0 || selection.isCollapsed) return;

  const range = selection.getRangeAt(0);
  console.log('Text:', range.toString());
  console.log('Start-Offset:', range.startOffset);
  console.log('Gemeinsamer Container:', range.commonAncestorContainer.nodeName);
});
Text: Hallo Welt Start-Offset: 6 Gemeinsamer Container: #text

Auswahl mit <mark> hervorheben

const highlightSelection = () => {
  const selection = window.getSelection();
  if (!selection.rangeCount) return;

  const range = selection.getRangeAt(0);
  const mark = document.createElement('mark');
  try {
    // Klappt nur, wenn die Auswahl keine Elementgrenzen halb schneidet
    range.surroundContents(mark);
  } catch {
    // Rückfall: Inhalt herauslösen und eingepackt wieder einfügen
    mark.appendChild(range.extractContents());
    range.insertNode(mark);
  }
  selection.removeAllRanges();
};

document.querySelector('#highlight-btn').addEventListener('click', highlightSelection);

Tooltip an der Auswahl positionieren

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

document.addEventListener('selectionchange', () => {
  const sel = document.getSelection();
  if (!sel.rangeCount || sel.isCollapsed) {
    tooltip.hidden = true;
    return;
  }
  const rect = sel.getRangeAt(0).getBoundingClientRect();
  tooltip.style.top = `${rect.top + window.scrollY - 40}px`;
  tooltip.style.left = `${rect.left + window.scrollX + rect.width / 2}px`;
  tooltip.hidden = false;
});

Cursorposition in contenteditable sichern und wiederherstellen

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

editor.addEventListener('blur', () => {
  const sel = window.getSelection();
  if (sel.rangeCount) {
    // Kopie anlegen, weil die Referenz sonst mitverändert wird
    savedRange = sel.getRangeAt(0).cloneRange();
  }
});

const restoreCursor = () => {
  if (!savedRange) return;
  editor.focus();
  const sel = window.getSelection();
  sel.removeAllRanges();
  sel.addRange(savedRange);
};

// Wichtig · Fallstricke

  • IndexSizeError: Ist rangeCount gleich 0, etwa wenn noch nie geklickt wurde oder nach removeAllRanges(), wirft getRangeAt(0) eine DOMException. Prüfe deshalb immer vorher selection.rangeCount > 0.
  • Mehrere Bereiche: Nur Firefox unterstützt mehrere Bereiche. In Chrome, Edge und Safari ist rangeCount höchstens 1. Code, der auf mehrere Bereiche angewiesen ist, funktioniert dort also nicht.
  • Referenz statt Kopie: Änderungen am zurückgegebenen Range können die sichtbare Auswahl direkt verändern. Zum Speichern ist cloneRange() nötig.
  • Formularfelder: Bei Auswahlen in <input> und <textarea> liefert der Bereich nicht den ausgewählten Text innerhalb des Feldes. Dafür gibt es selectionStart und selectionEnd des Elements.
  • Shadow DOM: Auswahlen in Shadow Roots sind je nach Browser nicht vollständig sichtbar. Neuere Browser bieten dafür Selection.getComposedRanges().
  • Einfügen von HTML: Wer aus Nutzereingaben HTML baut und per range.insertNode() einfügt, sollte die Eingaben bereinigen, sonst droht XSS.