jQuery: Detecting pressed mouse button during mousemove event

Jquery

Jquery Problem Overview


I tried to detect which mouse button -if any- is the user pressing during a mousemove event under jQuery, but I'm getting ambiguous results:

no button pressed:      e.which = 1   e.button = 0
left button pressed:    e.which = 1   e.button = 0
middle button pressed:  e.which = 2   e.button = 1
right button pressed:   e.which = 3   e.button = 2

Code:

<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
  
<input id="whichkey" value="type something">
<div id="log"></div>
<script>$('#whichkey').bind('mousemove',function(e){ 
  $('#log').html(e.which + ' : ' +  e.button );
});  </script>

</body>
</html>

How can I tell the difference between left mouse button pressed and no button at all?

Jquery Solutions


Solution 1 - Jquery

You can write a bit of code to keep track of the state of the left mouse button, and with a little function you can pre-process the event variable in the mousemove event.

To keep track of the state of the LMB, bind an event to document level for mousedown and mouseup and check for e.which to set or clear the flag.

The pre-processing is done by the tweakMouseMoveEvent() function in my code. To support IE versions < 9, you have to check if mouse buttons were released outside the window and clear the flag if so. Then you can change the passed event variable. If e.which was originally 1 (no button or LMB) and the current state of the left button is not pressed, just set e.which to 0, and use that in the rest of your mousemove event to check for no buttons pressed.

The mousemove handler in my example just calls the tweak function passing the current event variable through, then outputs the value of e.which.

$(function() {
    var leftButtonDown = false;
    $(document).mousedown(function(e){
        // Left mouse button was pressed, set flag
        if(e.which === 1) leftButtonDown = true;
    });
    $(document).mouseup(function(e){
        // Left mouse button was released, clear flag
        if(e.which === 1) leftButtonDown = false;
    });
    
    function tweakMouseMoveEvent(e){
        // Check from jQuery UI for IE versions < 9
        if ($.browser.msie && !e.button && !(document.documentMode >= 9)) {
            leftButtonDown = false;
        }
        
        // If left button is not set, set which to 0
        // This indicates no buttons pressed
        if(e.which === 1 && !leftButtonDown) e.which = 0;
    }

    $(document).mousemove(function(e) {
        // Call the tweak function to check for LMB and set correct e.which
        tweakMouseMoveEvent(e);

        $('body').text('which: ' + e.which);
    });
});

Try a live demo here: http://jsfiddle.net/G5Xr2/

Solution 2 - Jquery

Most browsers (except Safari) *) now support the MouseEvent.buttons property (note: plural "buttons"), which is 1 when the left mouse button is pressed:

$('#whichkey').bind('mousemove', function(e) { 
    $('#log').html('Pressed: ' + e.buttons);
});

https://jsfiddle.net/pdz2nzon/2

*) The world is moving forward:
https://webkit.org/blog/8016/release-notes-for-safari-technology-preview-43/
https://trac.webkit.org/changeset/223264/webkit/
https://bugs.webkit.org/show_bug.cgi?id=178214

Solution 3 - Jquery

jQuery normalizes the which value so it will work across all browsers. I bet if you run your script you will find different e.button values.

Solution 4 - Jquery

For some reason, when binding to mousemove event, the event.which property is set to 1 if left button or none is pressed.

I changed to mousedown event and it worked Ok:

  • left: 1
  • middle: 2
  • right: 3

Here's a working example: http://jsfiddle.net/marcosfromero/RrXbX/

The jQuery code is:

$('p').mousedown(function(event) {
    console.log(event.which);
    $('#button').text(event.which);
});

Solution 5 - Jquery

Those variables are updated when the mousedown event (amongst others) fires; you're seeing the value that remains from that event. Note that they are properties of that event, not of the mouse itself:

> Description: For key or button events, this attribute indicates the specific button or key that was pressed.

There is no value for "no button press", because the mousedown event will never fire to indicate that there's no button being pressed.

You'll have to keep your own global [boolean] variable and toggle it on/off on mousedown/mouseup.

  • This will only work if the browser window had focus when the button was pressed, which means a focus-switch between the user depressing the mouse button and your mousemove event firing will prevent this from working properly. However, there's really not much you can do about that.

Solution 6 - Jquery

As of the date, the following works on Firefox 47, Chrome 54 and Safari 10.

$('#whichkey').bind('mousemove',function(e){
    if (e.buttons & 1 || (e.buttons === undefined && e.which == 1)) {
        $('#log').html('left button pressed');
    } else if (e.buttons & 2 || (e.buttons === undefined && e.which == 3)) {
        $('#log').html('right button pressed');
    } else {
        $('#log').html('no button pressed');
    }
});

Solution 7 - Jquery

For users looking for similar solution but without the use of JQuery, here is a way of how I solved my problem:

    canvas.addEventListener("mousemove", updatePosition_mouseNtouch);

    function updatePosition_mouseNtouch (evt) {
      // IF mouse is down THEN set button press flag
      if(evt.which === 1)
        leftButtonDown = true;
      // If you need to detect other buttons, then make this here
      // ... else if(evt.which === 2) middleButtonDown = true;
      // ... else if(evt.which === 3) rightButtonDown = true;
      // IF no mouse button is pressed THEN reset press flag(s)
      else
        leftButtonDown = false;
    
      if (leftButtonDown) {
        /* do some stuff */
      }
    }

I hope this is usefull to someone seeking an answer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSebasti&#225;n GrignoliView Question on Stackoverflow
Solution 1 - JqueryDarthJDGView Answer on Stackoverflow
Solution 2 - JquerySphinxxxView Answer on Stackoverflow
Solution 3 - JqueryMottieView Answer on Stackoverflow
Solution 4 - JquerymarcosfromeroView Answer on Stackoverflow
Solution 5 - JqueryLightness Races in OrbitView Answer on Stackoverflow
Solution 6 - JqueryGiancarlo SportelliView Answer on Stackoverflow
Solution 7 - JqueryIvan dos Reis AndradeView Answer on Stackoverflow