Events not registering after replaceWith
Asked Answered
P

3

19

When I replaceWith an element to bring one out of the DOM, then replaceWith it back in, events registered to it do not fire. I need to events to remain intact.

Here's my Javascript:

var replacement = $(document.createElement('span'));
var original = $(this).replaceWith(replacement);

replacement
    .css('background-color', 'green')
    .text('replacement for ' + $(this).text())
    .click(function() {
        replacement.replaceWith(original);
    });

Live demo

In the demo, when you click an element, it is replaced with another element using replaceWith. When you click the new element, that is replaced with the original element using replaceWith. However, the click handler does not work any more (where I would think it should).

Pandolfi answered 20/4, 2009 at 22:7 Comment(2)
Did you end up using the event reattachment, or were you ever able to get Live events to work? I am doing the exact same thing, and would love to learn from your experience.Untruth
@Erick T, I'm sorry, but I honestly cannot remember. I asked this question almost two years ago. I think using $.fn.live didn't work because I was dealing with actual elements, not a selector. ($.fn.delegate (which didn't exist then) may work for you as a live alternative.) Because of the answer I selected, I assume I did end up re-attaching the event handler. You may try deep cloning the element as well (which IIRC may keep event handlers in the latest jQuery).Pandolfi
N
13

Because when you replace the original element, events bound to it are removed. You'll need to re-attach the click event handler on original after the call to replacement.replaceWith(original):

$(function() 
{   
   function replace() 
   {
      var replacement = $(document.createElement('span'));
      var original = $(this).replaceWith(replacement);

      replacement
         .css('background-color', 'green')
         .text('replacement for ' + $(this).text())
         .click(function() 
         {
            replacement.replaceWith(original);
            original.click(replace);
         });
   }

   $('.x').click(replace);
});
Nassir answered 20/4, 2009 at 22:15 Comment(4)
I wish there were an automatic/elegant way of doing this. I guess this solution will have to do.Pandolfi
@strager: You could try Matt's live events suggestion, or implement a targeted version for your own purposes. There are serious (and unpleasant) side-effects in certain browsers if you fail to detach events from detached elements, so you really do want it to work this way.Nassir
This does not make sense. Elements can have events without being attached to the DOM, so why would removing them from the DOM remove the events? Must be some performance specific decisions, well well...Transferase
I would also point you to this alternative code to replace elements without losing the bound events:bugs.jquery.com/ticket/13400#comment:10Sakai
F
4

UPDATE: live() and bind() have been deprecated, in favour of on().

You can use live() and bind() events, this is your new code:

$(function() {
$('.x').live('click', function() {
    var replacement = $(document.createElement('span'));
    var original = $(this).replaceWith(replacement);

    replacement
        .css('background-color', 'green')
        .text('replacement for ' + $(this).text())
        .bind('click', function() {
            replacement.replaceWith(original);
        });
});
});

-Live event works with jQuery 1.3 and upper.

-if you want to stop the live propagation use die() function.

Figueroa answered 20/4, 2009 at 22:7 Comment(0)
L
3

live events are what you are looking for

Larder answered 20/4, 2009 at 23:53 Comment(2)
May be what I need. I'll look into it.Pandolfi
deprecated, actually removed from jquery, and replaced with on()Clea

© 2022 - 2024 — McMap. All rights reserved.