Attaching jQuery event handlers so that they are triggered first
There is a rather nice plugin called jQuery.bind-first that provides analogues of the native on
, bind
, delegate
and live
methods which push an event to the top of the registration queue. It also takes account of differences in event registration between 1.7 and earlier versions. Here's how to use it:
$('button')
.on ('click', function() { /* Runs second */ })
.onFirst('click', function() { /* Runs first */ });
As with most of these answers, the big disadvantage is that it relies on jQuery's internal event registration logic and could easily break if it changes—like it did in version 1.7! It might be better for the longevity of your project to find a solution that doesn't involve hijacking jQuery internals.
In my particular case, I was trying to get two plugins to play nice. I handled it using custom events as described in the documentation for the trigger
method. You may be able to adapt a similar approach to your own circumstances. Here's an example to get you started:
$('button')
.on('click', function() {
// Declare and trigger a "before-click" event.
$(this).trigger('before-click');
// Subsequent code run after the "before-click" events.
})
.on('before-click', function() {
// Run before the main body of the click event.
});
And, in case you need to, here's how to set properties on the event object passed to the handler function and access the result of the last before-click
event to execute:
// Add the click event's pageX and pageY to the before-click event properties.
var beforeClickEvent = $.Event('before-click', { pageX: e.pageX, pageY: e.pageY });
$(this).trigger(beforeClickEvent);
// beforeClickEvent.result holds the return value of the last before-click event.
if (beforeClickEvent.result === 'no-click') return;
Here's a simple plugin I did a while back. Lets you bind a handler to the beginning of the list. It is very simple, and I wouldn't guarantee that it works with namespaced events or anything terribly fancy.
For simply binding a single or space separate group of events, it should work.
Example: http://jsfiddle.net/gbcUy/
$.fn.bindUp = function(type, fn) {
type = type.split(/\s+/);
this.each(function() {
var len = type.length;
while( len-- ) {
$(this).bind(type[len], fn);
var evt = $.data(this, 'events')[type[len]];
evt.splice(0, 0, evt.pop());
}
});
};
Or if you wanted to manipulate the Array of handlers in some other manner, just get the handlers for the element you want, and manipulate it however you want:
Example: http://jsfiddle.net/gbcUy/1/
var clickHandlers = $('img').data('events').click;
clickHandlers.reverse(); // reverse the order of the Array