Range (rozszerzenie)#
Range.createContextualFragment()#
Metoda createContextualFragment() pozwala sparsować przekazany łańcuch znakowy i zwrócić wynik 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 new_fragment = range.createContextualFragment(text);gdzie poszczególne człony oznaczają:
- new_fragment - nowy fragment dokumentu ze sparsowanym łańcuchem znakowym.
- range - zakres będący obiektem kontekstu.
- text - łańcuch znakowy reprezentujący dodawaną strukturę znacznikową do zwracanego fragmentu dokumentu, np. "
<p>Jakiś nowy tekst.</p>".
Algorytm wywołania metody createContextualFragment(text) nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
Niech node będzie węzłem początkowym w obiekcie kontekstu.
Niech context będzie następujący, w zależności od interfejsu node:
- Dla
DocumentiDocumentFragment: Wartością
null.- Dla
Element: Węzłem node.
- Dla
Text,CommentiProcessingInstruction: Rodzicem elementowym dla node.
- Dla
DocumentType: DOM4 zapobiega takiej ewentualności (algorytm ustawiania początku lub końca w zakresie musi zrzucić wyjątek
"InvalidNodeTypeError").
- Dla
Jeśli context jest wartością
nulllub wszystkie poniższe warunki są prawdziwe:- Właścicielem dla context jest dokument HTML.
- Nazwą lokalną dla context jest "
html". - Przestrzenią nazw dla context jest przestrzeń nazw HTML.
niech context będzie nowym węzłem typu
Elementz:- Nazwą lokalną w postaci "
body". - Przestrzenią nazw będącą przestrzenią nazw HTML.
- Właścicielem będącym właścicielem w obiekcie kontekstu.
- Niech fragment będzie wynikiem działania algorytmu parsowania fragmentu z łańcuchem znakowym będącym text oraz z elementem kontekstu będącym context.
Dla każdego (for each) skryptu we fragment dezaktywuj flagi "parser-inserted" i "already started".
Krok ten ma być równoważny z nieustawianiem tych flag w pierwszej kolejności, aby zapewnić, że skrypty zostaną uruchomione dopiero wtedy, kiedy fragment będzie wstawiany do dokumentu.
- Zwróć fragment.
Metoda createContextualFragment() przydaje się w chwili, kiedy zależy nam na utworzeniu jakiegoś drzewa węzłów poza drzewem dokumentu. Na podstawie przekazanego tekstu przy wywołaniu metody otrzymamy obiekt typu DocumentFragment, którego zawartością będzie sparsowany tekst. Drzewo takie możemy dowolnie modyfikować za pomocą standardowych poleceń DOM, i dopiero na koniec wstawić do pewnej części aktywnego drzewa dokumentu lub do innego drzewa węzłów.
Za pomocą metody createContextualFragment() w połączeniu z innymi poleceniami wstawiającymi DOM można zasymulować działanie metody Element.insertAdjacentHTML().
Parsowanie danych tekstowych pochodzących od osób trzecich stwarza duże zagrożenie i jeśli nie jest niezbędne należy rozważyć alternatywne rozwiązania.
Prosty przykład:
<script>
var str1 = "<div>Teks w kontenerze DIV.</div>";
// Tworzymy nowy zakres
var range = document.createRange();
var new_fragment1 = range.createContextualFragment(str1);
document.write(new_fragment1); // [object DocumentFragment]
document.write("<br>");
document.write(new_fragment1.childNodes.length); // 1
document.write("<br>");
document.write(new_fragment1.childNodes[0]); // [object HTMLDivElement]
document.write("<br>");
document.write(new_fragment1.childNodes[0].textContent); // Teks w kontenerze DIV.
document.write("<br><br>");
var str2 = "<strong>Pogrubiony</strong> i <em>pochylony</em> tekst.";
// Zmieniamy początek zakresu
range.setStart(document.documentElement, 1);
var new_fragment2 = range.createContextualFragment(str2);
document.write(new_fragment2); // [object DocumentFragment]
document.write("<br>");
document.write(new_fragment2.childNodes.length); // 4
document.write("<br>");
document.write(new_fragment2.childNodes[2]); // [object HTMLElement]
document.write("<br>");
document.write(new_fragment2.childNodes[2].textContent); // pochylony.
document.write("<br><br>");
var newDoc = document.implementation.createHTMLDocument("");
document.write(newDoc.firstChild); // [object DocumentType]
try{
range.setStart(newDoc.firstChild, 0);
}
catch(e){
document.write("<br>" + "Próba ustawienia DocumentType na węzeł początkowy zakresu zrzuca błąd:" + "<br>");
document.write(e); // Wyjątek typu "InvalidNodeTypeError"
}
</script>Kolejny prosty przykład:
<!DOCTYPE html>
<html>
<head>
<script>
var num = 0;
function insertHTML(context){
var box = document.getElementById("box"); // referencja do kontenera
var str = context.value;
var range = document.createRange();
var new_fragment = range.createContextualFragment(str);
box.appendChild(new_fragment);
}
</script>
</head>
<body>
<div id="box" style="width:300px; background-color:#e0a0b0;">Kontener będący docelowym elementem.</div>
<p>Kliknij konkretny przycisk by wstawić nową sparsowaną zawartość na końcu kontenera DIV.</p>
<input type="button" value="<p>Nowy akapit z <strong>pogrubieniem</strong> i <em>pochyleniem</em>.</p>" onclick="insertHTML(this)">
<input type="button" value="<strong> pogrubienie </strong>" onclick="insertHTML(this)">
<input type="button" value="<em> pochylenie </em>" onclick="insertHTML(this)">
</body>
</html>Metoda createContextualFragment() była (i do tej pory jest) rzadko stosowana przez programistów, głównie ze względu na długotrwały brak standaryzacji i różnice w implementacjach. Obecnie jest obsługiwana przez wszystkie wiodące przeglądarki internetowe (w IE od wersji 10).
Składnia Web IDL#
partial interface Range { [NewObject] DocumentFragment createContextualFragment(DOMString fragment); };