Signatur
Beschreibung
Die Eigenschaft selectionStart liefert den nullbasierten Index des ersten ausgewählten Zeichens in einem <textarea>. Ist nichts markiert, entspricht der Wert der aktuellen Cursorposition – dann sind selectionStart und selectionEnd gleich.
Die Eigenschaft ist beschreibbar: Wer einen neuen Wert zuweist, verschiebt den Anfang der Auswahl. Ist der neue Wert größer als selectionEnd, wird selectionEnd automatisch auf denselben Wert angehoben. Wenn Anfang und Ende zusammen gesetzt werden sollen, ist setSelectionRange() meist die bessere Wahl.
Typische Einsatzgebiete sind eigene Editor-Funktionen: Text an der Cursorposition einfügen, markierten Text mit Markdown- oder BBCode-Tags umschließen, Zeichen bis zum Cursor zählen oder die aktuelle Zeile bzw. Spalte ermitteln.
Rückgabewert
Beispiele
Cursorposition und Auswahl auslesen
const textarea = document.querySelector('#notiz');
textarea.addEventListener('select', () => {
const { selectionStart, selectionEnd, value } = textarea;
console.log(`Auswahl von ${selectionStart} bis ${selectionEnd}:`, value.slice(selectionStart, selectionEnd));
});
textarea.addEventListener('keyup', () => {
console.log('Cursor steht bei Index', textarea.selectionStart);
});
Text an der Cursorposition einfügen
const textarea = document.querySelector('#nachricht');
const insertAtCursor = (el, text) => {
const start = el.selectionStart;
const end = el.selectionEnd;
el.value = el.value.slice(0, start) + text + el.value.slice(end);
// Cursor hinter den eingefügten Text setzen
const pos = start + text.length;
el.setSelectionRange(pos, pos);
el.focus();
};
document.querySelector('#emoji-btn').addEventListener('click', () => {
insertAtCursor(textarea, '😊');
});
Markierten Text fett formatieren (Markdown)
const textarea = document.querySelector('#editor');
const wrapSelection = (el, before, after = before) => {
const { selectionStart: start, selectionEnd: end, value } = el;
const selected = value.slice(start, end);
el.setRangeText(before + selected + after, start, end, 'select');
el.focus();
};
document.querySelector('#bold-btn').addEventListener('click', () => {
wrapSelection(textarea, '**');
});
Aktuelle Zeile und Spalte berechnen
const textarea = document.querySelector('#code');
const status = document.querySelector('#status');
const updatePosition = () => {
const textBefore = textarea.value.slice(0, textarea.selectionStart);
const lines = textBefore.split('\n');
const line = lines.length;
const column = lines.at(-1).length + 1;
status.textContent = `Zeile ${line}, Spalte ${column}`;
};
['keyup', 'click', 'input'].forEach((evt) => textarea.addEventListener(evt, updatePosition));
// Wichtig · Fallstricke
- UTF-16-Einheiten: Der Index zählt UTF-16-Codeeinheiten, keine sichtbaren Zeichen. Emojis und andere Zeichen außerhalb der BMP zählen doppelt. Mit
value.slice()passt das zusammen, mit[...value]nicht. - Zeilenumbrüche: Im DOM-Wert steht ein Umbruch immer als
\nund zählt als ein Zeichen. Beim Absenden des Formulars wird daraus\r\n, die Indizes bleiben davon aber unberührt. - Richtung der Auswahl:
selectionStartist immer der kleinere Index, auch wenn rückwärts markiert wurde. Die Richtung steht inselectionDirection. valueneu setzen: Wervaluedirekt zuweist, schiebt den Cursor in den meisten Browsern ans Textende und leert den Rückgängig-Verlauf.setRangeText()ändert den Text gezielter,document.execCommand('insertText')ist zwar veraltet, erhält aber den Verlauf.- Fokus: Die Auswahl bleibt auch ohne Fokus gespeichert. Sichtbar hervorgehoben wird sie aber erst wieder, wenn das Element fokussiert ist.
- Kompatibilität: Wird von allen modernen Browsern unterstützt. Sehr alte IE-Versionen (vor IE 9) kannten die Eigenschaft nicht und brauchten
document.selection.