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ść
nulllub 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
Elementlub 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.
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); };