how to avoid mouse event conflict with timer

77 views Asked by At

My goal is to hover an element on a webpage, in this case an li tag, causing a main image to swap with an alternate one. While the mouse hovers the li tag, the alternate image is to be visible. The alternate image is to remain visible for n seconds after the mouse has left the li tag. The initial hover action is not to be triggered again until the alternate image has swapped back to the main image after the n seconds.

My search so far has lead me to: Detect IF hovering over element with jQuery. I forked the jsfiddle from Meligy and came up with this:

var $sample = $("#sample");
var $main = $("#main");
var $alt = $("#alt");

$alt.hide();

setInterval(function () {
    if ($sample.is(":hover")) {
        $main.hide();
        $alt.show();
    } else {
        setInterval(function(){
            $alt.hide();
            $main.show();
        },3000);
    }
}, 200);

Also, jQuery on hover animation fires multiple times and using FC's jsfiddle came up with which happens to be surprisingly close.

var $hover = $("#hover");
var $main = $("#main");
var $alt = $("#alt");

$alt.hide();

$hover.hover(

function () {
    $alt.stop(true, true).show();
    $main.stop(true, true).hide();
},

function () {
    $main.stop(true, true).show(2000);
    $alt.stop(true, true).hide(2000);
});

so far the nearest thing I have is below but after a few hovers the images flutter back and forth uncontrollably.

var $hover = $("#hover");
var $main = $("#main");
var $alt = $("#alt");

$alt.hide();


$hover.hover(function () {
    if ($main.is(":visible")) {
        $main.hide();
        $alt.show();
    }
}, function () {
    setInterval(function () {

        // Also attempted $main.is(":hidden")

        if ($main.not(":visible")){
            $alt.hide();
            $main.show();
        }
    }, 3000);
});

Thanks everyone.

1

There are 1 answers

1
Tyr On BEST ANSWER

Use a timeout to avoid this behavior. The cause is, that an interval (timeout too) will fire, regardless of the hover. You have to cancel the running timeout/interval if you leave/reenter the element. I made some edits on your code for testing purposes:

var timer = null;

$hover.on('mouseenter', function () {
    if (window.timer != null)
        clearTimeout(window.timer);

        $main.hide();
        $alt.show();
});

$hover.on('mouseout', function () {
    window.timer = setTimeout(function () {
        // Also attempted $main.is(":hidden")
        $alt.hide();
        $main.show();
    }, 3000);
});

The updated fiddle: https://jsfiddle.net/m18voLeL/5/