9

I have a list of several 'triggers' (<li>s), each trigger shows a specific DIV, and each DIV has 'close' button.

Now, I want to improve the usability by adding a timer/delay to the opened/visible DIV so that after3 or 5 seconds after the user has moved his mouse away from the trigger, the opened/visible DIV fades out.

The problem I'm having right now, is that whenever I add a function with .mouseleave(), the opened/visible DIV hides as soon as the mouse leaves the trigger area.

However, if you remove the function, then the DIV stays visible and you're able to close it by clicking the close button.

Here's a FIDDLE/DEMO of my situation.

Any help would be greatly appreciated.

Thanks.

Ricardo Zea
  • 10,053
  • 13
  • 76
  • 79

3 Answers3

11

@locrizak's answer is right (+1). This is because .delay() defaults to the effects queue, but .hide() with no parameters hides the selected elements without any effect, so the effects queue isn't involved at all.

If you want to hide without any animation, just use setTimeout:

$('.trigger').mouseleave(function() {
    setTimeout(function () {
        $('.copy .wrapper').hide();
    }, 3000);
});

http://jsfiddle.net/mattball/93F3k/


Last edit, I promise

//Show-Hide divs
var current;
$('.trigger').live('mouseenter', function() {    
    var id = current = $(this).data('code');
    $('#' + id).show().siblings().fadeOut();
}).live('mouseleave', function() {
    var id = $(this).data('code');
    current = null;
    setTimeout(function ()
    {
        if (current !== id) $('#' + id).hide(1);
    }, 3000);
});

//Close button
$('.copy .wrapper span').live('click', function() {
    $(this).closest('.wrapper').stop(true, true).fadeOut();
});

Demo: http://jsfiddle.net/mattball/b2ew5/

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • Matt, thanks. I used your setTimeout function but it didn't work, although I wasn't sure if I should've put it inside the $('.trigger').hover(function() or outside. Tnx. – Ricardo Zea Jun 06 '11 at 17:55
  • I don't understand your confusion. Did you look at the jsFiddle? – Matt Ball Jun 06 '11 at 17:56
  • It almost works 100%. The problem is that if you hover over the next item after having hovered over another one first but the initial wrapper hasn't faded out yet, then both wrappers fade out at the same time, and after that if you hover over any trigger, its corresponding wrapper fades out after a second has passed even if you leave your mouse over the trigger. Thanks. – Ricardo Zea Jun 07 '11 at 21:31
  • Something else. Just hover up and down over all the triggers and you'll see what I mean. – Ricardo Zea Jun 07 '11 at 21:39
  • See my edit, what do you think? Do you want the other `.copy .wrapper` elements to hide immediately when you hover over a different `.trigger`? like this: http://jsfiddle.net/mattball/T6YUp/1/ – Matt Ball Jun 07 '11 at 21:40
  • Yes, that's correct Matt. Any other `.wrapper` that's visible should hide immediately, which is what's happening in your example. However, there are still 2 problems there: 1. Hovering up and down the triggers makes the wrappers disappear after a second after leaving the trigger element. And 2. The Close button doesn't close the the `.wrapper`. Tnx. – Ricardo Zea Jun 07 '11 at 21:53
  • Let me add that problem #1 happens randomly, you just have to hover up and down and at some point you'll see the `.wrapper` disappear almost immediately after leaving the `.trigger`, when it should be 3 seconds after. Tnx again. – Ricardo Zea Jun 07 '11 at 21:55
  • 1
    BTW, don't call `.click()` inside of `.hover()` since that will rebind the `click` handler every time. – Matt Ball Jun 07 '11 at 21:57
  • Hey Matt, your example worked great! That's exactly what I needed. Thanks a lot for your time and advice. Yeah, now that I look at it I don't see a need to call `.click()` inside the `.hover()`. Tnx again! – Ricardo Zea Jun 08 '11 at 16:31
  • Hey Matt... is it me or for some reason the wrappers are not hiding at all now in your example? I tried reloading the page too but nothing. o_O – Ricardo Zea Jun 08 '11 at 16:37
  • You're right, it's because I switched from `.hover(...)` to `.live('hover', ...)` but didn't write the callback correctly. I'm such a dunce! Anyway, it's fixed now, see the edit. – Matt Ball Jun 08 '11 at 16:53
  • Absolutely perfect! Tnx again Matt :) – Ricardo Zea Jun 08 '11 at 17:20
  • Hey Matt, you're going to kill me ^_^, but I there's a small problem: again, if you hover in and out real fast and several times over the triggers, and then stop and simply hover over any trigger, the wrapper appears but it then hides even if your mouse is over a trigger. Amigo Matt, you've invested a lot of time on this already, if you don't want to mess around with this anymore, no worries, all's cool, I totally understand. I wish I could be of more help than just troubleshooting, but as you can see I'm not that proficient at jQuery yet. Tnx again. – Ricardo Zea Jun 08 '11 at 17:34
  • 1
    Hm, I don't think I can reproduce the problem, but I'll take a guess. Does this work any better for you? http://jsfiddle.net/mattball/b2ew5/ – Matt Ball Jun 08 '11 at 18:03
  • Yep, somehow that got rid of the problem. Thank you very much :) – Ricardo Zea Jun 08 '11 at 20:22
3

you need a duration in the hide:

$('.copy .wrapper').delay(3000).hide('fast');

You can take a look at the docs http://api.jquery.com/delay/

update

is this what your looking for?

$('.trigger').bind("mouseenter" , function() {    
    var id = $(this).attr("data-code"); // Get the data from the hovered element
    $('.copy .wrapper:visible').fadeOut();
    $('#' + id).stop(true, true).show(); // Toggle the correct div    
    //Close button
    $('.copy .wrapper span').click(function() {
        $('.copy .wrapper').fadeOut();
    });
});

Thats it get rid of mouseleave listener

locrizak
  • 12,192
  • 12
  • 60
  • 80
  • locrizak, thanks. However, although the visible DIV hides on mouseleave, the 'close' button doesn't work. ie: http://jsfiddle.net/rzea/8gWJM/3/. I did check jQuery's .delay() documentation, but I'm not THAT proficient with JS. – Ricardo Zea Jun 06 '11 at 17:53
3

Use setTimeout instead of delay.

Working demo: http://jsfiddle.net/J7qTy/

From jQuery delay documentation:

The .delay() method is best for delaying between queued jQuery effects. Because it is limited—it doesn't, for example, offer a way to cancel the delay—.delay() is not a replacement for JavaScript's native setTimeout function, which may be more appropriate for certain use cases.

marcosfromero
  • 2,853
  • 17
  • 17