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

Range.extractContents()

Methode

Verschiebt den Inhalt eines <code>Range</code> aus dem Dokument in ein neues <code>DocumentFragment</code> und gibt dieses zurück.

seit JavaScript Baseline: alle Browser (DOM Level 2) Kategorie: webapi

Signatur

Range.prototype.extractContents()

Beschreibung

extractContents() entfernt alle Knoten, die innerhalb eines Range liegen, aus dem DOM und liefert sie gesammelt in einem DocumentFragment zurück. Das Ergebnis entspricht in etwa cloneContents() gefolgt von deleteContents(). Vollständig enthaltene Knoten werden aber tatsächlich verschoben und nicht kopiert. Sie behalten also ihre Identität und ihre per addEventListener registrierten Event-Listener.

Beginnt oder endet der Bereich mitten in einem Element, wird dieses Element geteilt: Das Fragment bekommt eine flache Kopie des Elternelements (ohne Event-Listener) mit dem ausgewählten Teil. Der Rest bleibt im Dokument. Textknoten werden an den Grenzen des Bereichs aufgeteilt. Danach ist der Range zusammengefallen (collapsed === true) und steht an der Stelle, an der der Inhalt entfernt wurde.

Typische Einsatzfälle sind Rich-Text-Editoren (markierten Text ausschneiden, in ein Element einwickeln oder woandershin verschieben), das Umsortieren von Knotenbereichen und das Aufteilen von Inhalten, etwa bei Seitenumbrüchen.

Rückgabewert

Typ
DocumentFragment
Beschreibung
Ein neues DocumentFragment mit den entfernten Knoten. Ist der Range bereits zusammengefallen, ist das Fragment leer.

Beispiele

Einen Knotenbereich in ein anderes Element verschieben

// HTML: <ul id="quelle"><li>A</li><li>B</li><li>C</li></ul><ul id="ziel"></ul>
const quelle = document.getElementById('quelle');
const ziel = document.getElementById('ziel');

const range = document.createRange();
range.setStart(quelle, 1); // vor <li>B</li>
range.setEnd(quelle, 3);   // nach <li>C</li>

const fragment = range.extractContents();
ziel.append(fragment);

console.log(quelle.children.length, ziel.children.length);
console.log(range.collapsed);
1 2 true

Markierten Text in <mark> einwickeln

// Wickelt die aktuelle Textauswahl in ein <mark>-Element ein
const markiereAuswahl = () => {
  const selection = window.getSelection();
  if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return;

  const range = selection.getRangeAt(0);
  const mark = document.createElement('mark');
  mark.append(range.extractContents());
  range.insertNode(mark);

  // Auswahl auf das neue Element setzen
  selection.removeAllRanges();
  const neu = document.createRange();
  neu.selectNodeContents(mark);
  selection.addRange(neu);
};

document.getElementById('btn-markieren').addEventListener('click', markiereAuswahl);

Teilweise ausgewählte Elemente werden geteilt

const p = document.createElement('p');
p.innerHTML = '<b>Hallo Welt</b> und mehr';

const text = p.firstChild.firstChild; // Textknoten "Hallo Welt"
const range = document.createRange();
range.setStart(text, 6);           // vor "Welt"
range.setEnd(p.lastChild, 4);      // nach " und"

const frag = range.extractContents();
const div = document.createElement('div');
div.append(frag);

console.log(div.innerHTML);
console.log(p.innerHTML);
<b>Welt</b> und <b>Hallo </b> mehr

// Wichtig · Fallstricke

  • Verschieben statt Kopieren: Vollständig enthaltene Knoten werden aus dem DOM entfernt. Referenzen darauf bleiben gültig, zeigen danach aber auf Knoten im Fragment. Sobald das Fragment eingefügt wird, ist es leer.
  • Event-Listener: Vollständig verschobene Knoten behalten ihre Listener. Die Kopien teilweise ausgewählter Elternelemente sind flache Klone und haben keine Listener.
  • Doctype: Liegt ein DocumentType-Knoten im Bereich, wird ein HierarchyRequestError (DOMException) ausgelöst.
  • IDs: Wird ein Element geteilt, taucht sein id-Attribut sowohl im Dokument als auch im Fragment auf. Nach dem Wiedereinfügen gibt es also doppelte IDs.
  • Undo: Direkte DOM-Änderungen landen nicht im Rückgängig-Verlauf des Browsers, anders als document.execCommand in contenteditable.
  • Wird von allen modernen Browsern unterstützt. Für eine reine Kopie ohne Änderung am DOM nimmt man cloneContents().