5

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!

PaulAdamDavis
  • 1,574
  • 3
  • 16
  • 19

7 Answers7

14

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
  • 109,619
  • 77
  • 317
  • 330
1

.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
  • 49,587
  • 11
  • 107
  • 104
1

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
  • 10,139
  • 5
  • 38
  • 50
1

Sounds like you could use the hoverIntent plugin.

nickf
  • 537,072
  • 198
  • 649
  • 721
  • That was my first response, then I read that he didn't want to use a plugin. – mVChr May 23 '10 at 15:43
  • @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 May 23 '10 at 23:00
0

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

Community
  • 1
  • 1
Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
0

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!

Community
  • 1
  • 1
TheVillageIdiot
  • 40,053
  • 20
  • 133
  • 188
0

If you need to optimize a bit you can use something like that. This code is adapted for google maps pins but you get the idea

google.maps.event.addListener(marker, 'mouseover', function(){
  this.timeout = setTimeout(markerClick.bind(this, false), 500)
  google.maps.event.addListener(this, 'mouseout', function(){
    if(this.timeout){
      clearTimeout(this.timeout)
      delete this.timeout
    }
    google.maps.event.clearListeners(this, 'mouseout');
  }.bind(this))
}.bind(marker))
Rivenfall
  • 1,189
  • 10
  • 15