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
Document
iDocumentFragment
: Wartością
null
.- Dla
Element
: Węzłem node.
- Dla
Text
,Comment
iProcessingInstruction
: 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ą
null
lub 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
Element
z:- 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); };