elementReady: a jQuery plugin

Tuesday, 14 August 2007

Please see waitFor, the updated version of elementReady.

I have written a simple but useful jQuery plugin. elementReady calls a function during page load as soon as a specific element is available — even before the full DOM is loaded. It’s useful if you have unobtrusive JavaScript that you want to apply to particular page elements immediately, without having to wait for the whole DOM to load in a large page.

Using the elementReady plugin is very similar to the existing jQuery.ready() function, except that you must also pass in a string representing the ID of the element that should have the function call attached.

This version of the plugin works well for me in testing (and on this page), but it has not been exhaustively tested. I would appreciate your comments on the idea and the implementation.

Download

Get jquery.elementReady.js from the Github project.

Get the latest version from the elementReady jQuery plugin page. Get jquery.elementReady.js here. Then read on for instructions and details.

Documentation for jQuery.elementReady()

$.elementReady( String id, Function fn ) returns jQuery

While a page is loading, call a given callback function as soon as a specific
element is loaded into the DOM, even before the full DOM has been loaded.
Executes the function within the context of the element. This means that when
the passed-in function is executed, the ‘this’ keyword points to the specific
DOM element.

The function returns ‘this’, so you can chain multiple calls to
elementReady(). (Not that there’s much benefit in doing that.)

One argument is passed to the callback: a reference to the jQuery function.
You can name this argument $ and therefore use the $ alias even in
noConflict mode.

If the element has not been found by the time the DOM is fully loaded, then
the function will not be called.

Example:

Change the source of a specific image as soon as it is loaded into the
DOM (before the whole DOM is loaded).

$.elementReady('powerpic', function(){
    this.src = 'powered-by-jquery.png';
});

Example:

If you want to have the jQuery object instead of the regular DOM
element, use the $(this) function.

$.elementReady('header', function(){
    $(this).addClass('fancy');
});

Example:

Chain multiple calls to $.elementReady().

$.elementReady('first',  function(){ $(this).fancify(); })
 .elementReady('second', function(){ $(this).fancify(); });

Example:

Use the ‘$’ alias within your callback, even in noConflict mode.

jQuery.noConflict();
jQuery.elementReady('header', function($){
    $(this).addClass('fancy');
});

Example:

Change the polling interval to 100ms. This only works if $.elementReady() has not yet been called.

$.elementReady.interval_ms = 100;

Why?

I asked about this feature on the jQuery development list, and to my surprise nobody had made much of an effort to do this. jQuery author John Resig has some magic code that makes this happen automatically(!), but including this “auto” feature in the core would complicate things unnecessarily. He suggested that a plugin should be written. So here it is.

Implementation notes

The jQuery.elementReady() function is interesting because it’s quite unlike most other jQuery methods. It’s not a method applied to a normal jQuery object; it can’t be, because a jQuery object is normally constructed from a DOM element (or list of DOM elements). But in this case, all we have is the ID of an element: the element itself does not yet exist.

When the function is called, the matched element is passed to the callback function as a raw DOM element rather than a jQuery object. This is consistent with other event handlers, and is also the most efficient approach.

The function returns the global jQuery object, so you can chain calls to elementReady().

My implementation is inspired by the Yahoo UI library’s onAvailable(), but is simpler (and, to be sure, less well-tested). YUI also includes a related method called onContentReady(), which is supposed to fire when the element and all its content is available. I have not implemented that feature yet, but I think I may end up doing so in elementReady(). This will make it more robust yet still dead simple to use.

I thought about somehow overloading the original ready() function but thought that would just add complexity for no real benefit.

Things to do

This is an early version of the plugin. I’m afraid I have tested it only on Windows browsers, but I have had no problems with it yet. The main thing to do is to test it more thoroughly. As I mentioned above, I also might decide to modify the function to check that the entire contents of the target element are loaded, not just the element itself.

Have your say

Apparently blog posts get x% more comments if the last heading says “Have your say”. So have your say! Is this useful? How can it be improved?

Tags: , ,

231 comments

You can leave a comment, or trackback from your own site.

  1. According to a FT source, Braithwaite was needing to take
    a trip to London on a weekly bssis too obtain her choices
    accepted. Tech Citty UK rejects the claims and states there aare errors in the report.

  2. You’re so cool! I do not think I’ve truly read through something like
    this before. So good to find another person with some original thoughts on this subject
    matter. Really.. thank you for starting this up.
    This site is one thing that is needed on the internet, someone with some originality!

Leave a comment