jQuery在另一个之前绑定事件监听器

使用prettyPhoto插件打开模态式内容容器,并尝试与Google Analytics的事件跟踪集成,以跟踪video何时打开。

麻烦的是,当我

$('a.videoClickListener').click(function(event){ console.log('here'); _gaq.push(['_trackEvent', 'Product Page', 'Video Open', 'getNameWithManufacturer(); ?>']); }); 

事件永远不会被触发,因为prettyPhoto会阻止事件继续(非常正确,否则如果单击超链接,页面将会更改)。

prettyPhoto似乎没有提供“开放”回调函数,但如果它确实无法使用它,因为prettyPhoto监听器在布局中的某处设置(我们每次使用时都使用rel="prettyPhoto" prettyPhoto,并通过URL传递params,这是prettyPhoto推荐的做事方式)。 我还想将产品详细信息传递给Analytics,排除所有prettyPhoto开幕活动的全球video开放听众。

如何在prettyPhoto监听器之前绑定我的监听器? 如果事实certificate我必须使用.unbind() ,然后绑定我的监听器,然后重新绑定prettyPhoto,我如何取消绑定插件中指定的处理程序?

理想情况下,您可以任何其他事件之前添加事件绑定,以便首先执行它。

不幸的是,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" 

我正在使用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; }; 

使用较旧和较新的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 ......

以下是使用更现代的.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. }); 

不得不在上面的代码中更改一行以使其工作:

  var currentBindings = $this.data('events',type); // var currentBindings = $this.data('events')[type]; 

这可能是因为我使用的是jquery 2.0.3

如果你使用unbind(),那么即使插件所做的绑定也会被解除绑定。