a practical example of using custom events in jQuery

I’ve recently been converted to the practice of using jQuery custom events. At first I didn’t really see the point but then as time wore on it started to dawn on me how much more extensible it made the jQuery plug-in architecture and allowed a level of pseudo MVC, where the DOM translates literally into your view.

The example I’m going to illustrate it’s usefulness is a simple drag and drop, I recently found myself having to re-implement a drag and drop plug-in in jQuery as the standard UI plug-in although quick to implement was simply not very performant due to the incredible amount of configurability it has.

At first taking from the jQuery UI drag and drop template I started off with an implementation that was invoked by calling the following:

$("foo").dragLite({

containment : "parent",

axis : "xy",

startDrag: function() {foo.bar},

stopDrag: function() {foo.bar}

});

Pretty familiar stuff, like what you’d see on 99% of plug-ins.  So as the age old adage goes “If it ain’t broke…” until another developer came along a few months later and said “I want to hook into your stopDrag event”.

UH OH.

Well, you could do, but the only way to do that is to edit my original initialisation call and add in a call to your function in my anonymous function, which you could do, but is pretty messy, creates two fairly deep dependencies and could mean that if either of our code breaks, the functionality will not fail in a graceful way…

Clink. The penny drops. For the last few months, some people at work, some people on the web (dean edwards for one wrote an interesting post), and random tramps I met on the street, had been banging on and on about the custom event functionality in jQuery and this was why.

In my first example, I had had to pass my anon function into the last function through the initialise code, so my plug-in code looked something like this:

var dragStopped = function(event) {

//some stop drag code here

if(event.data.stopDrag) {

//execute the call back

event.data.stopDrag();

}

}

which as mentioned before means if anyone wants to add in an additional call back they have to do this:

$("foo").dragLite({

containment : "parent",

axis : "xy",

startDrag: function() {foo.bar();},

stopDrag: function() {foo.bar(); someOtherClass.someOtherCallBack();}

});

However, what if we abandon callbacks for custom events instead, so the plug-in code becomes:

var dragStopped = function(event) {

//some stop drag code here

//trigger custom event bindings

$(this).trigger("dragLite.stopDrag");

}

which won’t fail if we have no functions bound and our initialisation call becomes this

$("foo").dragLite({

containment : "parent",

axis : "xy"

}).bind("dragLite.stopDrag",foo.bar) ;

then all my other developer has to do in his code is

$("foo").bind("dragLite.stopDrag", someOtherClass.someOtherCallBack) ;

which he can do anywhere in the code, independent of whether the drag functionality has been implemented yet.

Pretty Neat, and most definitely worth doing for increased stability, better code flow and less work for you!

Leave a Reply