89

How could I identify which Ctrl / Shift / Alt keys are pressed in the following code ?

$("#my_id").click(function() {
    if (<left control key is pressed>) { alert("Left Ctrl"); }
    if (<right shift and left alt keys are pressed>) { alert("Right Shift + Left Alt"); }
});
Be Brave Be Like Ukraine
  • 7,596
  • 3
  • 42
  • 66
Misha Moroshko
  • 166,356
  • 226
  • 505
  • 746
  • @JeremyBanks You are looking for [KeyboardEvent Location](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location) *([see table support](http://caniuse.com/#feat=keyboardevent-location))*. In jQuery, using jq event wrapper, you need to use `event.originalEvent.location`. Then the logic to implement on click isn't that hard i guess, just set some flag/object on keydown/keyup events and check it on click. Issue could be to handle `altGr` key which can give inconsistent result. If i have time, i'll make an answer, later... – A. Wolff Dec 06 '15 at 09:28

10 Answers10

86

Well you this wont work in all browsers just IE 8. Microsoft implemented the ability to determine which (right/left) key was pressed. Here is a link http://msdn.microsoft.com/en-us/library/ms534630(VS.85).aspx

I also found this wonder article about keypress, keyup, keydown event in browsers. http://unixpapa.com/js/key.html

$('#someelement').bind('click', function(event){ 

    if(event.ctrlKey) {
      if (event.ctrlLeft) {
        console.log('ctrl-left'); 
      }
      else {
        console.log('ctrl-right');
      }
    }
    if(event.altKey) {
      if (event.altLeft) {
        console.log('alt-left'); 
      }
      else {
        console.log('alt-right');
      }
    }
    if(event.shiftKey) {
      if (event.shiftLeft) {
        console.log('shift-left'); 
      }
      else
      {
        console.log('shift-right');
      }
    }
  }); 
John Hartsock
  • 85,422
  • 23
  • 131
  • 146
  • Sorry, I didn't mention that I'm interested in Firefox 3.6.3. I updated the question accordingly. – Misha Moroshko May 21 '10 at 01:01
  • Misha Moroshko. Sorry but there is just no way to do this in firefox yet. Perhaps it will implement "keyLocation", "keyIdentifier", or "shiftLeft" in the future....I do have a wild suggestion but not sure if it will work. I know JAVA applets have the ability to detect right and left keystrokes. if you could capture the keystroke in the applet and then pass the right/left information back to the website. I cant even begin to tell you how to do this. but its an idea. Flash may be an alternative to a JAVA applet – John Hartsock May 21 '10 at 13:23
  • Yeah i figured you wouldnt. But right now its just not possible to do uisng JQuery/HTML DOM and Firefox 3.6.3 – John Hartsock May 21 '10 at 14:52
  • Likewise, you could do it with some [Flash Actionscript3 as well](http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/events/KeyboardEvent.html#keyLocation), but I'm guessing you don't want to go there either. – mVChr May 26 '10 at 01:39
  • The quirksmode link in one of the other comments suggests that it's IE6+ rather than just IE8... – Stobor May 27 '10 at 02:50
  • good pont stobor but since he is looking for a solution in Firefox 3.6.3. That is a bit irrelevent – John Hartsock May 27 '10 at 13:19
40
$('#someelement').bind('click', function(event){
   if(event.ctrlKey)
      console.log('ctrl');
   if(event.altKey)
      console.log('alt');
   if(event.shiftKey)
      console.log('shift');

});

I don't know if it's possible to check for left/right keys within a click event, but I don't think it's possible.

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • 1
    Shift left and right both have a key code of 16. Same with Ctrl (17) and alt (18) –  May 20 '10 at 15:30
  • 9
    I think you'll have to wait for DOM3 support to be able to tell left from right. DOM 3 introduces event.keyLocation (http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-KeyboardEvent-keylocation). – DaveS May 20 '10 at 20:02
  • Is that possible that Firefox 3.6.3 has some implementation of this ? – Misha Moroshko May 21 '10 at 01:00
  • 2
    It seems those left/right features aren't yet implemented in Firefox. For shift there'sa feature request you could star: https://bugzilla.mozilla.org/show_bug.cgi?id=458433 ctrlLeft doesn't even have a bug/feature request. Quirksmode page (though lacking info on any recent browsers): http://www.quirksmode.org/dom/w3c_events.html#keyprops – Simon B. May 26 '10 at 11:42
10

e.originalEvent.location returns 1 for left key and 2 for right key. Therefore you can detect which modifier key is pressed like following. Hope this will help you.

var msg = $('#msg');
$(document).keyup(function (e) {
      if (e.keyCode == 16) {
          if (e.originalEvent.location == 1)
              msg.html('Left SHIFT pressed.');
          else
              msg.html('Right SHIFT pressed.');
      } else if (e.keyCode == 17) {
          if (e.originalEvent.location == 1)
              msg.html('Left CTRL pressed.');
          else
              msg.html('Right CTRL pressed.');
      } else if (e.keyCode == 18) {
          if (e.originalEvent.location == 1)
              msg.html('Left ALT pressed.');
          else
              msg.html('Right ALT pressed.');
        
          e.preventDefault(); //because ALT focusout the element
      }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Press modifier key: </label>
<strong id="msg"></strong>
Ibrahim Khan
  • 20,616
  • 7
  • 42
  • 55
  • I did a quick look in Chrome and I came up with the same result as you. Use `event.location` or `event.keyLocation` and possibly a fallback to the `event.ctrlLeft` syntax for IE OLDTIMER. – Tokimon Dec 08 '15 at 17:05
  • Using **event.location** is the only thing that worked for me in Chrome, to distinguish left-side keys from right-side keys. – Mac Oct 13 '16 at 00:27
  • `e.originalEvent.location` working for me in Chrome as well as Firefox. @Mac – Ibrahim Khan Oct 13 '16 at 06:17
  • Seems strange to use `keyup`... If you want to know whether `Ctrl` was pressed (held down) during a `click`, you would want to use `keydown` and set a flag that you can then check in the click listener. Reset the flag in `keyup`. – Stijn de Witt Jan 28 '18 at 13:27
8

In most instances the ALT, CTRL,and SHIFT key booleans will work to see if those keys were pressed. For example:

var altKeyPressed = instanceOfMouseEvent.altKey

When called upon, it will return true or false. For more info, go to https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/altKey

For future reference, there is also one called metaKey (NS/firefox only) which works when the meta key is pressed.

Mwiza
  • 7,780
  • 3
  • 46
  • 42
DJHakim
  • 133
  • 1
  • 11
  • This is probably the best answer here. Interestingly it does not have upvotes. – MarkSkayff Mar 20 '17 at 16:11
  • It's worth noting that this simple solution may fail if the user is using Linux Mint 18 with default settings. If the OS setting found at Preferences: Windows: Behavior: Special Key to move and resize windows is set to Alt (as it is by default), holding Alt will cause the `click` event to not be fired and, therefore, the function referencing the `altKey` property will never be executed. – Patrick Dark Apr 23 '18 at 07:42
7

Just thought I would add an answer appropriate for 2020.


You can now also use MouseEvent.getModifierState() for this - it's supported by most browsers as of time of writing.

document.addEventListener("click", (evn) => {
  const shift = evn.getModifierState("Shift");
  const ctrl = evn.getModifierState("Control");
  const alt = evn.getModifierState("Alt");

  console.log("Mouse pressed! Modifiers:");
  console.table({shift, ctrl, alt});
});

Example

Caveats:

  • Notably, this API does not distinguish between left and right modifiers. If you care about that, you are kind of out of luck. But I imagine this only matters for a small number of use cases.
  • One of the main benefits of this API is that it supports modifiers other than shift, ctrl, and alt. However the specific behaviour is somewhat erratic across different OSes due to innate platform differences. Check here before you use them.
cyqsimon
  • 2,752
  • 2
  • 17
  • 38
2

Following my comment, this is possible solution.

To check which specific modifier key is pressed, you can use KeyboardEvent Location (see table support)

To support IE8, fortunately you could use already posted solution.

Now the workaround is to set a global object with relevant properties regarding which modifier keys are held. Other ways without using global object would be possible of course.

Here, i capture event using relevant javascript listener method (jQuery doesn't support capturing phase). We capture event to handle case where keydown/keyup events propagation would be stopped for some reason by already in-use code.

/* global variable used to check modifier keys held */
/* Note: if e.g control left key and control right key are held simultaneously */
/* only first pressed key is handled (default browser behaviour?)*/
window.modifierKeys = (function() {
  /* to handle modifier keys except AltGr which is key shortcut for controlRight + alt */
  var mKeys = {};
  /* to fire keydown event only once per key held*/
  var lastEvent, heldKeys = {};
  // capture event to avoid any event stopped propagation
  document.addEventListener('keydown', function(e) {
    if (lastEvent && lastEvent.which == e.which) {
      return;
    }
    lastEvent = e;
    heldKeys[e.which] = true;
    setModifierKey(e);
  }, true);
  // capture event to avoid any event stopped propagation
  document.addEventListener('keyup', function(e) {
    lastEvent = null;
    delete heldKeys[e.which];
    setModifierKey(e);
  }, true);

  function setModifierKey(e) {
    mKeys.alt = e.altKey;
    mKeys.ctrlLeft = e.ctrlKey && e.location === 1;
    mKeys.ctrlRight = e.ctrlKey && e.location === 2;
    mKeys.shiftLeft = e.shiftKey && e.location === 1;
    mKeys.shiftRight = e.shiftKey && e.location === 2;
  }
  return mKeys;
})();

/* on div click, check for global object */
$('.modifierKey').on('click', function() {
  console.log(modifierKeys);
  /* for demo purpose */
  $('.info').text(function() {
    var txt = [];
    for (var p in modifierKeys) {
      if (modifierKeys[p]) txt.push(p);
    }
    return txt.toString();
  });
})
/* for demo purpose */

.info:not(:empty) {
  border: 1px solid red;
  padding: .1em .5em;
  font-weight: bold;
}
.info:not(:empty):after {
  content: " held";
  font-weight: normal;
 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="modifierKey" tabindex="-1">
  DIV to catch modifier keys on click
</div>
<br>
<span class="info"></span>

As side notes:

  • ALT GR key is a shortcut key for CTRL-Right & ALT keys
  • holding simultaneously two indentical modifier keys (e.g Shift-Left & Shift-Rigth keys), would result in only first one to be handled (seems like default browser behaviour, so anyway, seems right!)
Mwiza
  • 7,780
  • 3
  • 46
  • 42
A. Wolff
  • 74,033
  • 9
  • 94
  • 155
1

Use js-hotkeys. It is a jQuery plugin.

This is a test to show what you are looking for. It also shows you how to capture left, right, up, down keys standard and those from numeric key pad (the one with numbers 2,4,6,8)! http://afro.systems.googlepages.com/test-static-08.html

user347594
  • 1,256
  • 7
  • 11
0

Easier than anything: you use keydown event to check if it's Ctrl (17) or Shift (16), you then use keyup event to check if it's Enter (13) and Ctrl or Shift hit before (on key down) cancel Ctrl or Shift on any keyup but Enter

Eleanor Zimmermann
  • 414
  • 1
  • 8
  • 26
Otvazhnii
  • 603
  • 5
  • 12
0

There are some reasons that right and left CTRL,SHIFT & ALT keys are not distinguishable because 1. keyCodes are same 2. Many laptop keyboards may not have two control keys Taken a Reference : How can I tell if an event comes from right Ctrl key?

Mwiza
  • 7,780
  • 3
  • 46
  • 42
Parth Patel
  • 774
  • 1
  • 8
  • 15
0

Works like a charm! and on Chrome, Firefox, IE, and Edge too ;) https://jsfiddle.net/55g5utsk/2/

var a=[];
function keyName(p){
    var cases = {16:'Shift',17:'CTRL',18:'Alt'};
    return cases[p] ? cases[p] : 'KeyCode: '+p;
}
function keyPosition(p){
    var cases = {1:'Left',2:'Right'};
    return cases[p] ? cases[p]+' ' : '';
}
$('input').on('keydown',function(e){
    a.push(keyPosition(e.originalEvent.location)+keyName(e.keyCode));
})
$('input').on('keyup',function(){
    var c='';
    var removeDuplicates = [];
    $.each(a, function(i, el){
        if ($.inArray(el, removeDuplicates) === -1) {
           removeDuplicates.push(el);
           c=c+(el)+' + ';
        }
    });
    a=[];
    alert(c.slice(0, -3))
});

Following, a version with the click event http://jsfiddle.net/2pL0tzx9/

var a=[];
function keyName(p){
    var cases = {16:'Shift',17:'CTRL',18:'Alt'};
    return cases[p] ? cases[p] : '';
}
function keyPosition(p){
    var cases = {1:'Left',2:'Right'};
    return cases[p] ? cases[p]+' ' : '';
}
$(document).on('keydown',function(e){
    a.push(keyPosition(e.originalEvent.location)+keyName(e.keyCode));
})
$('#my_id').on('click',function(){
    var c='';
    var removeDuplicates = [];
    a =a.filter(function(v){return v!==''});
    $.each(a, function(i, el){
      if ($.inArray(el, removeDuplicates) === -1){
          removeDuplicates.push(el);
          c=c+(el)+' + ';
      }
    });
    if (c) alert(c.slice(0, -3));
    a=[];   
});
Vixed
  • 3,429
  • 5
  • 37
  • 68