jQuery слушатель события привязки перед другим - PullRequest
15 голосов
/ 17 мая 2011

Использование плагина prettyPhoto для открытия контейнеров контента в модальном стиле и попытка интеграции с отслеживанием событий Google Analytics для отслеживания открывания видео.

Проблема в том, когда я

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

событие никогда не запускается, так как prettyPhoto останавливает продолжение события (совершенно правильно, так как в противном случае страница изменилась бы, если была нажата гиперссылка).

prettyPhoto, похоже, не обеспечивает'open' функция обратного вызова, но если бы это было так, я бы не смог ее использовать, так как слушатели prettyPhoto настраиваются где-то в макете (мы используем rel="prettyPhoto" каждый раз, когда хотим использовать prettyPhoto, и передаем параметры через URL, который является довольно рекомендуемым способом фотографии).Я также хотел бы передать сведения о продукте в Analytics, исключив глобального слушателя, открывающего видео, во всех событиях открытия prettyPhoto.

Как связать моего слушателя до слушателя prettyPhoto?Если оказывается, что мне нужно использовать .unbind(), затем привязать мой слушатель, а затем повторно привязать prettyPhoto, как я могу отсоединить обработчик, указанный в плагине?

Ответы [ 6 ]

20 голосов
/ 25 июня 2011

В идеале вы могли бы добавить вашу привязку события перед любым другим, чтобы оно выполнялось первым.

К сожалению, в 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"
15 голосов
/ 02 мая 2012

Я использую метод 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;
};
6 голосов
/ 12 ноября 2014

Работал для меня со старыми и более новыми 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 ...

5 голосов
/ 04 ноября 2015

Вот вариант решения с использованием более современного подхода .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.
});
2 голосов
/ 23 августа 2013

Нужно было изменить одну строку в приведенном выше коде, чтобы она заработала:

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

Это может быть потому, что я использую jquery 2.0.3

0 голосов
/ 17 мая 2011

если вы используете unbind (), тогда даже привязки, сделанные плагинами, будут не связаны

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...