molily: Erweiterung fürs User-JS

Beitrag lesen

Hallo,

Oh, das hast du ein Fass ohne Boden aufgemacht.

(Warum funktioniert document.onload nur im Opera, nicht aber im FF?)

Gegenfrage: Warum funktioniert document.onload im Opera? Ich sehe keinen Grund dafür.

Weil der load-Event gemäß DOM 3 Events (zumindest) am Document-Knoten des DOM-Knotenbaums passiert, in einem (X)HTML-Dokument ist das gemäß DOM HTML das document-Objekt. Dass Opera und Gecko window.addEventListener kennen, ist tendenziell proprietär. Gemäß der Objekthierarchie window.document könnte man annehmen: Der load-Event startet beim window-Event und steigt zum document-Objekt hinab (capture phase) und wieder auf (bubble phase).

Zugegeben, DOM 3 Events alleine erklärt nicht direkt, warum auch document.onload im Opera funktioniert. Es erklärt aber, wieso document.addEventListener("load", function () {alert("Hallo Welt");}, false); funktioniert (das kann Mozilla auch nicht). Und es ist logisch, dass Opera beim Feuern eines Events sowohl die Handlerfunktion feuert, die unter knotenobjekt.onevent gespeichert wurde, als auch die, die über knotenobjekt.addEventListener registriert wurden.

Zugegeben, in DOM 2 Events steht zudem nicht ausdrücklich, dass der load-Event beim Document-Knoten passiert, es steht dort gar nicht, wo er passiert. Es steht dort nur, dass unload für das body-Element gültig ist. Das lässt sich aber schlecht auf load übertragen, schließlich kann man document.body nicht ansprechen, um ihm ein load-Handler zuzuweisen, bevor document.body geladen ist, und dann ist es bereits zu spät. Also gehe ich von DOM 3 Events als Maßstab aus, auch wenn kein Browser sich wirklich vollständig daran orientiert.

Geckos Verhalten ist schlichtweg fehlerhaft. Korrekt (oder sagen wir einmal kohärent) verhält er sich in dem Punkt: Eventobjekt.target beim load-Event am window-Objekt ist nicht das window-Objekt selbst, sondern HTMLDocument, also das document-Objekt. Aber der Event kommt nie beim echten target, also document, an. Man denkt, es wäre ein Event, der danach hinabsteigt bzw. gerade aufgestiegen ist. Aber Eventobjekt.eventPhase sagt target phase. Das ist widersprüchlich, weil Eventobjekt.target und Eventobjekt.currentTarget in der target phase per definitionem identisch sein müssen. Daher ist Eventobjekt.target === document gemäß DOM 3 Events korrekt, aber das restliche Verhalten von Gecko widerspricht dem, insofern ist das Gecko-Konzept gemessen an DOM 3 Events fehlerhaft, gemessen an sich selbst inkohärent.

Opera spinnt auch ein wenig: Er sieht window und document in dieser Hinsicht als identisch an, nicht als verschachtelt. Das heißt, sowohl beim load-Handler für window als auch bei load-Handler für document ist Eventobjekt.target === document, Eventobjekt.currentTarget === document und Eventobjekt.eventPhase = 2 (target phase). Da steigt der load-Event nicht auf und nicht ab, window und document werden gleichermaßen als oberste Objekte angesehen. Das ist m.W. bei allen Events so, nehmen wir einmal den click-Event:

window.addEventListener("click", function (e) {alert(e.target + " " + e.currentTarget + " " + e.eventPhase);}, false);  
document.addEventListener("click", function (e) {alert(e.target + " " + e.currentTarget + " " + e.eventPhase);}, false);

Dasselbe Ergebnis wie beim load-Event (angenommen, das Dokument ist so klein, dass man in eine leere Fläche des Browserfensters klicken kann und somit kein Kindelement von body trifft).

Noch eine Kuriosität: Konqueror feuert den load-Event bei document mit target == null, currentTarget === document, eventPhase == 2. Dieser Event steigt nicht von oben herab und steigt auch nicht auf, löst also keinen load-Event bei window aus. Gleichzeitig wird ein zweiter Event gefeuert beim window-Objekt mit target == null, currentTarget == null, eventPhase == 2. (Immerhin verweist this auf das window-Objekt.) Dieser bewegt sich auch nicht weiter in der Objekthierarchie. Soviel zur Standardkonformität von Konqueror.

Mathias