Home > javascript, jquery > Markup-based unobtrusive comprehensive DOM-ready execution

Markup-based unobtrusive comprehensive DOM-ready execution

March 11th, 2009

On a recent project I took my previous approach to automating firing of onload events to a new level.

For instance if your code was architected in an object literal such as:

 
FOO = {
  common : {
    init     : function(){ ... },
    finalize : function(){ ... }
  },
  shopping : {
    init     : function(){ ... },
    cart     : function(){ ... },
    category : function(){ ... }
  }
}

A page with this body tag:

<body id="cart" class="shopping">

would load these functions sequentially:

UTIL.fire is calling: FOO.common.init()
UTIL.fire is calling: FOO.shopping.init()
UTIL.fire is calling: FOO.shopping.cart()
UTIL.fire is calling: FOO.common.finalize()

In addition, using these classes and IDs on the body tag provides some excellent specific hooks for your CSS.

The javascript:

UTIL = {
 
  fire : function(func,funcname, args){
 
    var namespace = FOO;  // indicate your obj literal namespace here
 
    funcname = (funcname === undefined) ? 'init' : funcname;
    if (func !== '' && namespace[func] && typeof namespace[func][funcname] == 'function'){
      namespace[func][funcname](args);
    } 
 
  }, 
 
  loadEvents : function(){
 
    var bodyId = document.body.id;
 
    // hit up common first.
    UTIL.fire('common');
 
    // do all the classes too.
    $.each(document.body.className.split(/\s+/),function(i,classnm){
      UTIL.fire(classnm);
      UTIL.fire(classnm,bodyId);
    });
 
    UTIL.fire('common','finalize');
 
  } 
 
}; 
 
// kick it all off here 
$(document).ready(UTIL.loadEvents);

This system worked very well and keeps you in serious control of the execution order.

In the end, I used this plus a custom event to bind super low priority script.
For example:

$(document).bind('finalized',function(){ ... }); // placed within a FOO.shopping.category()

And I'd trigger that

$(document).trigger('finalized');

at the very end of UTIL.loadEvents(). This allows you to keep similar code together, but delay portions responsibly without any setTimeout ugliness.

Paul Irish javascript, jquery

  1. redsquare
    | #1

    Nice Paul, Just starting a greenfield app and have used a variation of this, rather than using body id and class I have used the rest url peices
    e.g appName/Controller/Action - this provides me with common (appName), then more specific implementations using controller and finally the action. Seems to be working good although only a few hours into it. I hope this will spare the developers having to remember to specify body id and class. Any thoughts / issues with this?

  2. | #2

    @redsquare,
    Ah that's pretty nice. I would only go that route if you're confident the URL structure doesn't need to change and you don't have any SEO needs out of the site.

  3. | #3

    This is an excellent solution. Just tested out on one current project and the application feels much smoother

Comments are closed.