在“点击”事件中检查Ctrl / Shift / Alt键


78

我怎么能确定哪个 Ctrl/ Shift/Alt下面的代码键被按下?

$("#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"); }
});

@JeremyBanks您正在寻找KeyboardEvent位置 请参阅表支持。在jQuery中,使用jq事件包装器,您需要使用event.originalEvent.location。然后,我想实现单击的逻辑并不难,只需在击键/击键事件中设置一些标志/对象,然后在单击时进行检查即可。问题可能是处理altGr可能产生不一致结果的密钥。如果我有时间,我会在后面回答...
A. Wolff

Answers:


75

好吧,这仅适用于IE 8,因此无法在所有浏览器中使用。Microsoft实现了确定按下哪个(右/左)键的功能。这是链接http://msdn.microsoft.com/zh-cn/library/ms534630(VS.85).aspx

我还发现了这篇关于浏览器中的按键,按键,按键事件的奇妙文章。 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');
      }
    }
  }); 

抱歉,我没有提到我对Firefox 3.6.3感兴趣。我相应地更新了问题。
米沙·莫罗什科

Misha Moroshko。对不起,但是在Firefox中还没有办法做到这一点。也许将来它会实现“ keyLocation”,“ keyIdentifier”或“ shiftLeft”。我确实有一个疯狂的建议,但不确定是否会起作用。我知道JAVA小程序具有检测左右击键的能力。如果您可以捕获小程序中的击键,然后将左右信息传递回网站。我什至无法开始告诉你如何做到这一点。但它是一个主意。Flash可以替代JAVA小程序
John Hartsock 2010年

是的,我想你不会。但是目前无法使用JQuery / HTML DOM和Firefox 3.6.3
John Hartsock 2010年

同样,您也可以使用一些Flash Actionscript3来完成此操作,但是我猜您也不想去那里。
mVChr 2010年

其他评论之一中的quirksmode链接表明它是IE6 +,而不仅仅是IE8 ...
Stobor 2010年

40
$('#someelement').bind('click', function(event){
   if(event.ctrlKey)
      console.log('ctrl');
   if(event.altKey)
      console.log('alt');
   if(event.shiftKey)
      console.log('shift');

});

我不知道是否可以在一次点击事件中检查左/右键,但是我认为这是不可能的。


1
左右移动均具有键代码16。与Ctrl(17)和alt(18)相同

9
我认为您必须等待DOM3支持才能从右向左讲。DOM 3引入了event.keyLocation(w3.org/TR/DOM-Level-3-Events/…)。
DaveS 2010年

Firefox 3.6.3是否可以实现此功能?
Misha Moroshko 2010年

2
似乎这些左/右功能尚未在Firefox中实现。对于转换,您可以加注一个功能请求:bugzilla.mozilla.org/show_bug.cgi? id=458433 ctrlLeft甚至没有错误/功能请求。Quirksmode页面(尽管缺少任何最新浏览器的信息):quirksmode.org/dom/w3c_events.html#keyprops
Simon B. 2010年

7

e.originalEvent.location左键返回1,右键返回2。因此,您可以modifier像下面那样检测按下了哪个键。希望这会帮助你。

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>


我快速浏览了Chrome,并得出了与您相同的结果。对IE OLDTIMER使用event.locationevent.keyLocation可能的备用event.ctrlLeft语法。
Tokimon 2015年

在Chrome中,使用event.location是唯一对我有用的方法,用于区分左侧键和右侧键。
Mac

e.originalEvent.location在Chrome和Firefox中为我工作。@Mac
Ibrahim Khan

使用起来似乎很奇怪keyup……如果您想知道是否Ctrl在期间被按下(按住)click,则需要使用keydown并设置一个标志,然后可以在单击侦听器中签入。重置中的标志keyup
Stijn de Witt

7

在大多数情况下ALTCTRLSHIFT关键布尔将工作,看是否被按这些键。例如:

var altKeyPressed = instanceOfMouseEvent.altKey

调用时,它将返回true或false。有关更多信息,请访问https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/altKey

供将来参考,还有一个称为metaKey(仅适用于NS / firefox),当按下meta键时可以使用。


这可能是最好的答案。有趣的是,它没有投票。
MarkSkayff

值得注意的是,如果用户使用默认设置的Linux Mint 18,则此简单的解决方案可能会失败。如果在“首选项”:“ Windows:行为:用于移动和调整窗口大小的特殊键”中找到的操作系统设置设置为“ Alt”(默认情况下),则按住“ Alt”将click不会触发该事件,因此,引用该altKey属性的函数将永远不会被执行。
Patrick Dark

2

根据我的评论,这是可能的解决方案。

要检查按下了哪个特定的修饰键,可以使用 KeyboardEvent Location请参阅表支持

为了支持IE8,幸运的是您可以使用已经发布的解决方案

现在,解决方法是设置一个具有相关属性的全局对象,该属性涉及哪些修饰键。当然,不使用全局对象的其他方式也是可能的。

在这里,我使用相关的JavaScript侦听器方法捕获事件(jQuery不支持捕获阶段)。我们捕获事件以处理keydown/keyup由于已经在使用的代码而由于某种原因停止事件传播的情况。

/* 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>

作为旁注:

  • ALT GR键是CTRL-RightALT 键的快捷键
  • 同时按住两个相同的修饰键(例如Shift-Left和Shift-Rigth键),将只处理第一个(似乎是默认浏览器行为,所以无论如何似乎都是对的!)

2

只是想我会添加一个适合2020年的答案。


您现在也可以使用MouseEvent.getModifierState()它-撰写本文时,大多数浏览器都支持它。

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});
});

例

注意事项:

  • 值得注意的是,此API不能区分left和right修饰符。如果您在乎这一点,那您一定很不走运。但是我认为这仅对少数用例有意义。
  • 其中的这个API的主要好处是,它支持比其他修饰shiftctrlalt。但是,由于先天平台的差异,不同操作系统之间的特定行为有些不稳定。使用它们之前,请先检查这里

非常感谢。这太干净了!
奥斯丁·伯克


0

比任何事情都简单:使用keydown事件来检查它是Ctrl(17)还是Shift(16),然后使用keyup事件来检查它是Enter(13)和/Ctrl还是Shift在取消Ctrl或按下Shift任何keyup之前击中Enter


0

奇迹般有效!以及在Chrome,Firefox,IE和Edge上也是如此;)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))
});

以下是带有点击事件的版本 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=[];   
});

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.