Tuesday, October 16th, 2007

Ajaxian Featured Tutorial: When is your page ready?

Category: JavaScript, Tutorial

In this tutorial, Patrick Hunlock takes us through a page’s ready states and shows how to write JavaScript code to determine when a page’s DOM elements are loaded and available:

The problem with window.onload is that it assumes that no other script or library will want to attach an onload event of its own. And in this day of booming frameworks and endless pre-written snippets, that is no longer a certainty. Indeed, as your Javascript applications become larger you my find yourself stumbling over your own code!

Patrick provides step-by-step explanations and code that shows how to register events so they don’t conflict with other libraries or code snippets down the road:

startStack=function() { };  // A stack of functions to run onload/domready

registerOnLoad = function(func) {
   var orgOnLoad = startStack;
   startStack = function () {
      orgOnLoad();
      func();
      return;
   }
}

var ranOnload=false; // Flag to determine if we've ran the starting stack already.

if (document.addEventListener) {
  // Mozilla actually has a DOM READY event.
   document.addEventListener("DOMContentLoaded", function(){if (!ranOnload) {ranOnload=true; startStack();}}, false);
}  else if (document.all && !window.opera) {
  // This is the IE style which exploits a property of the (standards defined) defer attribute
  document.write("< \/scr" + "ipt>");  
  document.getElementById("DOMReady").onreadystatechange=function(){
    if (this.readyState=="complete"&&(!ranOnload)){
      ranOnload=true;
      startStack();
    }
  }
}

var orgOnLoad=window.onload;
window.onload=function() {
   if (typeof(orgOnLoad)=='function') {
      orgOnLoad();
   }
   if (!ranOnload) {
     ranOnload=true;
     startStack();
   }
}

Posted by Rey Bango at 8:00 am
23 Comments

++---
2.1 rating from 55 votes

23 Comments »

Comments feed TrackBack URI

Sry. Offtopic I guess..
Does anyone ever experienced problems when using ondomreadyWhatEver in a frameset ? Imagine when onDomR… was called in frame two, it’ll just stop working. If the same page was loaded in a new tab, no frame, it worked. Any Ideas ?

Comment by Felix — October 16, 2007

I know that using fancy curly quotes looks real cool and all… but when posting code, it is a royal PITA!

When a reader wants to try it out, they have to copy the code, then go over it and replace each occurence of a left double quote with a single quote, and then every right double quote with a single quote… and indent everything so that it is readable again.

Please don’t do this… just put the raw text in a pre tag with a fixed width font and be done with it!

PS If you want, put a width/height/border/overflow on the pre tag for styling needs.

Comment by walter — October 16, 2007

Yeah, blockquoting code is bad.

Comment by Jon Hartmann — October 16, 2007

@Walter & Jon: Better?

Comment by Rey Bango — October 16, 2007

The technique used for detecting DOM content loaded in IE is broken (hence the recent flurry of alternatives). It’s possible that a DOM modifications causes the deferred script to execute before DOM load anyway.

Comment by Mark Wubben — October 16, 2007

Awesome, thank you Rey!

I know that these tutorials are introductions to a concept, but when I look at stuff like this I begin to reflexively enclose the code and create lazy initializations and such… I do really like this topic though: detecting when the DOM is ready seems to be a hot issue, and methods to create detectors are tricky indeed.

Comment by Jon Hartmann — October 16, 2007

Been there done that. This still isn’t an all round solution, even sifr still relies on good old onload because the current onDOMReady solutions aren’t reliable enough (in sifrs case because the runtime styles haven’t been initialised yet). Still needs a lot of work, I think I’m on to something though, might post something up later.

Comment by Anonymous — October 16, 2007

Wait a minute, you mean this whole time it was that easy? Like, whoa.

Comment by Dustin Diaz — October 16, 2007

how to register events so they don’t conflict with other libraries or code snippets down the road

… ehr, with 4 global variables and an old (not perfect) approach to DOMContentLoaded problem ? … uhm, interesting! … more than my last two emails to Ajaxian I suppose :P

Comment by Andrea Giammarchi — October 16, 2007

Yeah I have to say, this particular solution seems a bit dated.. Plus you have to make sure you know what you can and can’t access on elements before all the rest has been loaded (runtime styles was mentioned).

But of course it’s always good to mention that the alternatives are out there, for the people still stuck in the archaic age of window onload. :)

Comment by Daniel Pihlström — October 16, 2007

@Dustin, Andrea, & Daniel: Instead of only presenting the negatives and/or sarcasm, it sure would be helpful if you offered alternatives and positive advice. The point of the tutorial series is to provide users, especially new ones, with helpful tips that will get them up to speed. If you know of better solutions, please feel free to post links, advice, etc. Better yet, write a tutorial and I’ll be happy to post it.

Comment by Rey Bango — October 16, 2007

