Is there a way to attach a jQuery event handler such that the handler is triggered before any previously-attached event handlers? I came across this article, but the code d
In addition to the selected answer, consider it's missing parameters:
jQuery.fn.bindUp = function (type, parameters, fn) {
type = type.split(/\s+/);
this.each(function () {
var len = type.length;
while (len--) {
if (typeof parameters === "function")
jQuery(this).bind(type[len], parameters);
else
jQuery(this).bind(type[len], parameters, fn);
var evt = jQuery._data(this, 'events')[type[len]];
evt.splice(0, 0, evt.pop());
}
});
};
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
Here's a combination of some prior methods including support for handlers, namespacing, non-jquery bindings, and once support:
$.fn.oneFirst = function(event_type, event_callback, handler) {
return this.bindFirst(event_type, event_callback, handler, "one");
},
$.fn.bindFirst = function(event_type, event_callback, handler, bind_type) {
var event_types = event_type.split(/\s+/);
var pos;
handler = (handler == undefined ? event_callback : handler);
event_callback = (typeof event_callback == "function" ? {} : event_callback);
this.each(function() {
var $this = $(this);
for (var i in event_types) { // each bound type
event_type = event_types[i];
var event_namespace = ((pos = event_type.indexOf(".")) > 0 ? event_type.substring(pos) : "");
event_type = (pos > 0 ? event_type.substring(0, pos) : event_type);
var current_attr_listener = this["on" + event_type];
if (current_attr_listener) { // support non-jquery binded events
$this.bind(event_type, function(e) {
return current_attr_listener(e.originalEvent);
});
this["on" + event_type] = null;
}
if (bind_type == "one") {
$this.one(event_type + event_namespace, event_callback, handler);
}
else {
$this.bind(event_type + event_namespace, event_callback, handler);
}
var all_events = $.data(this, 'events') || $._data(this).events;
var type_events = all_events[event_type];
var new_event = type_events.pop();
type_events.unshift(new_event);
}
});
};