Pregunta jQuery vincula el detector de eventos antes que otro


Utilizando el linda foto complemento para abrir contenedores de contenido de estilo modal e intentar integrar con el seguimiento de eventos de Google Analytics para rastrear cuándo se abren los videos.

El problema es cuando yo

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

el evento nunca se activa, ya que prettyPhoto impide que el evento continúe (con razón, ya que de lo contrario la página cambiaría si se hiciera clic en un hipervínculo).

prettyPhoto no parece proporcionar una función de devolución de llamada 'abierta', pero si lo hiciera, no podría usarlo de todos modos, ya que los oyentes de prettyPhoto están configurados en algún lugar del diseño (lo usamos rel="prettyPhoto" cada vez que queremos usar prettyPhoto, y pasar los parámetros a través de la URL, que es la manera recomendada por prettyPhoto de hacer las cosas). También me gustaría pasar los detalles del producto a Analytics, descartando a un oyente de apertura de video global en todos los eventos de apertura de prettyPhoto.

¿Cómo puedo vincular a mi oyente? antes de el oyente prettyPhoto? Si resulta que tengo que usar .unbind(), luego unir a mi oyente, y luego volver a enlazar prettyPhoto, ¿cómo puedo desvincular un controlador especificado en un complemento?


15
2018-05-17 10:05


origen


Respuestas:


Idealmente, podrías agregar tu enlace de eventos antes de cualquier otro, para que se ejecute primero.

Desafortunadamente, jQuery no parece incluir ninguna de esas facilidades.

Sin embargo, he codificado un método preBind, que parece hacer el truco:

$.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;
};

Uso:

$('#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"

20
2018-06-25 06:02



Estoy usando el método preBind de Jonathan, ligeramente modificado, y funciona muy bien.

$.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;
};

15
2018-05-02 11:47



Trabajó para mí con más viejo y más nuevo jQuery versiones:

/**
 * @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;
};

Pero cuidado, estas funciones solo pueden devolver / preajustar los eventos que se establecieron con jQuery.

Gracias especiales a @jonathanconway y @Patrick ...


6
2017-11-12 16:50



Aquí hay una variante de la solución que utiliza el enfoque .On () más moderno.

// 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;
};

El uso es como

$(document).priorityOn("click blur change", ".some .selector input", function (e) {
    // Your code.
});

5
2017-11-04 06:58



Tuvo que cambiar una línea en el código anterior para que funcione:

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

Esto podría ser porque estoy usando jquery 2.0.3


2
2017-08-22 23:39



si usa unbind (), incluso las vinculaciones creadas por los complementos se desvincularán.


-1
2018-05-17 10:13