How to structure my javascript/jquery code?

Viewed 24704

I am toying around with a pretty intensive ajax based jquery web application. It is getting to a point where I almost loose track of what events that should trigger what actions etc.

I am sort of left with a feeling that my javascript structure is wrong, on a more basic level. How do you guys structure your javascript/jquery code, the event handling etc., any advise for a newbie javascript developer.

10 Answers

To keep my events in control I use a publish/subscribe mechanism

jQuery.subscribe = function( eventName, obj, method ){
    $(window).bind( eventName, function() {
        obj[method].apply( obj, Array.prototype.slice.call( arguments, 1 ) );
    });
    return jQuery;
}

jQuery.publish = function(eventName){
    $( window ).trigger( eventName, Array.prototype.slice.call( arguments, 1 ) );
    return jQuery;
}

Here's an example of its use

// a couple of objects to work with
var myObj = {
    method1: function( arg ) {
        alert( 'myObj::method1 says: '+arg );
    },
    method2: function( arg1, arg2 ) {
        alert( arg1 );
        //republish
        $.publish( 'anEventNameIMadeUp', arg2 );
    }
}

var myOtherObj = {
    say: function(arg){
        alert('myOtherObj::say says: ' + arg);
    }
}



// you can then have all your event connections in one place

//myObj::method2 is now listening for the 'start' event 
$.subscribe( 'start', myObj, 'method2' );

//myOtherObj::say is now listening for the 'another' event
$.subscribe( 'anotherEvent', myOtherObj, 'say' );

//myObj::method1 is now listening for the 'anEventNameIMadeUp' event
$.subscribe( 'anEventNameIMadeUp', myObj, 'method1' );
//so is myOtherObj::say
$.subscribe( 'anEventNameIMadeUp', myOtherObj, 'say' );


// ok, trigger some events (this could happen anywhere)
$.publish( 'start', 'message1', 'message2' );
$.publish( 'anotherEvent', 'another message' );
(function($, window, slice)
{

    $.subscribe = function(eventName, obj, method)
    {
        $(window).bind(eventName, function()
        {
            obj[method].apply(obj, slice.call(arguments, 1));
        });
        return $;
    };

    $.publish = function(eventName)
    {
        $(window).trigger(eventName, slice.call(arguments, 1));
        return jQuery;
    };

})(jQuery, window, Array.prototype.slice);

To add to the existing answers, here's a great post that covers more advanced techniques that build on the Module Pattern.

Once your Javascript code reaches a certain size, you'll inevitably want to refactor it by breaking it into multiple files / modules / sub-modules. If you're not sure how to accomplish this using the module pattern, this article is a must-read.

My js files usually follow a naming convention similar to this :

  • xxx.utility.js
  • mypage.events.js
  • xxx.common.js
  • /lib/
  • /OS-DoNotDistribute/lib/

Where

  • 'mypage' is the name of the html, aspx, php, etc file.
  • 'xxx' is the concept. (i.e. orders.common.js)
  • 'utility' signifies it's a reusable library script (i.e. ajax.utility.js, controlfader.utility.js)
  • 'common' is reusable functionality for this app, but not reusable across other projects
  • 'lib' is a subdirectory for any external or library scripts
  • 'OS-DoNotDistribute' is a subdirectory to ensure no OS licensed code is distributed if the app is ever sold.

Also, for ajax, I have a special naming convention for call back functions, so it's easy to tell what they are.

I'm not sure it that's close to what you were looking for, but I hope it helps.

Related