Javascript - How to detect if document has loaded (IE 7/Firefox 3)

314,291

Solution 1

There's no need for all the code mentioned by galambalazs. The cross-browser way to do it in pure JavaScript is simply to test document.readyState:

if (document.readyState === "complete") { init(); }

This is also how jQuery does it.

Depending on where the JavaScript is loaded, this can be done inside an interval:

var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
        clearInterval(readyStateCheckInterval);
        init();
    }
}, 10);

In fact, document.readyState can have three states:

Returns "loading" while the document is loading, "interactive" once it is finished parsing but still loading sub-resources, and "complete" once it has loaded. -- document.readyState at Mozilla Developer Network

So if you only need the DOM to be ready, check for document.readyState === "interactive". If you need the whole page to be ready, including images, check for document.readyState === "complete".

Solution 2

No need for a library. jQuery used this script for a while, btw.

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
window.onload = init;

Solution 3

You probably want to use something like jQuery, which makes JS programming easier.

Something like:

$(document).ready(function(){
   // Your code here
});

Would seem to do what you are after.

Solution 4

if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

Solution 5

If you actually want this code to run at load, not at domready (ie you need the images to be loaded as well), then unfortunately the ready function doesn't do it for you. I generally just do something like this:

Include in document javascript (ie always called before onload fired):

var pageisloaded=0;
window.addEvent('load',function(){
 pageisloaded=1;
});

Then your code:

if (pageisloaded) {
 DoStuffFunction();
} else {
 window.addEvent('load',DoStuffFunction);
}

(Or the equivalent in your framework of preference.) I use this code to do precaching of javascript and images for future pages. Since the stuff I'm getting isn't used for this page at all, I don't want it to take precedence over the speedy download of images.

There may be a better way, but I've yet to find it.

Share:
314,291

Related videos on Youtube

Marcos
Author by

Marcos

Updated on July 25, 2020

Comments

  • Marcos
    Marcos almost 4 years

    I want to call a function after a document loads, but the document may or may not have finished loading yet. If it did load, then I can just call the function. If it did NOT load, then I can attach an event listener. I can't add an eventlistener after onload has already fired since it won't get called. So how can I check if the document has loaded? I tried the code below but it doesn't entirely work. Any ideas?

    var body = document.getElementsByTagName('BODY')[0];
    // CONDITION DOES NOT WORK
    if (body && body.readyState == 'loaded') {
        DoStuffFunction();
    } else {
        // CODE BELOW WORKS
        if (window.addEventListener) {  
            window.addEventListener('load', DoStuffFunction, false);
        } else {
            window.attachEvent('onload', DoStuffFunction);
        }
    }
    
    • Richard Simões
      Richard Simões almost 15 years
      "I want to call a function after a document loads, but the document may or may not have finished loading yet." This does not compute.
    • Ben Blank
      Ben Blank almost 15 years
      I believe he means he doesn't have control over when his block of code is initially run, but wants to ensure DoStuffFunction() isn't called before the document has finished loading.
  • Thomas L Holaday
    Thomas L Holaday almost 15 years
    And if he wants to see how jQuery does it in a portable way, jQuery's source is there for the inspection :-)
  • Ben Blank
    Ben Blank almost 15 years
    And in case it isn't clear, if ready() is called after document load, the passed function is run immediately.
  • Roatin Marth
    Roatin Marth over 12 years
    Totally missed the point of the question. init will not run if this code you posted is included after the page has already loaded, which is the point of the OP: he/she can't control when his script is included. (note that only the setInterval branch will work)
  • Roatin Marth
    Roatin Marth over 12 years
    @Ben Blank: unless of course jQuery itself is included after the document has loaded ;)
  • Ben Blank
    Ben Blank over 12 years
    @Roatin Marth — Actually, that works fine, too. (Just tried it with jQuery 1.7.1 on FF8 and IE8.)
  • Roatin Marth
    Roatin Marth over 12 years
    @Ben Blank: Ahh, see I'm in FF 3.0 where it fails.
  • marcgg
    marcgg over 11 years
    -1: even if the answer makes sense the OP never mentioned jQuery. Using the entire jQuery project just to get document ready is way overkill.
  • laurent
    laurent about 11 years
    @costa, if document.readyState == "complete", it means everything, including images, have been loaded.
  • b01
    b01 about 11 years
    This belongs in a library. Along with all the other wheels people commonly re-invent.
  • Tomáš Zato
    Tomáš Zato over 10 years
    I'm using combination of both events and document.readyState to make sure the function starts after DOM has been parsed, or later, depending on when it has been called. Is there an event for interactive readyState?
  • Yugal Jindle
    Yugal Jindle over 10 years
    Awesome - DOM is so deceptive.
  • Ryan Taylor
    Ryan Taylor about 10 years
    I'd use /loaded|complete/.test(document.readyState). Some browsers set document.readyState to "loaded" instead of "complete". Also, document.readyState does NOT ensure fonts have been loaded, there's no real good way to test for that without a plugin.
  • Admin
    Admin over 9 years
    What about document.onreadystatechange? This seems more streamlined if browsers support it. stackoverflow.com/questions/807878/…
  • wpp
    wpp over 9 years
    I think this results in an infinite loop if init() results in an error. @galambalazs answer takes care of that case
  • laurent
    laurent over 9 years
    @wpp, you are right. To be safe, it's better to clear the interval before calling init(). I've updated the code.
  • cantfindaname88
    cantfindaname88 almost 9 years
    I think to avoid setInterval, follow the answer below.
  • rnevius
    rnevius over 8 years
    I think it would be better to check for document.readyState !== "loading", for the "DOM ready" state. This prevents issues cropping up if the readyState is checked late for some reason (after the "interactive" state).
  • Aniket
    Aniket about 5 years
    Doesn't seem to work in the latest Chrome document.loaded is always undefined
  • Jman
    Jman about 5 years
    this was 2010 :). Now i'll use body.readyState === 'loaded'