Leon van der Veen
Leon van der Veen

Reputation: 1672

delay before function and cancel function on hover out

I'm trying to reach the following. I want to collapse my menu after I hovered over the menu for more then 3 seconds. But when I hover out of the menu before the 3 seconds it must not collapse.

$("#sidebar").hover(function() {
    if($(this).hasClass("collapsed-by-user")) {
        setTimeout(sidebarCollapse, 3000);
    }
}, function() {
    if($(this).hasClass("collapsed-by-user")) {
        sidebarNotCollapse();
        preventDefault();
    }
});

This is what I got so far. Collapse after 3 seconds is working but if I hover out before 3 seconds it still collapsing.

Any idea how to do this?

Upvotes: 1

Views: 58

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074989

You need to remember the timer handle and use it with clearTimeout if the hover ends, if it's within 3 seconds:

var handle = 0;
var when = 0;
$("#sidebar").hover(function() {
    // Start the timer if we don't have it running already and we have the class
    if(!handle && $(this).hasClass("collapsed-by-user")) {
        handle = setTimeout(function() {
            handle = 0;
            sidebarCollapse();
        }, 3000);
        when = Date.now(); // Remember when it started
    }
}, function() {
    // If we have a handle and it's been less than three seconds,
    // stop the timeout from running by clearing it
    if (handle && Date.now() - when < 3000) {
        clearTimeout(handle);
    }

    // Reset our handle var regardless (for next time)
    handle = 0;
});

Note that we're clearing the handle when the timer fires before callilng sidebarCollapse.

(I'm not sure why you're doing that class check, so I left it in.)

Or updated per Jamiec's comment below; he's right, we don't really need to do that when check:

var handle = 0;
$("#sidebar").hover(function() {
    // Start the timer if we don't have it running already and we have the class
    if(!handle && $(this).hasClass("collapsed-by-user")) {
        handle = setTimeout(function() {
            handle = 0;
            sidebarCollapse();
        }, 3000);
    }
}, function() {
    // clearTimeout is a no-op if the timer's already fired
    clearTimeout(handle);
    handle = 0;
});

Upvotes: 3

Related Questions