Start · Sprachen · JavaScript · Referenz · Range.cloneRange()

Range.cloneRange()

Methode

Erzeugt ein neues, unabhängiges <code>Range</code>-Objekt mit denselben Start- und Endpunkten wie der ursprüngliche Range.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

Range.prototype.cloneRange()

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

Typ
Range
Beschreibung
Ein neues 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);
Hallo Welt false

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));
});
Cursor bei Zeichen 5

// 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. Ohne cloneRange() kann sich ein gespeicherter Range deshalb unerwartet mitändern.
  • Wird nur auf Range angeboten, nicht auf StaticRange. Wird von allen modernen Browsern unterstützt.