0

Possible Duplicate:
JQuery Unbind and then bind

I have a function that performs animations on hover (mouseenter, mouseleave). I am trying to unbind the function (because i dont want the user to interact with it) after I click a button. This works but what I'm having issues with is re-binding the hover function again so that when the user clicks the button again the animations and hover effects are back in use.

Not sure if this is the right way to implement this, but hope I can get some help on this subject. Thanks.

Community
  • 1
  • 1
Guest123894
  • 11
  • 1
  • 2
  • You want to set a blocker variable and detect on `hover` that's toggled with the `button` click. I would suggest `$('#theElement').data('inHover', true)`. Or, alternatively, use a class name and `if ($('#theElement').is('.hoverable')) {... magic happens ...}`. – Jared Farrish Sep 29 '12 at 02:59

2 Answers2

3

continuously unbinding and rebinding is usually not the best approach. It requires more work than is needed.

One option would be to set a class on the element when you hover, and have your other code check for the existence of that class when invoked.

$('.myelem')
    .on("mouseenter", function() {
        $(this).addClass("hovering");
    })
    .on("mouseleave", function() {
        $(this).removeClass("hovering");
    })
    .on("click", function() {
        if ($(this).hasClass("hovering") === false) {
            // run the code
        }
    });

A similar approach would be to add the classes, but use event delegated methods to control the behavior, so that the selector is defined to work on elements that do not have the "hovering" class.

$('.myelem')
    .on("mouseenter", function() {
        $(this).addClass("hovering");
    })
    .on("mouseleave", function() {
        $(this).removeClass("hovering");
    });

$("#container").on("click", ".myelem:not(.hovering)", function() {
    // run the code
});
I Hate Lazy
  • 47,415
  • 13
  • 86
  • 77
  • +1 for good programing approach – StaticVariable Sep 29 '12 at 03:28
  • `$.hasClass()` will always return either a boolean `true` or boolean `false`, so the ` === false` isn't really necessary. Also, you can combine the duplicate `$.on` calls with one and use `$.toggleClass`. I'm a little wary of the last, from a performance standpoint, and I think you mean [`.myelem:not(.hovering)`](http://api.jquery.com/not-selector/), with a `:`. – Jared Farrish Sep 29 '12 at 03:32
  • @JaredFarrish: Yes, my `.not` should be `:not`. I'll update. Thanks. I did the `=== false` for two reasons. First is that I had typed it with a "logical not" operator, but I wanted to be more clear. Second is that I almost always use `===`, merely out of habit. It's a personal coding standard. But you're right, the comparison algorithm will be identical if I use `==` in this situation. I did 2 handlers, because I'm guessing there's more work to do. I could do one, and test the event type, but two seems a little clearer. Also `toggleClass` would require the second arg to make me comfortable. – I Hate Lazy Sep 29 '12 at 03:39
  • ...as in `.toggleClass("hovering", e.type === "mouseenter")` – I Hate Lazy Sep 29 '12 at 03:40
  • Well, that would depend on the way in which it's used. If it's possible for the state to be modified outside of the `toggleClass` calling function, then it might need to be done. So it's not wrong, it's just overdoing it in a "better safe than to be sorry" sort of way. Here's your `:not()` approach in a fiddle: http://jsfiddle.net/3TPzg/1 – Jared Farrish Sep 29 '12 at 03:47
  • @JaredFarrish: Yes, it soothes my paranoia. :) I didn't say it was wrong. I'm just not comfortable with it. I'm afraid that in some mad bout of entering/leaving, something will get skipped and we'll end up in a backward situation. I prefer to be as explicit as possible. – I Hate Lazy Sep 29 '12 at 03:51
  • I know where you're coming from; I've done the same thing in the past. I do it less often now, mostly due to experience and a (hopefully not misguided) belief in my understanding and skills. It can sometimes cause problems, but in many cases it's just simply, like you said, a practical self-check. – Jared Farrish Sep 29 '12 at 03:54
1

Here's a demo of multiple blocking contexts using a class name to keep the element's from reacting to the mouseenter mouseleave:

<div class="highlight">
    Hover Me
    <button type="button">Stop Hoverable</button>
</div>
<div class="highlight">
    Hover Me
    <button type="button">Stop Hoverable</button>
</div>
<div class="highlight">
    Hover Me
    <button type="button">Stop Hoverable</button>
</div>

$('.highlight')
    .on('mouseenter mouseleave', function(){
        if (!$(this).is('canceled')) {
            $(this).toggleClass('hovered');
        }
    })
    .on('click', 'button', function(){
        $(this).parent().toggleClass('canceled');
    });​

http://jsfiddle.net/rRaPB/

This is the line that makes it work:

if (!$(this).is('canceled')) {
Jared Farrish
  • 48,585
  • 17
  • 95
  • 104