Signatur
Beschreibung
cloneRange() legt eine Kopie eines Range-Objekts an. Der neue Range hat dieselben Begrenzungspunkte (startContainer, startOffset, endContainer, endOffset) wie das Original. Danach sind beide Objekte völlig unabhängig: Wer den Klon mit setStart(), setEnd() oder collapse() verändert, lässt das Original unberührt – und umgekehrt.
Wichtig: Kopiert wird nur der Bereich, nicht der Inhalt. Die DOM-Knoten selbst werden nicht dupliziert. Willst du den Inhalt kopieren, nimm Range.prototype.cloneContents().
Typische Einsatzfälle sind das Sichern einer Benutzerauswahl (Selection.getRangeAt()) vor Änderungen am DOM, Messungen an Teilbereichen (etwa die Cursor-Position in einem contenteditable-Element) sowie Operationen, die einen Range ändern würden, bei denen das Original aber erhalten bleiben soll.
Rückgabewert
Range-Objekt mit identischen Begrenzungspunkten, unabhängig vom Original.Beispiele
Range klonen und unabhängig verändern
const p = document.createElement('p');
p.textContent = 'Hallo Welt';
document.body.append(p);
const range = document.createRange();
range.selectNodeContents(p);
const kopie = range.cloneRange();
kopie.collapse(true); // nur der Klon wird auf den Anfang reduziert
console.log(range.toString());
console.log(kopie.toString());
console.log(range === kopie);
Benutzerauswahl sichern und wiederherstellen
let gespeichert = null;
const auswahlSichern = () => {
const sel = window.getSelection();
if (sel.rangeCount > 0) {
// Kopie anlegen, damit spätere Änderungen der Auswahl sie nicht beeinflussen
gespeichert = sel.getRangeAt(0).cloneRange();
}
};
const auswahlWiederherstellen = () => {
if (!gespeichert) return;
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(gespeichert);
};
document.querySelector('#editor')?.addEventListener('blur', auswahlSichern);
document.querySelector('#fett-button')?.addEventListener('mousedown', (e) => {
e.preventDefault();
auswahlWiederherstellen();
});
Cursor-Position in contenteditable ermitteln
const cursorOffset = (editor) => {
const sel = window.getSelection();
if (!sel.rangeCount) return 0;
const range = sel.getRangeAt(0);
const vorher = range.cloneRange();
vorher.selectNodeContents(editor);
vorher.setEnd(range.endContainer, range.endOffset);
return vorher.toString().length; // Anzahl Zeichen vor dem Cursor
};
const editor = document.querySelector('[contenteditable]');
editor?.addEventListener('keyup', () => {
console.log('Cursor bei Zeichen', cursorOffset(editor));
});
// Wichtig · Fallstricke
- Nicht mit
cloneContents()verwechseln:cloneRange()kopiert nur die Begrenzungspunkte, keine DOM-Knoten. - Die Kopie ist ein „Live“-Range: Ändert sich das DOM (z. B. werden Knoten entfernt), passt der Browser ihre Begrenzungspunkte genauso automatisch an wie beim Original. Ein gesicherter Range kann nach umfangreichen DOM-Änderungen also auf eine andere Stelle zeigen als erwartet.
Selection.getRangeAt()liefert in manchen Browsern eine Referenz auf den internen Range der Auswahl. OhnecloneRange()kann sich ein gespeicherter Range deshalb unerwartet mitändern.- Wird nur auf
Rangeangeboten, nicht aufStaticRange. Wird von allen modernen Browsern unterstützt.