JQuery привязывает прослушиватель событий к другому
Используя плагин prettyPhoto, чтобы открыть контейнеры содержимого в модальном стиле и попытаться интегрироваться с отслеживанием событий Google Analytics, чтобы отслеживать, когда видео открыть.
Проблема в том, что когда я
$('a.videoClickListener').click(function(event){
console.log('here');
_gaq.push(['_trackEvent', 'Product Page', 'Video Open', '<?php echo $product->getNameWithManufacturer(); ?>']);
});
событие никогда не запускается, так как prettyPhoto останавливает событие от продолжения (совершенно справедливо, поскольку в противном случае страница будет меняться при нажатии гиперссылки).
prettyPhoto, похоже, не предоставляет функцию "открытого" обратного вызова, но если бы это было так, я бы все равно не мог ее использовать, поскольку приемники prettyPhoto настроены где-то в макете (мы используем rel="prettyPhoto"
каждый раз, когда хотим используйте prettyPhoto и передайте параметры через URL-адрес, который является довольно популярным способом делать вещи). Я также хотел бы передать детали продукта в Google Analytics, исключая глобального прослушивателя, открывающего видео, через все открытые события prettyPhoto.
Как я могу привязать своего слушателя до приемника prettyPhoto? Если окажется, что я должен использовать .unbind()
, а затем связать свой прослушиватель, а затем переустановить prettyPhoto, как я могу отвязать обработчик, указанный в плагине?
Ответы
Ответ 1
В идеале вы сможете добавить привязку к событиям перед любыми другими, чтобы он выполнялся в первую очередь.
К сожалению, jQuery, похоже, не включает такой объект.
Однако, я закодировал метод preBind, который, похоже, делает трюк:
$.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;
};
Использование:
$('#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"
Ответ 2
Я использую метод Jonathan preBind, слегка измененный, и он прекрасно выполняет трюк.
$.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;
};
Ответ 3
Работала для меня со старыми и новыми версиями jQuery
:
/**
* @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;
};
Но будьте осторожны, эти функции могут только возвращать/предвключать те события, которые были установлены с помощью самого jQuery.
Особая благодарность @jonathanconway и @Patrick...
Ответ 4
Вот вариант решения, использующий более современный подход .On().
// 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;
};
Использование похоже на
$(document).priorityOn("click blur change", ".some .selector input", function (e) {
// Your code.
});
Ответ 5
При необходимости измените одну строку в приведенном выше коде:
var currentBindings = $this.data('events',type); // var currentBindings = $this.data('events')[type];
Это может быть связано с тем, что я использую jquery 2.0.3
Ответ 6
если вы используете unbind(), тогда привязки, сделанные плагинами, будут не привязаны.