Element (rozszerzenie)#
Element.insertAdjacentHTML()#
Metoda insertAdjacentHTML()
parsuje przekazany łańcuch znakowy (drugi argument) i wstawia w określone miejsce względem danego elementu (pierwszy argument).
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
element.insertAdjacentHTML(position, text);
gdzie poszczególne człony oznaczają:
- element - węzeł będący obiektem kontekstu.
- position - łańcuch znakowy reprezentujący pozycję dodawanej struktury znacznikowej względem danego elementu. Dostępne są tylko i wyłącznie następujące wartości (wielkość znaków nie ma znaczenia):
- "
beforebegin
" - przed znacznikiem otwierającym dany element (czyli za jego bratem poprzedzającym, jeśli występuje). - "
afterbegin
" - za znacznikiem otwierającym dany element (czyli przed pierwszym jego dzieckiem, jeśli występuje). - "
beforeend
" - przed znacznikiem zamykającym dany element (czyli za ostatnim jego dzieckiem, jeśli występuje). - "
afterend
" - za znacznikiem otwierającym dany element (czyli przed jego bratem następującym, jeśli występuje).
- "
- text - łańcuch znakowy reprezentujący dodawaną strukturę znacznikową do elementu, np. "
<p>Jakiś nowy tekst.</p>
".
Algorytm wywołania metody insertAdjacentHTML(position, text)
nie jest skomplikowany. Dla lepszego zrozumienia tematu prezentuję go w całości:
Użyj pierwszy pasujący element z tej listy:
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
beforebegin
" - Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
afterend
" Niech context będzie rodzicem posiadanym przez obiekt kontekstu.
Jeśli context ma wartość
null
lub jest węzłem typuDocument
, to zrzuć wyjątek"NoModificationAllowedError"
.- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
afterbegin
" - Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
beforeend
" Niech context będzie obiektem kontekstu.
- W przeciwnym razie
Zrzuć wyjątek
"SyntaxError"
.
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
Jeśli context nie jest węzłem typu
Element
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.
Użyj pierwszy pasujący element z tej listy:
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
beforebegin
" Wstaw fragment do rodzica posiadanego przez obiekt kontekstu przed obiektem kontekstu.
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
afterbegin
" Wstaw fragment do obiektu kontekstu przed jego pierwszym dzieckiem.
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
beforeend
" Dodaj fragment do obiektu kontekstu.
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
afterend
" Wstaw fragment do rodzica posiadanego przez obiekt kontekstu przed bratem następującym dla obiektu kontekstu.
- Jeśli position pasuje pod względem nieczułości na wielkość znaków ASCII do łańcucha znakowego "
Działanie metody insertAdjacentHTML()
dla pozycji "afterbegin"
i "beforeend"
w pewnym sensie można by zasymulować za pomocą właściwości Element.innerHTML
(np. poleceniem element.innerHTML += "markup";
). Niestety, w takim przypadku cała zawartość danego elementu zostaje najpierw zserializowana (ryzyko "zepsucia kodu") i ponownie sparsowana (z dołączeniem nowej zawartości), co z pewnością odbije się na gorszej wydajności takiego rozwiązania, szczególnie w sytuacji, kiedy element posiada rozległą zawartość.
Dlatego też pod względem wydajnościowym metodzie insertAdjacentHTML()
bliżej jest do metody Range.createContextualFragment()
w połączeniu z innymi poleceniami wstawiającymi DOM, niż do właściwości Element.innerHTML
. W praktyce insertAdjacentHTML()
może okazać się najszybsza, gdyż w niektórych przypadkach (np. dla pozycji "beforeend"
) przeglądarki internetowe potrafią odpowiednio zoptymalizować cały proces.
Warto podkreślić, że pozycje "beforebegin"
i "afterend"
nie będą dostępne w przypadku elementów, które nie posiadają rodzica, lub których rodzicem jest węzeł typu Document
(czyli dla elementu dokumentowego, np. <html>
), chociaż Chrome dla wspomnianych pozycji (w przeciwieństwie do Firefoksa i IE11) niepotrzebnie zrzuca błąd także dla elementów z rodzicami będącymi fragmentami dokumentów.
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:
<!DOCTYPE html>
<html>
<head>
<script>
var num = 0;
function insertHTML(context){
var box = document.getElementById("box"); // referencja do kontenera
var input_val = context.value;
num += 1;
var str = "Nowa sparsowana treść " + num + " (<b>" + input_val + "<b/>). ";
box.insertAdjacentHTML(input_val, str);
}
</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ść względem kontenera DIV.</p>
<input type="button" value="beforebegin" onclick="insertHTML(this)">
<input type="button" value="afterbegin" onclick="insertHTML(this)">
<input type="button" value="beforeend" onclick="insertHTML(this)">
<input type="button" value="afterend" onclick="insertHTML(this)">
</body>
</html>
Metoda insertAdjacentHTML()
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, aczkolwiek potencjał w niej drzemiący już dawno zauważył sam John Resig i opisał w artykule "DOM insertAdjacentHTML". Uzupełnieniem będzie artykuł Mozilli "insertAdjacentHTML() Enables Faster HTML Snippet Injection", w którym poruszono kilka kluczowych spraw (także wydajnościowych) dla tej metody.
Składnia Web IDL#
partial interface Element { void insertAdjacentHTML(DOMString position, DOMString text); };