Change element ID, but jQuery still fires event calling old ID. Why does this work?

2.6k views Asked by At

I created a fiddle to try to debug a problem I'm having where once I rearrange html elements with jQuery, hover events on those elements don't work anymore.

However, I came across this interesting situation here: http://jsfiddle.net/4yv1trj4/

I have a main div that changes color once I hover over it.

$("#block").hover(function() {
     $(this).css("backgroundColor", "red");
}, function() {
    $(this).css("backgroundColor", "#888");        
});

If you click the button, the main div's ID changes to block2:

$("#block").attr("id","block2");

but $("#block").hover() still fires when I hover over #block2. Also, all hover calls on #block2 do not work. Is there a fundamental principle of how jQuery works that would explain this?

4

There are 4 answers

4
lucasnadalutti On BEST ANSWER

When you do this:

$("#block").hover(function() {
    $(this).css("backgroundColor", "red");
}, function() {
    $(this).css("backgroundColor", "#888");        
});

you're telling jQuery to look for the element with the block ID and bind the hover event to it. Once this is done, the event will remain bound to that element, no matter what happens to its ID afterwards.

That is, unless you have some code that unbinds it, of course.

5
technophobia On

As an extension to lucasnadalutti's answer: It's worth noting that you can add the binding to the container and yield the result you expect:

Example:

$("body").on("mouseenter", "#block", function () {
    $(this).css("backgroundColor", "red");
}).on('mouseleave', "#block", function () {
    $(this).css("backgroundColor", "#888");
});

Notice the binding on the body, not the actual element. A trick to keep in your back pocket.

Demo: jsFiddle


Update:

From the comment section, it's clear a warning is needed - you should bind to the nearest element on the page. body was used here as a simple example.

Although I think this solution would suit you elegantly, you should read Should all jquery events be bound to $(document)? before you start abusing that power.

1
depperm On

If you remove the jQuery hover listener and add a CSS hover, it works the way you want:

#block:hover {
    background-color:red;
    width:300px;
    height:300px;
}
0
GingerBear On

$("#block") is looking for a specific DOM object. .hover() will bind a hover event to that DOM object. $("#block").attr("id","block2"); will change an attribute (id) of that DOM object, but the hover event is still bound to it.