Copie eventos de un elemento a otro usando jquery

5 minutos de lectura

Avatar de usuario de Praveen Prasad
praveen prasad

Tengo DOM es así:

<a href="https://stackoverflow.com/questions/2337521/javascript:void(0)" id='link1'>Element with  events bound initially</a>
<a href="https://stackoverflow.com/questions/2337521/javascript:void(0)" id='link2'>Element to which events are bound in future</a>

Y este javascript:

$(function(){
    $('#link1').bind('click',function(){alert('do something to make me happy');})
});

Ahora, en algún momento en el futuro, quiero copiar todos los eventos vinculados en link1 a link2. Lo estoy haciendo como está escrito a continuación, sugiera una mejor manera si es posible o está disponible.

var _elmEvents = $(#link1).data('events');

if (_elmEvents) {
    $.each(_elmEvents, function (event, handlers) {
        $.each(handlers, function (j, handler) {
            $('#link2').bind(event, handler);
        });
    });
}

  • Para cualquiera de los comentarios que se solicitan a continuación, es importante que tenga en cuenta que jQuery ahora ha cambiado y para obtener los eventos en un elemento debe usar $._data ($ (“# foo”)[0], “eventos” ). (Funciona a partir de jQuery v2.1.4) De lo contrario, recibirá indefinido de cualquiera de los métodos a continuación. Para referencia, consulte: stackoverflow.com/questions/2008592/…

    – Zanderi

    22 de junio de 2015 a las 21:34


Avatar de usuario de BBonifield
BBonifield

Si desea copiar todos los eventos de un objeto a otro sin clonarlos, puede hacerlo accediendo directamente a los datos de los eventos.

Por ejemplo, si hiciste:

$("#the_link").click(function(e){
    // do some stuff
    return false;
}).mouseover(function(e){
    // do some other stuff
});

Puede acceder a esos eventos asociados en los datos de ‘eventos’ del elemento

var events = $("#the_link").data('events');

Será un objeto cuyas claves representan el tipo de evento, cada una de las cuales contiene una matriz de asociaciones de eventos. Independientemente, aquí hay un ejemplo simple, sin tener en cuenta los espacios de nombres.

var events = $("#the_link").data('events');
var $other_link = $("#other_link");
if ( events ) {
    for ( var eventType in events ) {
        for ( var idx in events[eventType] ) {
            // this will essentially do $other_link.click( fn ) for each bound event
            $other_link[ eventType ]( events[eventType][idx].handler );
        }
    }
}

  • Esta solución no funcionó para mí y no tiene en cuenta los espacios de nombres de eventos. Agregué una nueva respuesta que los maneja (y funciona en mi caso).

    – Germán Latorre

    5 de junio de 2013 a las 15:51

  • ¿Por qué esto será devuelto “indefinido” para mí? alert($("#a").data('events')); ?! ver: jsfiddle.net/NabiKAZ/mbkL6gp3/1

    – Nabi Kaz

    30 de abril de 2020 a las 1:42


Este funcionó muy bien en mi guión.

$.each($('#original').data('events'), function() {
  // iterate registered handler of original
  $.each(this, function() {
    $('#target').bind(this.type, this.handler);
  });
});

Lo encontré aquí (fuente): http://snipplr.com/view/64750/

  • Funciona bien, pero tal vez sea necesario reemplazar el primer parámetro: vea el comentario de Zanderi debajo de la pregunta. (Gracias a ambos.)

    – Mirek

    12 de agosto de 2019 a las 14:26

  • ¿Por qué esto será devuelto “indefinido” para mí? alert($("#a").data('events')); ?! ver: jsfiddle.net/NabiKAZ/mbkL6gp3/1

    – Nabi Kaz

    30 de abril de 2020 a las 1:44

Avatar de usuario de Germán Latorre
Germán Latorre

La respuesta aceptada no me funcionó como uso espacios de nombres y otros eventos (como “pegar”) que no son un método en jQuery.

Esto funcionó para mí:

function copyEvents(source, destination) {
    // Get source events
    var events = source.data('events');

    // Iterate through all event types
    $.each(events, function(eventType, eventArray) {
        // Iterate through every bound handler
        $.each(eventArray, function(index, event) {
            // Take event namespaces into account
            var eventToBind = event.namespace.length > 0
                ? (event.type + '.' + event.namespace)
                : (event.type);

            // Bind event
            destination.bind(eventToBind, event.data, event.handler);
        });
    });
}

avatar de usuario de noah
Noé

Puedes clon un elemento y manipule el nuevo elemento como desee, sin embargo, jQuery no proporciona una manera fácil de copiar controladores de eventos de un elemento a otro. Sin embargo, el código que lo haría sería:

var events = jQuery.data( originalElement, "events" );

for ( var type in events ) {
    for ( var handler in events[ type ] ) {
        jQuery.event.add( targetElement, type, events[ type ][ handler ], events[ type ][ handler ].data );
    }
}

Pero dado que depende un poco de los elementos internos de jQuery, intentaría hacer una solución usando clon.

avatar de usuario de yckart
yckart

Esto se basa en Brandons funciona, pero se actualizó para que funcione con todas las versiones de jQuery. Probado en 1.6.4 hasta 2.0.x.

/**
 * Logic for copying events from one jQuery object to another.
 *
 * @private 
 * @name jQuery.event.copy
 * @param jQuery|String|DOM Element jQuery object to copy events from. Only uses the first matched element.
 * @param jQuery|String|DOM Element jQuery object to copy events to. Copies to all matched elements.
 * @type undefined
 * @cat Plugins/copyEvents
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * @author Yannick Albert (mail@yckart.com || http://yckart.com)
 */
jQuery.event.copy = function (from, to) {
    from = from.jquery ? from : jQuery(from);
    to = to.jquery ? to : jQuery(to);

    var events = from[0].events || jQuery.data(from[0], "events") || jQuery._data(from[0], "events");
    if (!from.length || !to.length || !events) return;

    return to.each(function () {
        for (var type in events)
        for (var handler in events[type])
        jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
    });
};

Avatar de usuario de Danijel
Danijel

Respuesta @Rikco editada de acuerdo con un jquery más nuevo.

function assingEvents() {
     //if you have multiple just use jQuery._data(jQuery('.copy-from-single-item')[0]
     jQuery.each(jQuery._data(jQuery('.copy-from-single-item'), 'events'), function()  {
       // iterate registered handler of original
       jQuery.each(this, function() {
        var parentEvent = this;
        jQuery.each(jQuery('.copy-to-multiple-item'),
            function() {
                jQuery(this).bind(parentEvent.type, parentEvent.handler);
            });
       });
    });
}

Timur.  Avatar de usuario de Z
Timur. Z

$.fn.copyEvents = function( to, filter )
{
    var to = to.jquery ? to : jQuery(to);
    var filter = filter ? filter.split(" ") : null;
    var events = this[0].events || jQuery.data(this[0], "events") || jQuery._data(this[0], "events");

    return this.each(function()
    {
        if (!to.length || !events) {
            return;
        }

        $.each(events, function(eventType, eventArray) {
            $.each(eventArray, function(index, event) {
                var eventToBind = event.namespace.length > 0
                    ? (event.type + '.' + event.namespace)
                    : (event.type);
                if (filter && $.inArray(eventToBind, filter) == -1) {
                    return true;
                }
                to.bind(eventToBind, event.data, event.handler);
            });
        });
    });
}

// Add some events to a element
$('#element').click(function() { });
$('#element').dblclick(function() { });
$('#element').change(function() { });

// Default usage, copy *all* events from one element to another
$('#element').copyEvents('#another-element');

// ... or you can copy only specific event types
$('#element').copyEvents('#another-element', 'change click');

el original esta aqui https://blog.armin-pfaeffle.de/2014/08/jquery-copy-events-from-one-element-to-other

¿Ha sido útil esta solución?