Document#
Document.importNode()#
Metoda importNode()
importuje (na zasadzie kopiowania) przekazany węzeł z innego dokumentu do danego dokumentu i zwraca referencję do zaimportowanego węzła.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var imported = document.importNode(node [, deep = false
]);
gdzie poszczególne człony oznaczają:
- imported - referencja do zaimportowanego węzła (kopia).
- document - dokument będący obiektem kontekstu.
- node - referencja do importowanego węzła (oryginał).
deep - opcjonalny boolowski parametr determinujący rodzaj kopii:
true
- oznacza kopię głęboką (deep copy), gdzie kopiowany będzie węzeł ze wszystkimi jego dziećmi.false
- oznacza kopię płytką (shallow copy), gdzie kopiowany będzie jedynie węzeł, bez jego dzieci (nawet z wykluczeniem węzłów tekstowych). Jest to wartość domyślna i zostanie automatycznie przekazana w przypadku braku argumentu w wywołaniu metody lub w chwili, kiedy przekazany argument należy do jednej z wartości negatywnych (np. dlaundefined
czynull
).
Algorytm wywołania metody importNode(node, deep)
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
- Jeśli node jest węzłem typu
Document
lubShadowRoot
, to zrzuć wyjątek"NotSupportedError"
. - Zwróć wynik klonowania dla node, z obiektem kontekstu oraz, jeśli deep ma boolowską wartość
true
, z ustawieniem flagi klonowania dzieci.
Możliwość pominięcia argumentu dla metody importNode()
została wprowadzona dopiero w specyfikacji DOM4. Podobnie jest z domyślnym zachowaniem preferującym kopię płytką, która po kolejnej aktualizacji specyfikacji zastąpiła domyślną kopię głęboką (DOM - Bug 23565). Warto zaznaczyć, że dla elementów pustych (nie zawierających żadnej zawartości), np. <img>
czy <input>
, nie ma znaczenia jaka wartość zostanie przekazana do metody.
Importowany węzeł zwracany przez metodę importNode()
zostaje skopiowany (opcjonalnie z całą swoją zawartością) z poprzedniego drzewa węzłów, ale nie jest częścią w nowym drzewie dokumentu dopóki nie zostanie dodany do innego węzła należącego do drzewa dokumentu. Dlatego adoptowany węzeł nie będzie posiadał rodzica (wartość null
), aczkolwiek dalej posiada jakiegoś właściciela (tylko, że zmienionego).
Do skopiowania węzła bez zmiany jego właściciela służy metoda Node.cloneNode()
.
Kopiowanie węzłów jest bardzo pożyteczne i w niektórych okolicznościach pozwala zwiększyć wydajności tworzonych skryptów. Mając rozległą strukturę węzłową szybciej odtworzymy ją za pomocą kopiowania, niż gdybyśmy ręcznie tworzyli każdy węzeł z takiej struktury.
Prosty przykład:
<script>
var newP = document.createElement("p");
newP.textContent = "Węzeł tekstowy w akapicie.";
var newDocXML = document.implementation.createDocument(null, null, null);
document.write("Akapit z jednym węzłem tekstowym przed importem: " + "<br>");
document.write("newP.childNodes.length: " + newP.childNodes.length + "<br>");
document.write("newP.childNodes[0]: " + newP.childNodes[0] + "<br>");
document.write("newP.childNodes[0].textContent: " + newP.childNodes[0].textContent + "<br>");
document.write("newP.childNodes[0].ownerDocument: " + newP.childNodes[0].ownerDocument + "<br><br>");
document.write("Nowy dokument XML (będzie importował węzeł tekstowy z akapitu): " + "<br>");
document.write("var newDocXML = createDocument(null, null, null);" + "<br>");
document.write("newDocXML: " + newDocXML + "<br>");
document.write("newDocXML.childNodes.length: " + newDocXML.childNodes.length + "<br>");
var compare = newDocXML == document;
document.write("newDocXML == document: " + compare + "<br><br>");
document.write("Import węzła tekstowego z akapitu:" + "<br>");
document.write("var imported = newDocXML.importNode(newP.firstChild);" + "<br>");
var imported = newDocXML.importNode(newP.firstChild);
document.write("newDocXML.childNodes.length: " + newDocXML.childNodes.length + "<br><br>");
document.write("Węzeł tekstowy po imporcie:" + "<br>");
document.write("imported: " + imported + "<br>");
document.write("imported.textContent: " + imported.textContent + "<br>");
document.write("imported.ownerDocument: " + imported.ownerDocument + "<br><br>");
document.write("Akapit po imporcie: " + "<br>");
document.write("newP.childNodes.length: " + newP.childNodes.length);
document.write("<br><br>");
try{
document.importNode(document); // importujemy węzeł będący dokumentem
}
catch(e){
document.write("Przekazanie do metody importNode() węzła będącego dokumentem zrzuca błąd:" + "<br>");
document.write(e); // opis zależny od przeglądarki
document.write("<br>");
document.write(e.constructor); // function DOMException() { [native code] }
}
document.write("<br><br>");
try{
document.importNode(newP.createShadowRoot()); // importujemy węzeł typu ShadowRoot
}
catch(e){
document.write("Przekazanie do metody importNode() węzła typu ShadowRoot zrzuca błąd:" + "<br>");
document.write(e); // opis zależny od przeglądarki
document.write("<br>");
document.write(e.constructor); // function DOMException() { [native code] }
}
</script>
Na chwilę obecną jedynie przeglądarki Firefox i Chrome w całości obsługują metodę importNode()
zgodnie z najnowszymi wymaganiami specyfikacji DOM4, gdyż faktycznie zezwalają na pominięcie argumentu określającego rodzaj wykonywanej kopii i domyślnie wykonują jej płytką odmianę.
Składnia Web IDL#
interface Document : Node { Node importNode(Node node, optional boolean deep = false); };