JavaScript: Onload-Techniken

Nachteile des load-Ereignisses

Wir haben bereits die drei Phasen von ereignisbasierten Scripten kennengelernt. Die zweite Phase tritt ein, wenn das Dokument fertig geladen ist und der DOM-Elementenbaum des Dokuments vollständig aufgebaut ist. Sinnvolle Scripte schalten sich automatisch hinzu, ohne dass JavaScript-Code direkt ins HTML eingebettet ist (Unobtrusive JavaScript). Dazu ist es von zentraler Wichtigkeit, das Script zu initialisieren, sobald der Zugriff auf den gesamten DOM-Baum möglich ist, vor allem um Event-Handler bei gewissen Elementen registriert.

Mit dem dokumentweiten load-Ereignis (window.onload) haben wir eine Funktion nach dem vollständigen Laden des Dokuments ausgeführt. Das load-Ereignis tritt jedoch erst dann ein, wenn das gesamte Dokument mitsamt aller externen Ressourcen vom Webserver heruntergeladen wurde. Dazu gehören eingebettete Grafiken, Multimedia-Plugins und gegebenenfalls Iframes mit weiteren HTML-Dokumenten. Je nachdem, welche externen Ressourcen eingebunden werden, kann das Dokument zum Zeitpunkt des load-Ereignisses schon längst im Browser aufgebaut sein und der Anwender kann es schon größtenteils lesen und bedienen.

Für das Event-Handling interessiert uns nicht, wann alle eingebetteten Ressourcen fertig geladen sind, sondern lediglich, wann der JavaScript-Zugriff auf den DOM-Baum möglich ist. Dieser Zeitpunkt, genannt DOM ready, tritt meistens weit vor dem load-Ereignis ein. Ein Script sollte dem Dokument so zeitnah wie möglich Interaktivität hinzufügen und notwendige Änderungen vornehmen, damit das Dokument einschließlich der JavaScript-Funktionalität bereits während des Ladens für den Anwender bedienbar ist.

DOMContentLoaded

Der load-Event ist aus heutiger Sicht für Unobtrusive JavaScript nicht geeignet. Glücklicherweise gibt es ein Ereignis, das eintritt, sobald der Parser den gesamten HTML-Code eingelesen hat und der komplette DOM-Baum für JavaScripte zugänglich ist: DOMContentLoaded.

Die Überwachung dieses Ereignises ist allerdings nur im Zusammenhang mit addEventListener, also dem W3C-Modell möglich. Alle großen Browser, die den DOM-Standard umsetzen, kennen mittlerweile auch DOMContentLoaded. Eine Ausnahme bilden der Internet Explorer vor Version 9: Diese älteren Versionen unterstützen weder den DOM-Events-Standard, noch kennen sie das Ereignis DOMContentLoaded.

Das folgende Beispiel demonstriert die Überwachung der beiden Ereignisse load und DOMContentLoaded:

function dokumentGeladen (e) {
   alert("Das Ereignis " + e.type + " ist passiert.")
}
document.addEventListener("load", dokumentGeladen, false);
document.addEventListener("DOMContentLoaded", dokumentGeladen, false);

Internet Explorer vor Version 9 können dieses Beispiel nicht ausführen, sie kennen die Methode addEventListener nicht.

Wenn Sie das Beispiel in ein HTML-Dokument einfügen, so demonstriert es, dass der DOMContentLoaded-Event vor dem load-Event passiert. Wenn große und zahlreiche externen Ressourcen in das Dokument eingebunden sind, dann kann zwischen beiden Ereignissen viel Zeit vergehen – wertvolle Zeit, die ein Script nicht untätig verstreichen lassen sollte.

Browserübergreifendes DOMContentLoaded

Leider gibt es ältere Browser, die das äußerst nützliche DOMContentLoaded-Ereignis nicht unterstützen. Ältere Internet Explorer kennen auch kein gleichwertiges Ereignis. Daher nutzt die verbreitete Sonderlösung verschiedene Microsoft-eigene Techniken, um Rückschlüsse darauf zu ziehen, ob der Elementenbaum bereits vollständig eingelesen wurde. Die genaue Funktionsweise sei hier nicht näher erklärt. Stattdessen sei auf eine browserübergreifende Fertiglösung hingewiesen, die sowohl DOMContentLoaded unterstützt als auch einen erprobten Workaround für ältere Internet Explorer enthält: ContentLoaded.js von Diego Perini. Das Script ist abwärtskompatibel, das heißt, wenn alle Stricke reißen, wird auf das robuste load-Ereignis zurückgefallen.

Wenn Sie dieses Script einbinden, können Sie eine Funktion folgendermaßen ausführen, sobald der DOM-Baum zur Verfügung steht:

function init () {
// Diese Funktion kann auf den gesamten DOM-Baum zugreifen.
}
// Nutzung von Diego Perinis Helferfunktion
ContentLoaded(window, init);

Ein solche DOM-Ready-Technik ist in den verbreiteten JavaScript-Frameworks bereits eingebaut. Diese bringen eigene Event-Handling-Systeme mit sich, die das Ausführen von Funktionen erlauben, sobald die DOM-Schnittstelle vollständig nutzbar ist.

Fallstricke bei DOMContentLoaded

Das DOMContentLoaded-Ereignis wurde ursprünglich vom Browserhersteller Mozilla erfunden. Andere Browserhersteller haben es übernommen, weil sie sie nützlich fanden. Mittlerweile wird die genaue Funktionsweise in HTML5 standardisiert.

Trotz dieser Standardisierung verhalten sich die Browser im Detail noch unterschiedlich. Eine Unstimmigkeit ist die Frage, ob das Ereignis durch den Ladevorgang externer Stylesheets verzögert werden soll.

Beide Varianten ergeben Sinn: Es reicht zwar aus, dass der DOM-Baum komplett eingelesen ist, wenn man Event-Handler registrieren will. Allerdings gibt es auch Scripte, die in der Initialisierungsphase bereits auf die Darstellung gewisser Elemente reagieren sollen – und diese wird üblicherweise durch externe Stylesheets geregelt. Wenn das Script beispielsweise die Größe eines Elements in Erfahrung bringen will, muss der Browser bereits die Stylesheets verarbeitet und die Darstellung berechnet haben.

In HTML5 ist geregelt, dass das Laden von Stylesheets das DOMContentLoaded-Ereignis verzögert. ...