jQuery’s SVN code seems to have the latest magic in this area and it looks beautifully simple. Haven’t tested it personally though.

Comment by Steve Clay — October 16, 2007

@Anonymous, RE: sIFR: that’s only true for Safari and Opera ;-)

Comment by Mark Wubben — October 17, 2007

I don’t really see what all the fuzz about sIFR is … the solutions currently offered, are for when the DOM is ready. WHEN THE DOM IS READY. If you require something for when the entire document is ready, use the onload event, that guarantees that the entire document is ready.

As for the code above, it reminded me of Simon Willisons addLoadEvent, which I personally used for quite awhile, customized to my own needs, and learned from. Nice to see that despite all the flaming, some people still have the courage to write tutorials.

Comment by Morgan Roderick — October 17, 2007

It’s not about courage. If you’re writing ajax/js you’ve almost certainly faced this problem, and probably found the current solution for it by yourself already. This tutorial does not improve upon that solution, its only purpose is to explain to newcomers how it works.

I’ve got a completely different solution atm that guarantees an onDOMReady event for all platforms (that is to say IE,FF,Op,Saf) and also guarantees the CSS to have been fully initialized in all browsers but Opera (trying to fix that without a browser detect, but it’s proving to be quite difficult).

Comment by Anonymous — October 17, 2007

Maybe I’m missing something, but I’ve just always put a small script block at the end of my content just before /body, and used that to call my “domReady” functions. Has always worked for me. To keep things clean, just the function call is there eg. init(), and the positioning of the script block just ensures the timing is accurate (eg., the DOM should be fully-parsed by that time.)

Comment by Scott Schiller — October 17, 2007

@Scott on it’s own that particular solution is not enough to guarantee the DOM is ready (doesn’t work consistently on all platforms, works fine on FF and IE though if I remember correctly). Also, hardcoded script tags are evil, if you decide to use a different method later on you’ll have to edit all your html pages.

Comment by Anonymous — October 17, 2007

@Anonymous: Thanks for the constructive feedback. This is the type of exchange that I would expect in these posts. If you have sample code or a tutorial, please feel free to email me and I’ll be glad to create a follow-up post. reybango at gmail

Comment by Rey Bango — October 17, 2007

@Ray … last week We wrote about last DOMContentLoaded IE alternative in about two Ajaxians posts + 3 or more different blogs.
It’s quite hilarius that “today” We have “here” a tutorial (with a defer “trick” explained different moths ago in Dean’s blog) that uses / talks about a deprecated solution using these not so much good practices (i.e. 4 global variables instead of one).
That’s all and please sorry for my sarcasm, it was for expecially for Ajaxian news (they ignore mine mailed two times :P), not for Patrick contribute.
Regards

Comment by Andrea Giammarchi — October 17, 2007

@Andrea: It’s hard enough finding good content that will keep experienced developers such as yourself interested without keeping track of every post that me, Dion, Ben or any of the other Ajaxians make. I know that I can’t do it.

With that said, I do my best to find tutorials that will cater to a variety of people, especially beginners. Some may be good and some may not be as good. At the end of the day, I do my best to find good stuff. Again, instead of simply presenting the negatives, how about offering up constructive feedback that could actually be useful. If you have better tutorials, then please feel free to send them to me or include them in the comments. I’d be happy to check them out and consider posting them here. Again you can catch me at reybango at gmail dot com.

Comment by Rey Bango — October 17, 2007

Maybe it’s something specific to the type of DOM things I’m doing, but I’ve never really run into issues with a small inline one-line script call at the bottom of the body. While I agree inline script is less than ideal, the “inline script tag” problem you (anonymously :D) cite is no different than if a CSS or image file name were to change, etc.
 
The “onload” problem has been written up many times (Dean Edwards et al,) and with mixed results; my take on it (until there’s a standard DOMContentLoaded,) is either to use a library script like the YUI which has presumably been extensively-tested, or just go with a one-line bottom-script block. I’ve used the technique on my site for years, and it’s served me well.

Comment by Scott Schiller — October 17, 2007

@Scott I generally agree with You but the problem is W3 (WAI) and an empty noscript after inline script tag while events managment inside head tag has not this problem and should be portable / compatible with different libraries. You probably don’t need portability and, as Me, You don’t use third part code so in this way is really simple to manage correctly a single function to call inside inline script but I suppose the goal of this post and, generally, onReady event is quite different.

@Rey, ok :-)

Comment by Andrea Giammarchi — October 18, 2007

ajaxflakes – Read all about the latest developments on web design 2.0 and ajax + lots of tips. TOP 100+ best Free Opensource Software for windows XP and Vista. Thought i should add it might be helpful to others… http://ajaxflakes.com

Comment by startoy — October 27, 2007

Leave a comment

You must be logged in to post a comment.