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.
The onreset event occurs when a form is reset.
That's correct. All event handlers are fired synchronously and in order of binding.
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:
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/)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.
jQuery event delegation to the rescue
$("#container").delegate('#testbutton', 'click',
function(){
alert("Button has been clicked!");
});
Note: .delegate()
is more efficient than .live()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With