onLoad
The load event is a general “loading complete” signal. It is supported by many elements. For example, external SCRIPT and IMG, IFRAME trigger it when downloading of their content finishes. The handler window.onload and iframe.onload triggers when the page is fully loaded with all dependent resources including images and styles.
- window.onload = function () {
- console.log("**** window.onload ****");
- var containerElement = document.getElementById("container"),
- html = containerElement.innerHTML;
- containerElement.innerHTML = html + "**** window.onload ****" + "<br>";
- console.log(containerElement);
- };
- // iFrame onload.
- document.getElementById("my-frame").onload = function () {
- console.log("**** iframe.onload ****");
- var containerElement = document.getElementById("container"),
- html = containerElement.innerHTML;
- containerElement.innerHTML = html + "**** iframe.onload ****" + "<br>";
- };
onDOMContentLoaded
The DOMContentLoaded event triggers on document when the page is ready. It waits for the full HTML and scripts, and then triggers.
All browsers except IE<9 support it.
What onDOMContentLoaded awaits
onDOMContentLoaded won't await
DOMContentLoaded won’t wait for a script, created by document.createElement (called dynamic script) in all browsers except Opera. This feature is used to add ads and counters which don’t block the page from initialization. Usually a script.async = true;
is added to make the script don’t wait for other scripts.
- // Dynamically load script.
- var script = document.createElement("script");
- script.src = "js/dynamic.js";
- document.getElementsByTagName("head")[0].appendChild(script);
Firefox doesn't autofill forms before DOMContentLoaded. For example, you have a login/password form, and the values are remembered by Firefox. The browser will autofill them only after DOMContentLoaded. If it takes too long, the user may have to wait.
onDOMContentLoaded awaits
DOMContentLoaded will wait for a script:
- In all browsers - external scripts in HTML.
- In Opera - all scripts.
- In Safari/Chrome - scripts with defer attribute.
Hacks for IE<9
IE<9 hack for a document not inside a frame
For IE, there is a hack which works if a window is not inside a frame. The document is being scrolled using document.documentElement.doScroll call. The browser throws exception until the DOM is complete. So basically the scoll is called every 10 ms or so until no exception is thrown. Then the DOM ready handler is activated.
- try {
- var isFrame = window.frameElement !== null ? TRUE : FALSE;
- } catch (e) {
- }
- // IE, the document is not inside a frame.
- if (document.documentElement.doScroll && !isFrame) {
- function tryScroll() {
- if (isReady) {
- return;
- }
- try {
- document.documentElement.doScroll("left");
- ready();
- } catch (e) {
- setTimeout(tryScroll, 10);
- }
- }
- tryScroll();
- }
IE<9 hack in a frame
For a document inside a frame or iframe, the doScroll trick doesn’t work, so we use a special IE event named document.onreadystatechange
. If it triggers with readyState === "complete"
, it means that the document is really complete.
- // IE, the document is inside a frame.
- document.attachEvent("onreadystatechange", function() {
- if ( document.readyState === "complete" ) {
- ready();
- }
- });
The crossbrowser DOMContentLoaded handling code
- function bindReady(handler) {
- var isReady = false;
- function ready() {
- if (isReady) {
- return;
- }
- isReady = true;
- handler();
- }
- if ( document.addEventListener ) { // Chrome, Firefox, Safari, Opera
- document.addEventListener("DOMContentLoaded", ready, false);
- } else if ( document.attachEvent ) { // IE
- try {
- var isFrame = window.frameElement !== null ? TRUE : FALSE;
- } catch(e) {
- }
- // IE, the document is not inside a frame
- if (document.documentElement.doScroll && !isFrame) {
- function tryScroll() {
- if (isReady) {
- return;
- }
- try {
- document.documentElement.doScroll("left");
- ready();
- } catch(e) {
- setTimeout(tryScroll, 10);
- }
- }
- tryScroll();
- }
- // IE, the document is inside a frame
- document.attachEvent("onreadystatechange", function() {
- if ( document.readyState === "complete" ) {
- ready();
- }
- });
- }
- // Old browsers
- if (window.addEventListener) {
- window.addEventListener("load", ready, false);
- } else if (window.attachEvent) {
- window.attachEvent("onload", ready);
- } else {
- var fn = window.onload // very old browser, copy old onload
- window.onload = function() { // replace by new onload and call the old one
- fn && fn();
- ready();
- };
- }
- }
Multiple handlers
- var readyList = [];
- function onReady(handler) {
- function executeHandlers() {
- for (var i=0; i<readyList.length; i++) {
- readyList[i]();
- }
- }
- if (!readyList.length) { // set handler on first run
- bindReady(executeHandlers);
- }
- readyList.push(handler);
- }
回應 (Leave a comment)