Range#
Range.extractContents()#
Metoda extractContents()
usuwa z drzewa węzłów całą zawartość danego zakresu i zwraca do niej referencję w postaci nowego fragmentu dokumentu.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var extract_contents = range.extractContents();
gdzie poszczególne człony oznaczają:
- extract_contents - nowy fragment dokumentu z usuniętą zawartością zakresu
- range - zakres będący obiektem kontekstu.
Algorytm wywołania metody extractContents()
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Zwróć wynik wyciągania zawartości w obiekcie kontekstu.
W ujęciu całościowym powyższy algorytm nie należy do najkrótszych i najłatwiejszych. Chodzi głównie o to, by prawidłowo wydobyć węzły częściowo zawarte, tak aby otrzymany wynik tworzył poprawną strukturę drzewa węzłów. W przeciwieństwie do metody Range.cloneContents()
, tutaj część węzłów jest całkowicie przenoszona w nowe miejsce, a tylko niektóre węzły zostają skopiowane. Teoretyczny opis tego procesu omówiłem w podstawach zakresów.
Wyciągnięta zawartość zakresu (węzeł typu DocumentFragment
) zwracana przez metodę extractContents()
nie jest częścią drzewa dokumentu dopóki nie zostanie dodana do innego węzła należącego do drzewa dokumentu. Dlatego wyciągnięta zawartość nie będzie posiadała rodzica (wartość null
), aczkolwiek dalej posiada jakiegoś właściciela.
Po wyciągnięciu zawartości zakresu metodą extractContents()
nastąpi automatyczne skorygowanie jego punktów granicznych (zakres zawsze zostanie zwinięty), tak żeby wszystko pasowało do nowej sytuacji.
Skopiowanie zawartości zakresu (bez usuwania z drzewa węzłów) można wykonać metodą Range.cloneContents()
. Do całkowitego usunięcia zawartości zakresu z drzewa węzłów (bez zwracania jakiejkolwiek referencji) służy metoda Range.deleteContents()
.
Prosty przykład:
<script>
var box = document.createElement("div");
box.innerHTML = "Pierwszy węzeł tekstowy. "
+ "<p>Drugi węzeł tekstowy (dodatkowo w akapicie).</p>"
+ " Trzeci węzeł tekstowy.";
document.write(box.childNodes.length); // 3
document.write("<br>");
document.write(box.textContent); // Pierwszy węzeł tekstowy. Drugi węzeł tekstowy (dodatkowo w akapicie). Trzeci węzeł tekstowy.
document.write("<br><br>");
// Tworzymy nowy zakres
var range = document.createRange();
// Ustawiamy zakres między różnymi danymi w węzłach tekstowych kontenera DIV
range.setStart(box.childNodes[0], 5);
range.setEnd(box.childNodes[2], box.childNodes[2].length - 5);
document.write(range.startContainer); // [object Text]
document.write("<br>");
document.write(range.startOffset); // 5
document.write("<br>");
document.write(range.endContainer); // [object Text]
document.write("<br>");
document.write(range.endOffset); // 18
document.write("<br>");
document.write(range); // szy węzeł tekstowy. Drugi węzeł tekstowy (dodatkowo w akapicie). Trzeci węzeł teks
document.write("<br><br>");
// Wyciągamy zawartość zakresu
var extract = range.extractContents();
document.write(extract); // [object DocumentFragment]
document.write("<br>");
document.write(extract.childNodes.length); // 3
document.write("<br>");
document.write(extract.textContent); // szy węzeł tekstowy. Drugi węzeł tekstowy (dodatkowo w akapicie). Trzeci węzeł teks
document.write("<br><br>");
document.write(box.childNodes.length); // 2
document.write("<br>");
document.write(box.textContent); // Pierwtowy.
document.write("<br><br>");
document.write(range.startContainer); // [object HTMLDivElement]
document.write("<br>");
document.write(range.startOffset); // 1
document.write("<br>");
document.write(range.endContainer); // [object HTMLDivElement]
document.write("<br>");
document.write(range.endOffset); // 1
document.write("<br>");
document.write(range.collapsed); // true - zakres zwinięty
</script>
Kolejny prosty przykład:
<!DOCTYPE html>
<html>
<head>
<script>
function extract(){
var info = document.getElementById("info");
var box = document.getElementById("box");
// Tworzymy nowy zakres i ustawiamy na pierwszy element w DIV
var range = document.createRange();
range.selectNode(box.firstElementChild);
// Wyciągamy zawartość zakresu
var extractNode = range.extractContents();
// Wstawiamy węzeł 'extractNode' do kontenera DIV
box.appendChild(extractNode);
var result = "range.startContainer: " + range.startContainer
+ "<br>" + "range.startOffset: " + range.startOffset
+ "<br><br>" + "range.endContainer: " + range.endContainer
+ "<br>" + "range.endOffset: " + range.endOffset
+ "<br><br>" + "range: " + range;
info.innerHTML = result;
}
</script>
</head>
<body>
<div id="box" style="background-color:#e0a0b0">
<p>Pierwszy akapit P1 w kontenerze DIV.</p>
<p>Drugi akapit P2 w kontenerze DIV.</p>
</div>
<p>Kliknij przycisk by przenieść pierwszy element za ostatni element w DIV za pomocą zakresu.</p>
<input type="button" value="extractContents()" onclick="extract()">
<p style="color: blue;">Szczegółowe informacje dla zakresu:</p>
<p id="info"></p>
</body>
</html>
Składnia Web IDL#
interface Range { [NewObject] DocumentFragment extractContents(); }