JavaScript: Check if mouse button down?

Viewed 216222

Is there a way to detect if a mouse button is currently down in JavaScript?

I know about the "mousedown" event, but that's not what I need. Some time AFTER the mouse button is pressed, I want to be able to detect if it is still pressed down.

Is this possible?

17 Answers

Regarding Pax' solution: it doesn't work if user clicks more than one button intentionally or accidentally. Don't ask me how I know :-(.

The correct code should be like that:

var mouseDown = 0;
document.body.onmousedown = function() { 
  ++mouseDown;
}
document.body.onmouseup = function() {
  --mouseDown;
}

With the test like this:

if(mouseDown){
  // crikey! isn't she a beauty?
}

If you want to know what button is pressed, be prepared to make mouseDown an array of counters and count them separately for separate buttons:

// let's pretend that a mouse doesn't have more than 9 buttons
var mouseDown = [0, 0, 0, 0, 0, 0, 0, 0, 0],
    mouseDownCount = 0;
document.body.onmousedown = function(evt) { 
  ++mouseDown[evt.button];
  ++mouseDownCount;
}
document.body.onmouseup = function(evt) {
  --mouseDown[evt.button];
  --mouseDownCount;
}

Now you can check what buttons were pressed exactly:

if(mouseDownCount){
  // alright, let's lift the little bugger up!
  for(var i = 0; i < mouseDown.length; ++i){
    if(mouseDown[i]){
      // we found it right there!
    }
  }
}

Now be warned that the code above would work only for standard-compliant browsers that pass you a button number starting from 0 and up. IE uses a bit mask of currently pressed buttons:

  • 0 for "nothing is pressed"
  • 1 for left
  • 2 for right
  • 4 for middle
  • and any combination of above, e.g., 5 for left + middle

So adjust your code accordingly! I leave it as an exercise.

And remember: IE uses a global event object called … "event".

Incidentally IE has a feature useful in your case: when other browsers send "button" only for mouse button events (onclick, onmousedown, and onmouseup), IE sends it with onmousemove too. So you can start listening for onmousemove when you need to know the button state, and check for evt.button as soon as you got it — now you know what mouse buttons were pressed:

// for IE only!
document.body.onmousemove = function(){
  if(event.button){
    // aha! we caught a feisty little sheila!
  }
};

Of course you get nothing if she plays dead and not moving.

Relevant links:

Update #1: I don't know why I carried over the document.body-style of code. It will be better to attach event handlers directly to the document.

I think the best approach to this is to keep your own record of the mouse button state, as follows:

var mouseDown = 0;
document.body.onmousedown = function() { 
    mouseDown = 1;
}
document.body.onmouseup = function() {
    mouseDown = 0;
}

and then, later in your code:

if (mouseDown == 1) {
    // the mouse is down, do what you have to do.
}

the solution isn't good. one could "mousedown" on the document, then "mouseup" outside the browser, and on this case the browser would still be thinking the mouse is down.

the only good solution is using IE.event object.

The following snippet will attempt to execute the "doStuff" function 2 seconds after the mouseDown event occurs in document.body. If the user lifts up the button, the mouseUp event will occur and cancel the delayed execution.

I'd advise using some method for cross-browser event attachment - setting the mousedown and mouseup properties explicitly was done to simplify the example.

function doStuff() {
  // does something when mouse is down in body for longer than 2 seconds
}

var mousedownTimeout;

document.body.onmousedown = function() { 
  mousedownTimeout = window.setTimeout(doStuff, 2000);
}

document.body.onmouseup = function() {
  window.clearTimeout(mousedownTimeout);
}

Using the MouseEvent api, to check the pressed button, if any:

// Mouse buttons
document.addEventListener('mousedown', e => console.log(e.buttons))
// Keyboard keys
document.addEventListener('keydown', e => console.log(e.key))

Return:

A number representing one or more buttons. For more than one button pressed simultaneously, the values are combined (e.g., 3 is primary + secondary).

0 : No button or un-initialized
1 : Primary button (usually the left button)
2 : Secondary button (usually the right button)
4 : Auxilary button (usually the mouse wheel button or middle button)
8 : 4th button (typically the "Browser Back" button)
16 : 5th button (typically the "Browser Forward" button)

In case someone else runs into this, you can use .matches with the :active selector:

function mouseDown() {
    return document.body.matches(":active");
}

You can combine @Pax and my answers to also get the duration that the mouse has been down for:

var mousedownTimeout,
    mousedown = 0;

document.body.onmousedown = function() {
  mousedown = 0; 
  window.clearInterval(mousedownTimeout);
  mousedownTimeout = window.setInterval(function() { mousedown += 200 }, 200);
}

document.body.onmouseup = function() {
  mousedown = 0;
  window.clearInterval(mousedownTimeout);
}

Then later:

if (mousedown >= 2000) {
  // do something if the mousebutton has been down for at least 2 seconds
}

You need to handle the MouseDown and MouseUp and set some flag or something to track it "later down the road"... :(

As said @Jack, when mouseup happens outside of browser window, we are not aware of it...

This code (almost) worked for me:

window.addEventListener('mouseup', mouseUpHandler, false);
window.addEventListener('mousedown', mouseDownHandler, false);

Unfortunately, I won't get the mouseup event in one of those cases:

  • user simultaneously presses a keyboard key and a mouse button, releases mouse button outside of browser window then releases key.
  • user presses two mouse buttons simultaneously, releases one mouse button then the other one, both outside of browser window.

Well, you can't check if it's down after the event, but you can check if it's Up... If it's up.. it means that no longer is down :P lol

So the user presses the button down (onMouseDown event) ... and after that, you check if is up (onMouseUp). While it's not up, you can do what you need.

Related