jQuery: the ready() event method in details

The jQuery's ready() event is related to the following DOM/jQuery's states and structures:

  • the DOMContentLoaded event
  • the document object
  • the readyList array
  • the isReady property
  • the bindReady() method
ready: function( fn ) {
  // Attach the listeners
  jQuery.bindReady();

  // If the DOM is already ready
  if ( jQuery.isReady ) {
   // Execute the function immediately
   fn.call( document, jQuery );

  // Otherwise, remember the function for later
  } else if ( readyList ) {
   // Add the function to the wait list
   readyList.push( fn );
  }

  return this;
}

Basically, this method performs two actions:

  1. if the DOM is fully loaded, it performs the function immediately
  2. otherwise, it puts that function in a queue for later use.

The handler ready() performs all the required work:

// Handle when the DOM is ready
 ready: function() {
  // Make sure that the DOM is not already loaded
  if ( !jQuery.isReady ) {
   // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
   if ( !document.body ) {
    return setTimeout( jQuery.ready, 13 );
   }

   // Remember that the DOM is ready
   jQuery.isReady = true;

   // If there are functions bound, to execute
   if ( readyList ) {
    // Execute all of them
    var fn, i = 0;
    while ( (fn = readyList[ i++ ]) ) {
     fn.call( document, jQuery );
    }

    // Reset the list of functions
    readyList = null;
   }

   // Trigger any bound ready events
   if ( jQuery.fn.triggerHandler ) {
    jQuery( document ).triggerHandler( "ready" );
   }
  }
}

This handler checks if the body element exists and in that case runs all functions in sequence by using the JavaScript call() function within a while loop that iterates over the readyList array. Finally, the bindReady() method actually binds this event to the document object:

bindReady: function() {
  if ( readyBound ) {
   return;
  }

  readyBound = true;

  // Catch cases where $(document).ready() is called after the
  // browser event has already occurred.
  if ( document.readyState === "complete" ) {
   return jQuery.ready();
  }

  // Mozilla, Opera and webkit nightlies currently support this event
  if ( document.addEventListener ) {
   // Use the handy event callback
   document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
   
   // A fallback to window.onload, that will always work
   window.addEventListener( "load", jQuery.ready, false );

  // If IE event model is used
  } else if ( document.attachEvent ) {
   // ensure firing before onload,
   // maybe late but safe also for iframes
   document.attachEvent("onreadystatechange", DOMContentLoaded);
   
   // A fallback to window.onload, that will always work
   window.attachEvent( "onload", jQuery.ready );

   // If IE and not a frame
   // continually check to see if the document is ready
   var toplevel = false;

   try {
    toplevel = window.frameElement == null;
   } catch(e) {}

   if ( document.documentElement.doScroll && toplevel ) {
    doScrollCheck();
   }
  }
 },

Here the DOMContentLoaded event is handled in a cross-browser way to make sure that also Internet Explorer will run the code sequence correctly. Anyway, the result will not be exactly the same because some versions of IE don't support the W3C DOM event at all.

This entry was posted in by Gabriele Romanato. Bookmark the permalink.

Leave a Reply

Note: Only a member of this blog may post a comment.