Here is a simple piece of code:
HTML:
<div id="close">Click me</div>
JS Code:
$("#close").click(function(){
alert("1");
$(this).attr('id','expand');
});
$("#expand").live('click', function(){
alert("2");
$(this).attr('id','close');
});
Problem: When I click on "close" it automatically calls live() too. See this in jsfiddle: /
Is it because I am changing the same element's id from "close" to "expand"? How do I fix this problem?
I have tried:
$("#expand").die().live('click', function()
but it didn't work. I tried event.stopPropagation() but that didn't help too. I tried having a separate div with id "expand" and hide it on document.ready but for some reason it is not working too.
Then I have tried since I read that live() has been deprecated in jQuery 1.7+:
$("#expand").on('click', function(){
and that is not working too.
Any thoughts? I think a fresh set of eyes will be able to spot what I am missing.
Thanks.
Here is a simple piece of code:
HTML:
<div id="close">Click me</div>
JS Code:
$("#close").click(function(){
alert("1");
$(this).attr('id','expand');
});
$("#expand").live('click', function(){
alert("2");
$(this).attr('id','close');
});
Problem: When I click on "close" it automatically calls live() too. See this in jsfiddle: http://jsfiddle/uFJkg/
Is it because I am changing the same element's id from "close" to "expand"? How do I fix this problem?
I have tried:
$("#expand").die().live('click', function()
but it didn't work. I tried event.stopPropagation() but that didn't help too. I tried having a separate div with id "expand" and hide it on document.ready but for some reason it is not working too.
Then I have tried since I read that live() has been deprecated in jQuery 1.7+:
$("#expand").on('click', function(){
and that is not working too.
Any thoughts? I think a fresh set of eyes will be able to spot what I am missing.
Thanks.
Share Improve this question asked Aug 16, 2012 at 19:38 BlueboyeBlueboye 1,4944 gold badges27 silver badges54 bronze badges 3-
What happens if you
return true;
from your first click function? – Platinum Azure Commented Aug 16, 2012 at 19:40 - You're adding two handlers for the same event, yes? – Brad Commented Aug 16, 2012 at 19:40
- Yeah but I am changing the id of the div. Wouldn't that be considered as a different event then? @Platinum: I am using the on() instead of live() and it is not even being called now. – Blueboye Commented Aug 16, 2012 at 19:42
3 Answers
Reset to default 10You need both delegate event (aka live) handler in this case. Because, you're toggling between both id
s and this toggling make both id
s as dynamic to DOM.
$("body").on("click", "#close", function(){
alert("1");
$(this).attr('id','expand');
});
$("body").on("click", "#expand", function(){
alert("2");
$(this).attr('id','close');
});
DEMO
Note
As live()
is deprecated, so instead of live()
use .on()
for delegate event handling.
This has to do with the way live
attaches events and how event bubbling works.
.live
attaches event handlers to the document
. When the document registers an event, it looks to see what the target
of that event is. If it matches the selector passed to .live
, it fires the handler.
So, when you click on #close
, this is what happens:
- click event registered on
#close
, handler fires. #close
is changed to#expand
- click event bubbles up the DOM until it reaches the
document
- click event registers on
document
, document sees that the ID of the target element is#expand
, and it fires the event handler
The way to solve this is to add stopPropagation()
to your handlers:
$("#close").click(function(e){
if(!e) { e = window.event; }
e.stopPropagation();
alert("1");
$(this).attr('id','expand');
});
However, I would remend not using live
and looking into delegate
or on
to handle delegated events.
I would also remend against changing the ID. I would try something like this if you want to keep the close/expand idea:
<div id="toggler" class="close">Close</div>
$('#toggler').on('click',function() {
$(this).toggleClass('close').toggleClass('expand');
});
One event handler, no delegation because it hooks into the permanent ID
First of all, it's not very clean to change your id's runtime. You're facing one of the results of that.
You might consider using the data-attributes. jQuery can read them by accessing the data property.
Eg.
$("#myObject").data("expanded", true);
In that way it's not necessary to change your id's.