views:

2293

answers:

6

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.

+12  A: 

For javascript code I found the following links from Christian Heilmann indispensable

I also really like the method described by Peter Michaux here

For jQuery, I heartily reccomend reading the guides on Authoring and I found this tutorial on jQuery plugin patterns very good

Steerpike
+1 for recommending the authoring link. I must for newbies.
bendewey
I do like the authoring link (which I have to thank you for), but I have to admit I'm not a big fan of the way jQuery plugins do exposing public methods. I think I just find Christian's method of exposing a single public object or Paul's public returns clearer to read.
Steerpike
Christian just pointed me to another option for the module, even more elegant:http://www.wait-till-i.com/2007/08/22/again-with-the-module-pattern-reveal-something-to-the-world/
Matt Gardner
A: 

Jeff actually has a very good post regarding this on Coding Horror; Code Smells

Gary Green
+1  A: 

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.

John MacIntyre
+3  A: 

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' );
meouw
+3  A: 

I definitely recommend reading up on the object literal pattern in addition to the module pattern; here's a good writeup:

http://ajaxian.com/archives/show-love-to-the-object-literal

rmurphey
+1  A: 
(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);