2014
Mar
09

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
  1. window.onload = function () {
  2. console.log("**** window.onload ****");
  3.  
  4. var containerElement = document.getElementById("container"),
  5. html = containerElement.innerHTML;
  6. containerElement.innerHTML = html + "**** window.onload ****" + "<br>";
  7. console.log(containerElement);
  8. };
iframe.onload
  1. // iFrame onload.
  2. document.getElementById("my-frame").onload = function () {
  3. console.log("**** iframe.onload ****");
  4.  
  5. var containerElement = document.getElementById("container"),
  6. html = containerElement.innerHTML;
  7. containerElement.innerHTML = html + "**** iframe.onload ****" + "<br>";
  8. };

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.

Example
  1. // Dynamically load script.
  2. var script = document.createElement("script");
  3. script.src = "js/dynamic.js";
  4. 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.

Example
  1. try {
  2. var isFrame = window.frameElement !== null ? TRUE : FALSE;
  3. } catch (e) {
  4.  
  5. }
  6.  
  7. // IE, the document is not inside a frame.
  8. if (document.documentElement.doScroll && !isFrame) {
  9. function tryScroll() {
  10. if (isReady) {
  11. return;
  12. }
  13. try {
  14. document.documentElement.doScroll("left");
  15. ready();
  16. } catch (e) {
  17. setTimeout(tryScroll, 10);
  18. }
  19. }
  20. tryScroll();
  21. }

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.

Example
  1. // IE, the document is inside a frame.
  2. document.attachEvent("onreadystatechange", function() {
  3. if ( document.readyState === "complete" ) {
  4. ready();
  5. }
  6. });

View Demo

The crossbrowser DOMContentLoaded handling code

Example
  1. function bindReady(handler) {
  2. var isReady = false;
  3.  
  4. function ready() {
  5. if (isReady) {
  6. return;
  7. }
  8. isReady = true;
  9. handler();
  10. }
  11.  
  12. if ( document.addEventListener ) { // Chrome, Firefox, Safari, Opera
  13. document.addEventListener("DOMContentLoaded", ready, false);
  14. } else if ( document.attachEvent ) { // IE
  15. try {
  16. var isFrame = window.frameElement !== null ? TRUE : FALSE;
  17. } catch(e) {
  18.  
  19. }
  20.  
  21. // IE, the document is not inside a frame
  22. if (document.documentElement.doScroll && !isFrame) {
  23. function tryScroll() {
  24. if (isReady) {
  25. return;
  26. }
  27. try {
  28. document.documentElement.doScroll("left");
  29. ready();
  30. } catch(e) {
  31. setTimeout(tryScroll, 10);
  32. }
  33. }
  34. tryScroll();
  35. }
  36.  
  37. // IE, the document is inside a frame
  38. document.attachEvent("onreadystatechange", function() {
  39. if ( document.readyState === "complete" ) {
  40. ready();
  41. }
  42. });
  43. }
  44.  
  45. // Old browsers
  46. if (window.addEventListener) {
  47. window.addEventListener("load", ready, false);
  48. } else if (window.attachEvent) {
  49. window.attachEvent("onload", ready);
  50. } else {
  51. var fn = window.onload // very old browser, copy old onload
  52. window.onload = function() { // replace by new onload and call the old one
  53. fn && fn();
  54. ready();
  55. };
  56. }
  57. }

Multiple handlers

Example
  1. var readyList = [];
  2.  
  3. function onReady(handler) {
  4. function executeHandlers() {
  5. for (var i=0; i<readyList.length; i++) {
  6. readyList[i]();
  7. }
  8. }
  9.  
  10. if (!readyList.length) { // set handler on first run
  11. bindReady(executeHandlers);
  12. }
  13.  
  14. readyList.push(handler);
  15. }

View Demo

Related Posts


回應 (Leave a comment)