SenTisso
SenTisso

Reputation: 641

When mouse stops moving in element in jQuery

What I'm trying to achieve: when my mouse is moving then do this, but when it stops moving for like half a second then do that, but when it starts to move again then do that. This is my temporary jQuery:

$(document).ready(function() {

  $('.test').mouseenter(function(){

    $(this).mousemove(function(){
      $(this).css({
        'background-color' : '#666',
        'cursor' : 'none'
      });
    });
  });

  $('.test').mouseout(function(){
    $(this).css({
      'background-color' : '#777',
      'cursor' : 'default'
    });
  });
});

And I have absolutely no idea how to do that, basically my code does this: when you enter an element with a mouse and your mouse is moving inside that element then apply this CSS and when your mouse leaves the element then apply this CSS, but when mouse is inside that element and it stops moving for some period of time then do this <- I can't figure the last bit out.

Upvotes: 6

Views: 3438

Answers (4)

Different55
Different55

Reputation: 597

Sounds like you're looking for timeouts. In a similar project, I used something like this:

var timer;

function active() {
    // Apply active styles
}

function inactive() {
    // Apply inactive styles
}

$('.test').mousemove(function(){
    active(); // Apply active styles
    clearTimeout(timer); // Reset the timer
    timer = setTimeout(out, 500);
});

Once you move the mouse over the area, that launches a timer that resets every mouse move. If the timer is ever allowed to expire, the user's gone inactive and we run whatever code we like.

Upvotes: 2

Louys Patrice Bessette
Louys Patrice Bessette

Reputation: 33943

I understood that you want to detect the mouse movements over a particular element.

To achieve this, you need to use the mousemove event... There is no mousefroze event, sadly!

So you will use a setTimeout() and will constantly clear its callback while the mouse moves. Since that event fires multiple times on a single slight movement, you can set the delay quite tight. So it should be accurate.

The setTimeout callback will execute only when the mouse will stop moving. And that is the whole "trick".

About delays... I think that 100 ms is the lowest accurate value. Less than that will create flickering on "slow" user moves.

The mouseenter is not really usefull here, because it is overridden by the mousemove event right after (because when the mouse enters... it also moves!). But the mouseleave or mouseout is really usefull to restore the element's original state and clear the timeout too... Because the mouse won't be moving over your element does'nt mean it doesn't move at all. So you have to clear that when leaving.

$(document).ready(function() {

  var test = $('#test');
  var moveTimer;

  test.on("mouseout",function(){
    $(this).css({
      'background-color' : 'white',
    }).text("");
    clearTimeout(moveTimer);
  });

  test.on("mousemove",function(){
    console.log("I'm moving!");

    clearTimeout(moveTimer);
    moveTimer = setTimeout(function(){
      console.log("I stopped moving!");
      test.css({
        'background-color' : 'red',
      }).text("The mouse is not moving.");
    },100)

    $(this).css({
      'background-color' : 'blue',
    }).text("Movement detected...");
  });
});
#test{
  margin:50px;
  border:2px solid black;
  height:200px;
  width:200px;
  cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="test"></div>

CodePen

Upvotes: 5

SenTisso
SenTisso

Reputation: 641

So I was just googling. This is the answer:

  $(document).ready(function() {
    var countdown;
    $('.test').hover(function() {
      setTimeout(function(){
        $('.test').css({
          'background-color' : '#666',
          'cursor' : 'none'
        });
        cursor();
      }, 2000);
    }, function(e){
      $('.test').css({
          'background-color' : '#777',
      'cursor' : 'default'
      });
    });

    $('.test').mousemove(function() {
      $('.test').css({
        'background-color' : '#777',
        'cursor' : 'default'
        });
        cursor();
      });
      function cursor() {
        countdown = setTimeout(function() {
          $('.test').css({
            'background-color' : '#666',
            'cursor' : 'none'
          });
        }, 2000);
      }
    });
  });

Upvotes: 1

Ibu
Ibu

Reputation: 43850

This may deviate from your current code, but I think CSS is more appropriate here than JavaScript.

.test {
    background-color:#666;
}

.test:hover {
    background-color:#777;
    cursor:none;
}

These lines of CSS should perform the exact same thing without the complication. Note that in your example, for every pixel the mouse moves, the css is set once more. And since you are not removing the event handler on mouse out, the event is actually ran multiple times.

Upvotes: 0

Related Questions