PaulAdamDavis
PaulAdamDavis

Reputation: 1584

If element has been 'mouseover'ed for 500ms, run function with jQuery

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!

Upvotes: 5

Views: 5366

Answers (7)

Rivenfall
Rivenfall

Reputation: 1263

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))

Upvotes: 0

nickf
nickf

Reputation: 546035

Sounds like you could use the hoverIntent plugin.

Upvotes: 1

mVChr
mVChr

Reputation: 50177

.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.

Upvotes: 1

serg
serg

Reputation: 111265

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");
  });
});
​

Upvotes: 14

patmortech
patmortech

Reputation: 10219

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);
});

Upvotes: 1

TheVillageIdiot
TheVillageIdiot

Reputation: 40497

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!

Upvotes: 0

Ólafur Waage
Ólafur Waage

Reputation: 69991

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

Upvotes: 0

Related Questions