Check Ctrl / Shift / Alt keys on 'click' event
Asked Answered
I

10

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"); }
});
Inconvincible answered 17/5, 2010 at 6:52 Comment(1)
@JeremyBanks You are looking for KeyboardEvent Location (see table support). 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...Manatee
N
85

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');
      }
    }
  }); 
Nonillion answered 20/5, 2010 at 21:30 Comment(6)
Sorry, I didn't mention that I'm interested in Firefox 3.6.3. I updated the question accordingly.Inconvincible
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 appletNonillion
Yeah i figured you wouldnt. But right now its just not possible to do uisng JQuery/HTML DOM and Firefox 3.6.3Nonillion
Likewise, you could do it with some Flash Actionscript3 as well, but I'm guessing you don't want to go there either.Dragelin
The quirksmode link in one of the other comments suggests that it's IE6+ rather than just IE8...Viniferous
good pont stobor but since he is looking for a solution in Firefox 3.6.3. That is a bit irreleventNonillion
E
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.

Entellus answered 17/5, 2010 at 7:2 Comment(4)
Shift left and right both have a key code of 16. Same with Ctrl (17) and alt (18)Transduction
I think you'll have to wait for DOM3 support to be able to tell left from right. DOM 3 introduces event.keyLocation (w3.org/TR/DOM-Level-3-Events/…).Chateau
Is that possible that Firefox 3.6.3 has some implementation of this ?Inconvincible
It seems those left/right features aren't yet implemented in Firefox. For shift there'sa feature request you could star: 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): quirksmode.org/dom/w3c_events.html#keypropsFelicity
C
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>
Cilo answered 8/12, 2015 at 12:51 Comment(5)
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.Velour
Using event.location is the only thing that worked for me in Chrome, to distinguish left-side keys from right-side keys.Errecart
e.originalEvent.location working for me in Chrome as well as Firefox. @ErrecartCilo
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.Kweiyang
e.originalEvent is the property that also has shiftKey and other related properties so use that if the specific SHIFT key pressed doesn't matter to you (left or right)Perretta
D
9

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.
Danieldaniela answered 27/5, 2020 at 3:2 Comment(0)
T
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.

Theism answered 10/12, 2015 at 15:0 Comment(2)
This is probably the best answer here. Interestingly it does not have upvotes.Deuterium
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.Twentyfour
M
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!)
Manatee answered 6/12, 2015 at 13:46 Comment(0)
L
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

Lemus answered 26/5, 2010 at 18:23 Comment(0)
D
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

Disorganize answered 11/9, 2014 at 7:1 Comment(0)
B
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?

Beaux answered 7/12, 2015 at 16:45 Comment(0)
C
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=[];   
});
Centistere answered 11/12, 2015 at 22:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.