views:

123

answers:

6

For the sanity of my users, I want a 'mouseover' event to run after the selector has been hovered for half a second rather than as soon as they hover it.

I first tried a setTimeout function but that runs however long the element has been hovered, I didn't think it through too much I guess. I've also spent a day (on and off) searching (and playing Pacman) ti no result, unless I'm searching for the wrong things.

I would like to keep this plugin-less if we can, purely for run speed & maintainability.

$("#mySelector").mouseover(function(){
    // Run after 500ms
    $(this).addClass("hasBeen500ms");
});

Let's see if we can crack this, I know it will have so many applications!

A: 

Check out this SO question about setting a callback to the setTimeout function.

Ólafur Waage
A: 

I'm trying to build upon Web Logic's answer

create a variable to track if mouse is still over said element:

var isMouseOver=false;

$("#mySelector").mouseover(function(){
   isMouseOver=true;//set variable to gtrue
   setTimeout(function() {
                 if(isMouseOver){
                      $(this).addClass("hasBeen500ms");
                 }
              }, 500);
});

also set mouseout callback, so we can track if mouse is still there after 500 ms.

$("#mySelector").mouseout(function(){
   isMouseOver=false;//set variable to false
});

hope this works!

TheVillageIdiot
A: 

.delay() wasn't working since .addClass() isn't part of the animation queue, so instead I decided to animate something null (decided on visibility:visible since you wouldn't be hovering over an invisible element) and then run the add the hover class in the callback function:

$('#mySelector').mouseenter(function(){
    $(this).animate({'visibility':'visible'},500,'swing',function(){
        $(this).addClass('hoverIntent');
    })
});

$('#mySelector').mouseleave(function(){
    $(this).removeClass('hoverIntent').stop().clearQueue();
});

On mouseleave class is removed, and the animation queue is stopped and cleared in case it's prior to 500ms. You could add the same functionality in the mouseleave if you wanted a delay before unhover.

mVChr
+1  A: 

Another option is to cancel the timeout if a person moves the mouse out before the 500 ms has passed:

var timer;

$('#mySelector').mouseover(function() {
    timer = setTimeout( function() {$(this).addClass('hasBeen500ms');}, 500);
});

$('#mySelector').mouseout(function() {
    clearTimeout(timer);
});
patmortech
+4  A: 

Prevent from showing up if mouse is already out by the time the delay is expired, plus remove class on mouse out:

$("#mySelector").mouseenter(function() {
  var el = $(this);
  var timeoutId = setTimeout(function() {
    el.addClass("hasBeen500ms");
  }, 500);
  el.mouseleave(function() {
    clearTimeout(timeoutId);
    el.removeClass("hasBeen500ms");
  });
});
​
serg
Works perfectly! Thank you. :)
PaulAdamDavis
+1  A: 

Sounds like you could use the hoverIntent plugin.

nickf
That was my first response, then I read that he didn't want to use a plugin.
mVChr
@mhr - ah... I obviously skipped over that part. In any case, I still recommend it. It's a known, documented and tested piece of code. It only adds one function to the jQuery object, and it is only 1.2kb minified.
nickf
+1 to that, but I guess he wants to learn to fish.
mVChr