Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript event missing after html reset

I have a situation where at one point the html contents of a div are changed to something else, and then are changed back. Some of jquery ui controls are misbehaving. I've reduced the problem to the following snippet, which basically shows that the event handler associated with the button doesn't fire anymore. I am assuming that these were garbage collected at some point when they were gone. So my question is -

How do I prevent event handlers from being garbage collected when they are missing from the DOM?

I understand that I could just reassign the click() function, but since I'm using an external library (jquery ui), i don't really know what's it doing with my controls. I'd just want their events restored as they were before.

<div id="container">
    <p>This container has a button, which will forget its click()...</p>
    <input id="testbutton" type="button" value="Click Me!"/>
</div>

<script type="text/javascript">
    $(function(){ 
        $("#testbutton").click(
            function(){
                alert("Button has been clicked!");
        })
    });
</script>

<div>
    <p>... when this button reseats html</p>
    <input id="actionbutton" type="button" value="Toggle"/>
</div>

<script type="text/javascript">
    var toggle = false;
    var html;
    $(function(){ 
        $("#actionbutton").click(
            function(){
                toggle = !toggle;
                if(toggle){
                    html = $("#container").html();
                    $("#container").html("");
                } else  $("#container").html(html);
        })
    });
</script>

This jfiddle demonstrates the problem that I'm having.

like image 865
Gleno Avatar asked Aug 09 '11 15:08

Gleno


People also ask

Which event occurs when the page is reset?

The onreset event occurs when a form is reset.

Are JavaScript events synchronous?

That's correct. All event handlers are fired synchronously and in order of binding.


2 Answers

Simple answer: use .live

$(function(){ 
    $("#testbutton").live('click',
        function(){
            alert("Button has been clicked!");
    })
});

Here's the updated fiddle: http://jsfiddle.net/mrchief/8S5E4/1/

Explanation: When you alter the DOM, event handlers attached the element are also removed. Using .live attaches the event handlers to 'body' (and filters by DOM element) so that it 'lives' even after removing/adding the same DOM element.

You can achieve the same effect using .delegate also:

$(function(){ 
    $('#container').delegate('#testbutton', 'click',
        function(){
            alert("Button has been clicked!");
    })
});

fiddle using .delegate: http://jsfiddle.net/mrchief/8S5E4/6/

I would recommend using .delegate over .live for:

  • You can cancel event bubbling. When you use live, the event bubbles up all the way to body and then your handler gets called, so there is no way to cancel its bubbling. (As of jQuery 1.4, this can be prevented by using a context argument: http://api.jquery.com/live/)
  • Since you're attaching to a DOM element specifically, it doesn't get invoked everytime there is a click on any other DOM element on body and hence, is more performant as it has to do less work now.

Here's a great article that beautifully explains the differences between live, delegate and bind and discusses about the nuances of each approach. Thanks to @andyb for pointing this link out.

like image 160
Mrchief Avatar answered Oct 31 '22 04:10

Mrchief


jQuery event delegation to the rescue

$("#container").delegate('#testbutton', 'click',
    function(){
        alert("Button has been clicked!");
});

Note: .delegate() is more efficient than .live()

like image 31
andyb Avatar answered Oct 31 '22 05:10

andyb