It can be anoying that jQuery event handlers always execute in the order they were bound. For example:
$('span').click(doStuff1);
$('span').click(doStuff2);
clicking on the span will cause doStuff1() to fire, followed by doStuff2().
At the time I bind doStuff2(), I would like the option to bind it before doStuff1(), but there doesn’t appear to be any easy way to do this.
I suppose most people would say, just write the code like this:
$('span').click(function (){
doStuff2();
doStuff1();
});
But this is just a simple example – in practise it is not always convienient to do that.
There are situations when you want to bind an event, and the object you are binding to already has events. And in this case you may simply want the new event to fire before any other existing events.
So what is the best way to achieve this in jQuery?
Updated Answer
jQuery changed the location of where events are stored in 1.8. Now you know why it is such a bad idea to mess around with internal APIs 🙂
The new internal API to access to events for a DOM object is available through the global jQuery object, and not tied to each instance, and it takes a DOM element as the first parameter, and a key (“events” for us) as the second parameter.
So here’s the modified code for jQuery 1.8.
And here’s a playground.
Original Answer
As @Sean has discovered, jQuery exposes all event handlers through an element’s
datainterface. Specificallyelement.data('events'). Using this you could always write a simple plugin whereby you could insert any event handler at a specific position.Here’s a simple plugin that does just that to insert a handler at the beginning of the list. You can easily extend this to insert an item at any given position. It’s just array manipulation. But since I haven’t seen jQuery’s source and don’t want to miss out on any jQuery magic from happening, I normally add the handler using
bindfirst, and then reshuffle the array.So for example, for this markup it would work as (example here):
However, since
.data('events')is not part of their public API as far as I know, an update to jQuery could break your code if the underlying representation of attached events changes from an array to something else, for example.Disclaimer: Since anything is possible :), here’s your solution, but I would still err on the side of refactoring your existing code, as just trying to remember the order in which these items were attached can soon get out of hand as you keep adding more and more of these ordered events.