JavaScript DOM Ready function

Many JavaScript libraries, including the almost ubiquitous jQuery, provide an element.ready function. This allows for queuing functions to run when the document or element is ready to receive commands. The first thing to note isthis is not the same as the standard onload function provided by JavaScript, though the two functions serve similar purposes. Ready is (in jQuery at least) intended to execute as soon as the browser has fetched the DOM (for the element) but before it is rendered.

Josh Caldwell, Developer
Posted

Many JavaScript libraries, including the almost ubiquitous jQuery, provide an element.ready function. This allows for queuing functions to run when the document or element is ready to receive commands. The first thing to note isthis is not the same as the standard onload function provided by JavaScript, though the two functions serve similar purposes. Ready is (in jQuery at least) intended to execute as soon as the browser has fetched the DOM (for the element) but before it is rendered. The onload function, on the other hand, will wait until the element is completely loaded and rendered before executing.

Having some insight into how this works can help both in better utilization of the function and a better understanding of JavaScript itself. The first central idea is ensuring that multiple functions can run when an event is triggered. In order to do this a function wrapper can be used – something along the lines of:

  1. function runThisToo (newFunc, oldFunc){<br><br>
  2.   oldFunc();<br><br>
  3.   newFunc();<br><br>
  4. }/>/>/>

Note that there are many ways to do this; this is just a very simple one.

The next step is determining when the document or element is ‘ready.’ In this post, we’ll just talk about determining when the document as a whole is ready but there are many other tutorials that cover elements. Unfortunately, each browser has its own way of signaling that the DOM is ready. Mozilla and Opera make this quite easy – all that's needed is for the function to be registered on the event ‘DOMContentLoaded’ – for example:

 

  1. if (document.addEventListener){ //check for Mozilla or Opera<br><br>
  2.   document.addEventListener(“DOMContentLoaded”, FuncToCall, false);<br><br>
  3. }/>/>

FuncToCall is the function to run when the DOM is ready in this example. The third parameter tells the browser not to use Capture, something we don't need to worry about for now.

Internet Explorer makes things more difficult, the commonly used and generally accepted method is creating a script tag with the attribute defer=”defer”. The defer attribute tells IE to not load the script file until the DOM has been fully loaded. To take advantage of this, the function can be called when the readyState of that particular script ‘file’ is complete.

 

  1. if(document.all && !window.opera){ //test to see if we’re working with IE<br><br>
  2.   document.write(‘<script type=”text/javascript” id=”domLoadedTest” defer=”defer” src=”javascript:void(0)”>');<br><br>
  3.   document.write('</script>’);<br>
  4.  <br>
  5. var readyTest = document.getElementById(‘domLoadedTest’);<br>
  6.   readyTest.onreadystatechange = function () {<br>
  7.     if(this.readyState == ‘complete’){<br>
  8.       FuncToCall();<br>
  9.     }<br>
  10.   };<br><br>
  11. }/>/>/>

The final group of browser that should be accounted for is Safari and all its derivatives (browsers that use webkit). The only way to test for the DOM being ready is to set an interval and check the property document.readyState.

 

  1. var safariTimer = setInterval(function(){<br>
  2.   if(“loaded|complete”.indexOf(document.readyState) != -1){<br>
  3.     FuncToCall();<br>  }<br>
  4. }, 50);

This will just run ever 50 milliseconds until the document says that it is loaded or complete. We now need to remember to clear the interval in our FuncToCall function so that it won't loop forever. We should also include a fail-safe or backup method to make sure that the function is called in older browsers as well. The best way to do that is to just register our function with the onload function:

  1. var old = document.onload;<br><br>
  2. document.onload = function() { <br><br>
  3.   if(old) {old();} <br><br>
  4.   FuncToCall(); <br>};/>/>/>/>

Those are all the pieces to the puzzle. Putting them together isn’t too hard. An add function that adds functions to run on ready would make this more useful. Also, in order to prevent our document.onload declaration from running the function twice on browsers we tested from, the FuncToCall might look something like this:

  1. var run = false;<br>
  2. function FuncToCall(){<br>
  3.   if(!run){<br>
  4.     if(safariInterval) { clearInterval(safariInterval); }<br>
  5.     addedFuncs();<br>
  6.     run = true;<br>
  7.   }<br>
  8. }

I hope that the code snippets and basic explanations will help you to better understand the way that the ready function works; when it should be called; and how to write your own. I think its also good to remember that jQuery and similar libraries aren't black magic but instead a way to improve productivity by not having to rewrite these functions again and again.

Josh Caldwell

Developer