Element (rozszerzenie)#
Element.innerHTML#
Właściwość innerHTML
parsuje (przy ustawianiu) lub serializuje (przy pobieraniu) zawartość danego elementu.
Opis działania#
Samo wywołanie i poszczególne jego części najlepiej objaśnić na zapisie składniowym:
var actual_content = element.innerHTML; // getting element.innerHTML = new_content; // setting
gdzie poszczególne człony oznaczają:
- actual_content - łańcuch znakowy reprezentujący aktualną zawartość struktury znacznikowej w elemencie, np. "
<p>Jakiś tekst.</p>
". - element - węzeł będący obiektem kontekstu.
- new_content - łańcuch znakowy reprezentujący nową ustawianą strukturę znacznikową w elemencie, np. "
<p>Jakiś nowy tekst.</p>
". Wartośćnull
jest traktowana jak pusty łańcuch znakowy.
W zależności od podejmowanej akcji muszą zostać wykonane następujące kroki:
Odczyt wartości atrybutu (getting):
Zwróć wynik działania algorytmu serializacji fragmentu na obiekcie kontekstu z przekazaniem boolowskiej wartości
true
dla flagi wymaganego dobrego sformułowani.W przypadku dokumentów XML krok ten może zrzucić wyjątek
"InvalidStateError"
zamiast zwrócenia łańcucha znakowego, kiedy obiekt kontekstu nie może zostać zserializowany zgodnie z wymogami XML-a (kwestia nierozstrzygnięta).
Zmiana wartości atrybutu: (setting):
Niech fragment będzie wynikiem działania algorytmu parsowania fragmentu z łańcuchem znakowym będącym ustawianą wartością oraz z elementem kontekstu będącym obiektem kontekstu.
W przypadku dokumentów XML krok ten może zrzucić wyjątek
"SyntaxError"
zamiast zwrócenia struktury znacznikowej, kiedy przekazany łańcuch znakowy nie może zostać sparsowany zgodnie z wymogami XML-a.- Zastąp wszystko przez fragment w obiekcie kontekstu.
Właściwość innerHTML
bierze pod uwagę jedynie zawartość (content) danego elementu, bez uwzględniania jego znacznika otwierającego i znacznika zamykającego. Jeśli zależy nam na takim zachowaniu, to można skorzystać z właściwości Element.outerHTML
.
Warto podkreślić, że przy serializacji węzłów tekstowych (ewentualnie atrybutów w elementach) może nastąpić samoczynne zastąpienie w danych tekstowych lub w wartościach atrybutów znaków &
, <
, >
i "
na odpowiadające im encje nazwane. Szczegóły tego zachowania są zależne od rodzaju przetwarzanego dokumentu, i w razie potrzeby należy je samodzielnie ustalić poprzez dokładną analizę poszczególnych algorytmów. Odczyt danych w oryginalnej postaci można przeprowadzić alternatywnymi poleceniami, np. Node.textContent
czy Attr.value
.
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 html = document.documentElement; // referencja do elementu HTML
alert(html.innerHTML); // Zwróci serializację zawartości elementu HTML (bez niego samego)
html.innerHTML = "<p style='color: blue'>Nowa zawartość!</p>";
</script>
Starsze przeglądarki internetowe mogą obsługiwać właściwość innerHTML
z drobnymi uchybieniami względem aktualnych standardów. Przykładowo, przeglądarka Internet Explorer (do wersji 8 włącznie) serializuje wpisaną przez użytkownika wartość do pola <input type="text">
, kiedy pozostałe przeglądarki tego nie robią. Od wersji IE9 wszystko działa prawidłowo:
<!DOCTYPE html>
<html>
<head>
<script>
function getInnerHTML(){
var box = document.getElementById("box"); // referencja do kontenera
alert(box.innerHTML); // Po wpisaniu tekstu do pola input starsze przeglądarki IE uwzględnią zmianę
}
</script>
</head>
<body>
<div id="box">
<p>Kliknij przycisk by zserializować zawartość kontenera DIV.</p>
<input type="text">
<input type="button" value="div.innerHTML" onclick="getInnerHTML()">
</div>
</body>
</html>
Właściwości innerHTML
nigdy nie powinno się używać do zapisu części tabeli - w takiej sytuacji parser przeglądarki internetowej może automatycznie zamknąć część tagów przy aktualizacji drzewa węzłów, aby uzyskać jego poprawną strukturę, a dalszą część (dodawaną w kolejnym wywołaniu polecenia) wstawić dopiero za tabelą. Nie ma natomiast problemów w przypadku zapisywania całej tabeli w jednym kroku lub modyfikacji zawartości pojedynczych komórek.
W związku z powyższym przeglądarka IE specjalnie blokuje możliwość zmiany zawartości niektórych elementów za pomocą właściwości innerHTML
, żeby nie dopuścić do problematycznych sytuacji. Na dzień dzisiejszy jest to niestandardowe zachowanie i nie musi być powielane przez pozostałe programy.
Na zakończenie warto omówić kwestię wydajnościową, która najczęściej poruszana jest w różnych publikacjach dla właściwości innerHTML
. W przypadku starszych przeglądarek internetowych właściwość innerHTML
była szybsza od alternatywnych metod DOM (tworzących i modyfikujących węzły) i oczywiście wygodniejsza, gdyż ten sam fragment kodu można było utworzyć przy użyciu mniejszej liczby poleceń. Wraz z premierą przeglądarki Chrome, gdzie silnik JS oparto na JIT, sytuacja uległa zmianie. Obecnie to alternatywne polecenia DOM okazują się szybsze. W razie potrzeby namawiam do wykonania podstawowego testu, który określi różnice wydajnościowe między kluczowymi technikami modyfikowania zawartości węzłów w aktualnych programach.
Składnia Web IDL#
partial interface Element { [TreatNullAs=EmptyString] attribute DOMString innerHTML; };