597

How do you obtain the clicked mouse button using jQuery?

$('div').bind('click', function(){
    alert('clicked');
});

this is triggered by both right and left click, what is the way of being able to catch right mouse click? I'd be happy if something like below exists:

$('div').bind('rightclick', function(){ 
    alert('right mouse button is pressed');
});
Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
Sinan
  • 10,875
  • 6
  • 34
  • 48

17 Answers17

925

As of jQuery version 1.1.3, event.which normalizes event.keyCode and event.charCode so you don't have to worry about browser compatibility issues. Documentation on event.which

event.which will give 1, 2 or 3 for left, middle and right mouse buttons respectively so:

$('#element').mousedown(function(event) {
    switch (event.which) {
        case 1:
            alert('Left Mouse button pressed.');
            break;
        case 2:
            alert('Middle Mouse button pressed.');
            break;
        case 3:
            alert('Right Mouse button pressed.');
            break;
        default:
            alert('You have a strange Mouse!');
    }
});
Developerium
  • 6,563
  • 4
  • 30
  • 54
Acorn
  • 44,010
  • 23
  • 124
  • 163
  • I have had problems with `event.which` not working correctly in Chrome. – Jeff Hines Jul 28 '11 at 20:32
  • 5
    @Jeff Hines - I was trying to detect a right click in Chrome and the implementation shown here appeared to work fine, but I realized that was only because the alert() prevented the context menu from appearing. :( boo – jinglesthula Nov 28 '11 at 22:47
  • 17
    Keep scrolling down and make sure to read @JeffHines's [answer](http://stackoverflow.com/questions/1206203/how-to-distinguish-between-left-and-right-mouse-click-with-jquery/4963381#4963381). Basically, jQuery has this built-in as the event 'contextmenu'. – jpadvo Dec 17 '11 at 20:30
  • 8
    @jpadvo jQuery did not build it as "contextmenu", `contextmenu` is native of the browser. in native JavaScript you can attach to the `oncontextmenu` event. – Naftali aka Neal Aug 20 '12 at 13:12
  • 1
    How do I detect the 4th mouse button? – Petah Oct 02 '12 at 07:09
  • 6
    ie8: Unable to get value of the property 'which': object is null or undefined – Simon Mar 14 '13 at 16:08
  • 2
    Can I prevent the context menu from coming up after the event is fired? – kmoney12 Apr 06 '13 at 03:07
  • 1
    The answer code does work for IE, it's just that the OP wanted to handle `click`, not `mousedown`, which always returns `0`. – Barney Sep 17 '13 at 10:07
  • I tried adding event.preventDefault() and return false; but the context menu still pops up when I right click using this solution :( – Curtis Jun 02 '14 at 00:29
  • @JeffHines, @Syom, it works for me in Chrome and IE 8. Note, jQuery does normalization on this, so it will not necessarily work correctly if you don't use jQuery. Also, per @Barney, it looks like IE has some limitations re event.which on click, but the answer is for `mousedown`. – Matthew Flaschen Sep 19 '14 at 01:04
  • See test I used, http://jsfiddle.net/mLkcrrc2/ , which also lets you test the behavior on click. – Matthew Flaschen Sep 19 '14 at 01:20
  • Don't forget break; in your case:1, if you do, right click will also execute on case1. Doh! – Andy Aug 20 '17 at 05:07
  • If you want to track multiple buttons being pressed at once, use `event.buttons`. It also handles mouse buttons 4 and 5 (which navigate forward/backward in the browser). See this: https://jsfiddle.net/9hponw1t/1/ – mbomb007 Sep 25 '20 at 19:42
253

Edit: I changed it to work for dynamically added elements using .on() in jQuery 1.7 or above:

$(document).on("contextmenu", ".element", function(e){
   alert('Context Menu event has fired!');
   return false;
});

Demo: jsfiddle.net/Kn9s7/5

[Start of original post] This is what worked for me:

$('.element').bind("contextmenu",function(e){
   alert('Context Menu event has fired!');
   return false;
}); 

In case you are into multiple solutions ^^

Edit: Tim Down brings up a good point that it's not always going to be a right-click that fires the contextmenu event, but also when the context menu key is pressed (which is arguably a replacement for a right-click)

gavit
  • 509
  • 3
  • 6
Jeff Hines
  • 3,401
  • 1
  • 17
  • 20
  • 28
    This should be the accepted answer. This event works in all relevant browsers and triggers on a whole click (mouse down + mouse up in proximity). – Nick Retallack Dec 16 '11 at 18:18
  • 3
    This is the *only* solution that worked for me with regards to capturing the right click on a – tango whiskey double Dec 19 '11 at 05:07
  • 17
    Right-clicking is not the only way to trigger the context menu though. – Tim Down Nov 01 '12 at 14:55
  • @Tim Down, would you like to help me improve my answer for future visitors? – Jeff Hines Nov 01 '12 at 16:44
  • 3
    I think it's the wrong approach because the `contextmenu` event firing does not always imply that the right mouse button was clicked. The correct approach is get button information from a mouse event (`click` in this case). – Tim Down Nov 02 '12 at 16:06
  • 1
    Hey! Thanks, this looks great, but I cant get it to bind to an element like a table row or even the body. it works with $(window). Im using backbone.js to populate a area #main with new content etc. – Harry Jan 15 '13 at 08:30
  • @Harry, try using the `.on()` method instead of `.bind()` because it looks like you are trying to fire a context menu on a dynamically generated element. See http://jsfiddle.net/Kn9s7/5/ – Jeff Hines Jan 15 '13 at 23:20
  • Also if the context menu is already overridden by a custom context menu, then this won't capture a right mouse click event, instead you will have to capture the raw `mousedown` event as mentioned in the accepted answer. – User Aug 30 '18 at 14:52
85

You can easily tell which mouse button was pressed by checking the which property of the event object on mouse events:

/*
  1 = Left   mouse button
  2 = Centre mouse button
  3 = Right  mouse button
*/

$([selector]).mousedown(function(e) {
    if (e.which === 3) {
        /* Right mouse button was clicked! */
    }
});
ErikE
  • 43,574
  • 19
  • 137
  • 181
Russ Cam
  • 117,566
  • 29
  • 193
  • 253
  • 4
    The jQuery plugin linked above is using `e.button==2` instead. – ceejayoz Oct 29 '09 at 22:33
  • 6
    yep. Using `event.button` cross browser is more of a problem than `event.which` as the numbers used for the buttons in `event.button` vary. Take a look at this article from Jan 2009 - http://unixpapa.com/js/mouse.html – Russ Cam Oct 29 '09 at 22:37
  • 1
    Wouldn't this be better to be `mouseup` to verify a person truly clicked the item? There's alot of times if i accidentally click something I'm able to prevent the click by holding in the mouse button and dragging outside the element. – Chris Marisic Dec 03 '14 at 19:50
  • 1
    @ChrisMarisic `mouseup` is probably a better event, this is just an example of the use of `event.which` for mouse button clicks – Russ Cam Dec 03 '14 at 22:06
39

You can also bind to contextmenu and return false:

$('selector').bind('contextmenu', function(e){
    e.preventDefault();
    //code
    return false;
});

Demo: http://jsfiddle.net/maniator/WS9S2/

Or you can make a quick plugin that does the same:

(function( $ ) {
  $.fn.rightClick = function(method) {

    $(this).bind('contextmenu rightclick', function(e){
        e.preventDefault();
        method();
        return false;
    });

  };
})( jQuery );

Demo: http://jsfiddle.net/maniator/WS9S2/2/


Using .on(...) jQuery >= 1.7:

$(document).on("contextmenu", "selector", function(e){
    e.preventDefault();
    //code
    return false;
});  //does not have to use `document`, it could be any container element.

Demo: http://jsfiddle.net/maniator/WS9S2/283/

Naftali aka Neal
  • 138,754
  • 36
  • 231
  • 295
  • 1
    @Raynos yes, but that is the only way to handle a right-click event. if the context menu was still there then you could not do anything on a right click. – Naftali aka Neal Dec 13 '11 at 15:53
  • 1
    @Raynos - there are many cases where your point is not valid, such as building an internal tool, or coding something for your own personal use..I'm sure there are more – vsync Feb 15 '12 at 14:18
  • 1
    If you actually wanted it to act like one of the jQuery event handlers (like click, for example), that should be `method.call(this, e);` instead of `method();` That way, `method` gets the correct value for `this` and also has the event object passed to it correctly. – Jeremy T Apr 27 '12 at 18:44
  • @JeremyT that is true... you could handle the callback in any way you want ^_^ – Naftali aka Neal Aug 20 '12 at 13:14
30

$("#element").live('click', function(e) {
  if( (!$.browser.msie && e.button == 0) || ($.browser.msie && e.button == 1) ) {
       alert("Left Button");
    }
    else if(e.button == 2){
       alert("Right Button");
    }
});

Update for the current state of the things:

var $log = $("div.log");
$("div.target").on("mousedown", function() {
  $log.text("Which: " + event.which);
  if (event.which === 1) {
    $(this).removeClass("right middle").addClass("left");
  } else if (event.which === 2) {
    $(this).removeClass("left right").addClass("middle");
  } else if (event.which === 3) {
    $(this).removeClass("left middle").addClass("right");
  }
});
div.target {
  border: 1px solid blue;
  height: 100px;
  width: 100px;
}

div.target.left {
  background-color: #0faf3d;
}

div.target.right {
  background-color: #f093df;
}

div.target.middle {
  background-color: #00afd3;
}

div.log {
  text-align: left;
  color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="target"></div>
<div class="log"></div>
TheVillageIdiot
  • 38,082
  • 20
  • 126
  • 184
  • 1
    is this msie-specific? ie is it portable across other browsers? – Taryn East Mar 04 '10 at 11:34
  • 13
    This method is now unnecessary as `event.which` has been introduced which eliminates cross browser compatibility. – Acorn Apr 28 '10 at 00:13
  • 8
    I suspect event.which actually eliminates cross browser incompatibility, but that's just me. – DwB Jan 27 '11 at 17:06
18
$.event.special.rightclick = {
    bindType: "contextmenu",
    delegateType: "contextmenu"
};

$(document).on("rightclick", "div", function() {
    console.log("hello");
    return false;
});

http://jsfiddle.net/SRX3y/8/

Esailija
  • 130,716
  • 22
  • 250
  • 308
16

There are a lot of very good answers, but I just want to touch on one major difference between IE9 and IE < 9 when using event.button.

According to the old Microsoft specification for event.button the codes differ from the ones used by W3C. W3C considers only 3 cases:

  1. Left mouse button is clicked - event.button === 1
  2. Right mouse button is clicked - event.button === 3
  3. Middle mouse button is clicked - event.button === 2

In older Internet Explorers however Microsoft are flipping a bit for the pressed button and there are 8 cases:

  1. No button is clicked - event.button === 0 or 000
  2. Left button is clicked - event.button === 1 or 001
  3. Right button is clicked - event.button === 2 or 010
  4. Left and right buttons are clicked - event.button === 3 or 011
  5. Middle button is clicked - event.button === 4 or 100
  6. Middle and left buttons are clicked - event.button === 5 or 101
  7. Middle and right buttons are clicked - event.button === 6 or 110
  8. All 3 buttons are clicked - event.button === 7 or 111

Despite the fact that this is theoretically how it should work, no Internet Explorer has ever supported the cases of two or three buttons simultaneously pressed. I am mentioning it because the W3C standard cannot even theoretically support this.

Konstantin Dinev
  • 30,746
  • 13
  • 64
  • 91
  • 6
    so upon pressed button you get `event.button === 0` which is no button clicked, brilliant IE `ಠ_ಠ` – Sinan Dec 17 '12 at 19:14
  • That's in versions of IE lower than 9. – Konstantin Dinev Dec 17 '12 at 19:28
  • If developers collectively stopped choosing to support ie, people would have to switch, and then developers would no longer have to worry about supporting ie. – ahnbizcad Feb 16 '15 at 23:04
  • If you want to track multiple buttons being pressed at once, use `event.buttons`. It also handles mouse buttons 4 and 5 (which navigate forward/backward in the browser). See this: https://jsfiddle.net/9hponw1t/1 – mbomb007 Sep 25 '20 at 19:44
8

It seems to me that a slight adaptation of TheVillageIdiot's answer would be cleaner:

$('#element').bind('click', function(e) {
  if (e.button == 2) {
    alert("Right click");
  }
  else {
    alert("Some other click");
  }
}

EDIT: JQuery provides an e.which attribute, returning 1, 2, 3 for left, middle, and right click respectively. So you could also use if (e.which == 3) { alert("right click"); }

See also: answers to "Triggering onclick event using middle click"

Community
  • 1
  • 1
Dan Burton
  • 51,332
  • 25
  • 109
  • 190
4

event.which === 1 ensures it's a left-click (when using jQuery).

But you should also think about modifier keys: ctrlcmdshiftalt

If you're only interested in catching simple, unmodified left-clicks, you can do something like this:

var isSimpleClick = function (event) {
  return !(
    event.which !== 1 || // not a left click
    event.metaKey ||     // "open link in new tab" (mac)
    event.ctrlKey ||     // "open link in new tab" (windows/linux)
    event.shiftKey ||    // "open link in new window"
    event.altKey         // "save link as"
  );
};

$('a').on('click', function (event) {
  if (isSimpleClick(event)) {
    event.preventDefault();
    // do something...
  }
});
callum
  • 26,180
  • 30
  • 91
  • 142
2

To those who are wondering if they should or not use event.which in vanilla JS or Angular : It's now deprecated so prefer using event.buttons instead.

Note : With this method and (mousedown) event:

  • left click press is associated to 1
  • right click press is associated to 2
  • scroll button press is associated with 4

and (mouseup) event will NOT return the same numbers but 0 instead.

Source : https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons

Valink
  • 51
  • 4
  • It also handles mouse buttons 4 and 5 (which navigate forward/backward in the browser). See this: https://jsfiddle.net/9hponw1t/1 – mbomb007 Sep 25 '20 at 19:45
1

there is also a way, to do it without JQuery!

check out this:

document.addEventListener("mousedown", function(evt) {
    switch(evt.buttons) {
      case 1: // left mouse
      case 2: // right mouse
      case 3: // middle mouse <- I didn't tested that, I just got a touchpad
    }
});
  • Middle mouse seemed 4 on my PC (Ubuntu 14.04 - FireFox). I believe left and right together is 3 and middle is 4.. There has to be a better "cross browser", "cross platform" way... – Paul Jul 10 '16 at 18:43
1

If you are looking for "Better Javascript Mouse Events" which allow for

  • left mousedown
  • middle mousedown
  • right mousedown
  • left mouseup
  • middle mouseup
  • right mouseup
  • left click
  • middle click
  • right click
  • mousewheel up
  • mousewheel down

Have a look at this cross browser normal javascript which triggers the above events, and removes the headache work. Just copy and paste it into the head of your script, or include it in a file in the <head> of your document. Then bind your events, refer to the next code block below which shows a jquery example of capturing the events and firing the functions assigned to them, though this works with normal javascript binding as well.

If your interested in seeing it work, have a look at the jsFiddle: https://jsfiddle.net/BNefn/

/**
   Better Javascript Mouse Events
   Author: Casey Childers
**/
(function(){
    // use addEvent cross-browser shim: https://gist.github.com/dciccale/5394590/
    var addEvent = function(a,b,c){try{a.addEventListener(b,c,!1)}catch(d){a.attachEvent('on'+b,c)}};

    /* This function detects what mouse button was used, left, right, middle, or middle scroll either direction */
    function GetMouseButton(e) {
        e = window.event || e; // Normalize event variable

        var button = '';
        if (e.type == 'mousedown' || e.type == 'click' || e.type == 'contextmenu' || e.type == 'mouseup') {
            if (e.which == null) {
                button = (e.button < 2) ? "left" : ((e.button == 4) ? "middle" : "right");
            } else {
                button = (e.which < 2) ? "left" : ((e.which == 2) ? "middle" : "right");
            }
        } else {
            var direction = e.detail ? e.detail * (-120) : e.wheelDelta;
            switch (direction) {
                case 120:
                case 240:
                case 360:
                    button = "up";
                break;
                case -120:
                case -240:
                case -360:
                    button = "down";
                break;
            }
        }

        var type = e.type
        if(e.type == 'contextmenu') {type = "click";}
        if(e.type == 'DOMMouseScroll') {type = "mousewheel";}

        switch(button) {
            case 'contextmenu':
            case 'left':
            case 'middle':
            case 'up':
            case 'down':
            case 'right':
                if (document.createEvent) {
                  event = new Event(type+':'+button);
                  e.target.dispatchEvent(event);
                } else {
                  event = document.createEventObject();
                  e.target.fireEvent('on'+type+':'+button, event);
                }
            break;
        }
    }

    addEvent(window, 'mousedown', GetMouseButton);
    addEvent(window, 'mouseup', GetMouseButton);
    addEvent(window, 'click', GetMouseButton);
    addEvent(window, 'contextmenu', GetMouseButton);

    /* One of FireFox's browser versions doesn't recognize mousewheel, we account for that in this line */
    var MouseWheelEvent = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
    addEvent(window, MouseWheelEvent, GetMouseButton);
})();

Better Mouse Click Events Example (uses jquery for simplicity, but the above will work cross browser and fire the same event names, IE uses on before the names)

<div id="Test"></div>
<script type="text/javascript">
    $('#Test').on('mouseup',function(e){$(this).append(e.type+'<br />');})
              .on('mouseup:left',function(e){$(this).append(e.type+'<br />');})
              .on('mouseup:middle',function(e){$(this).append(e.type+'<br />');})
              .on('mouseup:right',function(e){$(this).append(e.type+'<br />');})

              .on('click',function(e){$(this).append(e.type+'<br />');})
              .on('click:left',function(e){$(this).append(e.type+'<br />');})
              .on('click:middle',function(e){$(this).append(e.type+'<br />');})
              .on('click:right',function(e){$(this).append(e.type+'<br />');})

              .on('mousedown',function(e){$(this).html('').append(e.type+'<br />');})
              .on('mousedown:left',function(e){$(this).append(e.type+'<br />');})
              .on('mousedown:middle',function(e){$(this).append(e.type+'<br />');})
              .on('mousedown:right',function(e){$(this).append(e.type+'<br />');})

              .on('mousewheel',function(e){$(this).append(e.type+'<br />');})
              .on('mousewheel:up',function(e){$(this).append(e.type+'<br />');})
              .on('mousewheel:down',function(e){$(this).append(e.type+'<br />');})
              ;
</script>

And for those who are in need of the minified version...

!function(){function e(e){e=window.event||e;var t="";if("mousedown"==e.type||"click"==e.type||"contextmenu"==e.type||"mouseup"==e.type)t=null==e.which?e.button<2?"left":4==e.button?"middle":"right":e.which<2?"left":2==e.which?"middle":"right";else{var n=e.detail?-120*e.detail:e.wheelDelta;switch(n){case 120:case 240:case 360:t="up";break;case-120:case-240:case-360:t="down"}}var c=e.type;switch("contextmenu"==e.type&&(c="click"),"DOMMouseScroll"==e.type&&(c="mousewheel"),t){case"contextmenu":case"left":case"middle":case"up":case"down":case"right":document.createEvent?(event=new Event(c+":"+t),e.target.dispatchEvent(event)):(event=document.createEventObject(),e.target.fireEvent("on"+c+":"+t,event))}}var t=function(e,t,n){try{e.addEventListener(t,n,!1)}catch(c){e.attachEvent("on"+t,n)}};t(window,"mousedown",e),t(window,"mouseup",e),t(window,"click",e),t(window,"contextmenu",e);var n=/Firefox/i.test(navigator.userAgent)?"DOMMouseScroll":"mousewheel";t(window,n,e)}();
NinjaKC
  • 761
  • 6
  • 15
1
$("body").on({
    click: function(){alert("left click");},
    contextmenu: function(){alert("right click");}   
});
Paul Roub
  • 35,100
  • 27
  • 72
  • 83
A. K.
  • 42
  • 5
  • You should probably add some details a to why it works. - I agree that it does, but you're not explaining to a n00b why. – Adam Copley Mar 01 '18 at 11:23
0
$(document).ready(function () {
    var resizing = false;
    var frame = $("#frame");
    var origHeightFrame = frame.height();
    var origwidthFrame = frame.width();
    var origPosYGrip = $("#frame-grip").offset().top;
    var origPosXGrip = $("#frame-grip").offset().left;
    var gripHeight = $("#frame-grip").height();
    var gripWidth = $("#frame-grip").width();

    $("#frame-grip").mouseup(function (e) {
        resizing = false;
    });

    $("#frame-grip").mousedown(function (e) {
        resizing = true;
    });
    document.onmousemove = getMousepoints;
    var mousex = 0, mousey = 0, scrollTop = 0, scrollLeft = 0;
    function getMousepoints() {
        if (resizing) {
            var MouseBtnClick = event.which;
            if (MouseBtnClick == 1) {
                scrollTop = document.documentElement ? document.documentElement.scrollTop : document.body.scrollTop;
                scrollLeft = document.documentElement ? document.documentElement.scrollLeft : document.body.scrollLeft;
                mousex = event.clientX + scrollLeft;
                mousey = event.clientY + scrollTop;

                frame.height(mousey);
                frame.width(mousex);
            }
            else {
                resizing = false;
            }
        }
        return true;

    }


});
nhahtdh
  • 52,949
  • 15
  • 113
  • 149
  • @Nitin.Katti :- This is work up on mouse point and left button click if freeze the left button of mouse then it stop the re sizing. – user2335866 Apr 30 '13 at 12:46
0

With jquery you can use event object type

jQuery(".element").on("click contextmenu", function(e){
   if(e.type == "contextmenu") {
       alert("Right click");
   }
});
Ari
  • 3,637
  • 3
  • 29
  • 42
0
$.fn.rightclick = function(func){
    $(this).mousedown(function(event){
        if(event.button == 2) {
            var oncontextmenu = document.oncontextmenu;
            document.oncontextmenu = function(){return false;};
            setTimeout(function(){document.oncontextmenu = oncontextmenu;},300);
            func(event);
            return false;
        }
    });
};

$('.item').rightclick(function(e){ 
    alert("item");
}); 
-1
    $.event.special.rightclick = {
     bindType: "contextmenu",
        delegateType: "contextmenu"
      };

   $(document).on("rightclick", "div", function() {
   console.log("hello");
    return false;
    });
  • 1
    Hi. This answer is being flagged as low quality for deletion. It seems you've added an answer to a question that was answered some time ago. Unless there is an explanation in the answer that explains how this contribution improves the accepted answer, I am inclined to vote to delete too. – Popnoodles Jun 24 '14 at 11:42
  • 1
    @popnoodles, its okay but never repeat it. – Yip Man WingChun Jun 24 '14 at 12:06