Using the prettyPhoto plugin to open modal-style content containers, and trying to integrate with Google Analytics\' Event Tracking to track when videos get opened.
Had to change one line in the above code to make it work:
var currentBindings = $this.data('events',type); // var currentBindings = $this.data('events')[type];
This could be because I am using jquery 2.0.3
Here is a variant of the solution using the more modern .On() approach.
// Same as .on() but moves the binding to the front of the queue.
$.fn.priorityOn = function (type, selector, data, fn) {
this.each(function () {
var $this = $(this);
var types = type.split(" ");
for (var t in types) {
$this.on(types[t], selector, data, fn);
var currentBindings = $._data(this, 'events')[types[t]];
if ($.isArray(currentBindings)) {
currentBindings.unshift(currentBindings.pop());
}
}
});
return this;
};
Usage is like
$(document).priorityOn("click blur change", ".some .selector input", function (e) {
// Your code.
});
Worked for me with older and newer jQuery
versions:
/**
* @link http://stackoverflow.com/a/26892146/655224
*/
jQuery.fn.getEvents = function() {
if (typeof(jQuery._data) == 'function') {
return jQuery._data(this.get(0), 'events') || {};
} else if (typeof(this.data) == 'function') { // jQuery version < 1.7.?
return this.data('events') || {};
}
return {};
};
jQuery.fn.preBind = function(type, data, fn) {
this.each(function () {
var $this = jQuery(this);
$this.bind(type, data, fn);
var currentBindings = $this.getEvents()[type];
if (jQuery.isArray(currentBindings)) {
currentBindings.unshift(currentBindings.pop());
}
});
return this;
};
But beware, this functions can only return/prebind that events that was set with jQuery itself.
Special thanks to @jonathanconway and @Patrick...
if you use unbind() then even the bindings made by plugins will be unbinded.
Ideally, you would be able to add your event binding before any others, so that it executes first.
Unfortunately, jQuery doesn't seem to include any such facility.
However, I've coded a preBind method, which seems to do the trick:
$.fn.preBind = function(type, data, fn) {
this.bind(type, data, fn);
var currentBindings = this.data('events')[type];
var currentBindingsLastIndex = currentBindings.length - 1;
var newBindings = [];
newBindings.push(currentBindings[currentBindingsLastIndex]);
$.each(currentBindings, function (index) {
if (index < currentBindingsLastIndex)
newBindings.push(this);
});
this.data('events')[type] = newBindings;
return this;
};
Usage:
$('#button').bind('click', function() {
console.log('world');
});
// 2nd apostrophe for the selector was missing
$('#button').preBind('click', function() {
console.log('hello');
});
$('#button').click();
// Output:
//
// > "hello"
// > "world"
I'm using Jonathan's preBind method, slightly modified, and it does the trick nicely.
$.fn.preBind = function (type, data, fn) {
this.each(function () {
var $this = $(this);
$this.bind(type, data, fn);
var currentBindings = $this.data('events')[type];
if ($.isArray(currentBindings)) {
currentBindings.unshift(currentBindings.pop());
}
});
return this;
};