Start · Sprachen · JavaScript · Referenz · Selection

Selection

Schnittstelle

Ein <code>Selection</code>-Objekt steht für den Textbereich, den der Benutzer markiert hat, oder für die aktuelle Position des Cursors im Dokument.

seit JavaScript Baseline: alle modernen Browser Kategorie: webapi

Signatur

interface Selection

Beschreibung

Die Schnittstelle Selection steht für die aktuelle Markierung im Dokument. Ein Objekt dafür bekommt man über window.getSelection() oder document.getSelection(). Pro Dokument gibt es genau ein Selection-Objekt. Es ist „live“, ändert sich also, sobald der Benutzer oder ein Skript die Markierung ändert.

Eine Markierung hat einen Anker (anchorNode/anchorOffset, dort beginnt sie) und einen Fokus (focusNode/focusOffset, dort endet sie). Markiert der Benutzer von rechts nach links, liegt der Fokus vor dem Anker. Ist nichts markiert, fallen Anker und Fokus zusammen (isCollapsed === true). Dann beschreibt die Selection nur die Cursor-Position, zum Beispiel in einem contenteditable-Element. Der markierte Inhalt besteht aus einem oder mehreren Range-Objekten (rangeCount, getRangeAt()). Praktisch unterstützt aber nur Firefox mehrere Bereiche.

Typische Einsätze sind:

  • markierten Text auslesen (toString()), etwa für „Zitieren“- oder „Teilen“-Schaltflächen,
  • Text per Skript markieren (selectAllChildren(), setBaseAndExtent(), addRange()),
  • Rich-Text-Editoren bauen: Cursor setzen (collapse()), Markierung verschieben (modify()), markierten Inhalt löschen (deleteFromDocument()),
  • prüfen, ob ein Knoten markiert ist (containsNode()).

Wichtige Eigenschaften: anchorNode, anchorOffset, focusNode, focusOffset, isCollapsed, rangeCount, type ("None", "Caret" oder "Range") und direction. Wichtige Methoden: getRangeAt(), addRange(), removeRange(), removeAllRanges() bzw. empty(), collapse(), collapseToStart(), collapseToEnd(), extend(), setBaseAndExtent(), selectAllChildren(), containsNode(), deleteFromDocument(), modify() und toString(). Änderungen an der Markierung meldet das Event selectionchange auf document.

Rückgabewert

Typ
Selection
Beschreibung
Das Selection-Objekt bekommt man über window.getSelection() bzw. document.getSelection(). Wenn das Dokument keinen Browsing-Kontext hat (z. B. ein iframe mit display: none in Firefox), kann auch null zurückkommen.

Beispiele

Markierten Text auslesen und Selection-Zustand prüfen

document.addEventListener('mouseup', () => {
  const selection = window.getSelection();
  if (!selection || selection.isCollapsed) return; // nichts markiert

  console.log('Text:', selection.toString());
  console.log('Typ:', selection.type);
  console.log('Bereiche:', selection.rangeCount);
  console.log('Anker:', selection.anchorNode.nodeName, selection.anchorOffset);
  console.log('Fokus:', selection.focusNode.nodeName, selection.focusOffset);
});
Text: Hallo Welt Typ: Range Bereiche: 1 Anker: #text 0 Fokus: #text 10

Inhalt eines Elements per Skript markieren (z. B. Code-Block)

const selectCode = (element) => {
  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.selectAllChildren(element);
};

const pre = document.querySelector('pre');
pre.addEventListener('dblclick', () => {
  selectCode(pre);
  console.log('Markiert:', window.getSelection().toString().length, 'Zeichen');
});
Markiert: 128 Zeichen

Cursor in einem contenteditable-Element ans Ende setzen

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

const placeCaretAtEnd = (el) => {
  el.focus();
  const range = document.createRange();
  range.selectNodeContents(el);
  range.collapse(false); // false = ans Ende

  const selection = window.getSelection();
  selection.removeAllRanges();
  selection.addRange(range);
  console.log('Typ:', selection.type, '| collapsed:', selection.isCollapsed);
};

placeCaretAtEnd(editor);
Typ: Caret | collapsed: true

Auf Änderungen der Markierung reagieren (Zitieren-Button)

const quoteButton = document.querySelector('#quote');

const onSelectionChange = () => {
  const selection = document.getSelection();
  const text = selection?.toString().trim() ?? '';
  quoteButton.hidden = text.length === 0;
  quoteButton.dataset.quote = text;
};

document.addEventListener('selectionchange', onSelectionChange);

quoteButton.addEventListener('click', () => {
  console.log(`> ${quoteButton.dataset.quote}`);
  document.getSelection().removeAllRanges();
});
> Markierter Absatztext

// Wichtig · Fallstricke

  • Das Objekt ist live: getSelection() liefert immer dasselbe Objekt, und dessen Werte ändern sich laufend. Wenn du den Zustand festhalten willst, speichere toString() oder eine Kopie mit getRangeAt(0).cloneRange().
  • Formularfelder: Markierungen in <input> und <textarea> erscheinen je nach Browser nicht korrekt in Selection, und toString() ist dort oft leer. Nutze stattdessen selectionStart, selectionEnd und setSelectionRange() am Element.
  • Mehrere Bereiche: Nur Firefox unterstützt mehr als einen Range. Chrome und Safari übernehmen bei addRange() keinen zweiten Bereich, wenn schon einer existiert. Rufe deshalb vorher removeAllRanges() auf.
  • Fehler: getRangeAt(i) wirft einen IndexSizeError, wenn rangeCount 0 ist. Prüfe rangeCount also vorher.
  • Richtung: Wenn rückwärts markiert wurde, liegt anchorNode nach focusNode. Für Start und Ende in Dokumentreihenfolge nimm getRangeAt(0).startContainer bzw. endContainer.
  • Shadow DOM: Markierungen innerhalb von Shadow Roots sind nicht überall einheitlich erreichbar. Neuere Browser bieten dafür getComposedRanges() an, die Unterstützung ist aber noch lückenhaft.
  • Nicht standardisiert: modify() ist in keiner Spezifikation festgelegt, funktioniert aber in allen großen Browsern. direction ist neu und fehlt in älteren Browsern.
  • Performance: selectionchange feuert sehr oft, etwa bei jeder Cursorbewegung. Aufwendige Handler solltest du drosseln (Debounce).