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

时间:2011-05-17 10:05:57

标签: 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传递params,这是漂亮的照片推荐的做事方式。我还希望将产品详细信息传递给Analytics,排除所有prettyPhoto开幕活动的全球视频开放听众。

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

6 个答案:

答案 0 :(得分:20)

理想情况下,您可以在之前添加您的事件绑定,以便首先执行。

不幸的是,jQuery似乎没有包含任何此类工具。

但是,我编写了一个preBind method,这似乎可以解决问题:

$.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"

答案 1 :(得分:15)

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

答案 2 :(得分:6)

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

答案 3 :(得分:5)

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

答案 4 :(得分:2)

必须在上面的代码中更改一行才能使其正常工作:

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

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

答案 5 :(得分:-1)

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