Копирование событий из одного элемента в другой с помощью jquery

У меня DOM выглядит так:

<a href='javascript:void(0)' id='link1'>Element with  events bound initially</a>
<a href='javascript:void(0)' id='link2'>Element to which events are bound in future</a>

И этот javascript:

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

Теперь, в будущем, я хочу скопировать все события, связанные с link1 в link2. Я делаю это, как указано ниже, предложите лучший способ, если это возможно или доступно.

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

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

Ответы

Ответ 1

Если вы хотите скопировать все события из одного объекта в другой без клонирования, вы можете сделать это, напрямую обратившись к данным событий.

Например, если вы это сделали:

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

Вы можете получить доступ к этим ассоциациям событий в данных "событий" элемента

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

Это будет объект, ключи которого представляют тип события, каждый из которых содержит массив ассоциаций событий. Независимо от того, здесь простой пример, не учитывающий пространства имен.

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

Ответ 2

Принятый ответ не работал у меня, поскольку я использую пространства имен и другие события (например, "вставить" ), которые не являются методом в jQuery.

Это сработало для меня:

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

Ответ 4

Вы можете clone элемент и управлять новым элементом, но хотите, однако jQuery не обеспечивает простой способ копирования обработчиков событий от одного элемента к другому. Однако код, который будет делать это, будет:

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

Но поскольку он полагается на внутренние элементы jQuery, я попытался бы сделать решение с помощью clone.

Ответ 5

Это хорошо работало в моем script.

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

Я нашел его здесь (источник): http://snipplr.com/view/64750/

Ответ 6

Это основано на Brandons, но обновлено для работы со всеми версиями jQuery. Протестировано на 1.6.4 до 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 ([email protected] || http://brandonaaron.net)
 * @author Yannick Albert ([email protected] || 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);
    });
};