【问题标题】:Detect multiple keys on single keypress event in jQuery在jQuery中检测单个按键事件上的多个键
【发布时间】:2012-05-26 04:18:58
【问题描述】:

是否有可能将 keypress 的混合组合来触发单个事件?

$(document).keyup(function(e){
    if (e.keyCode == 68 && e.keyCode == 69 && e.keyCode == 86) {
        alert('oh hai');
    }
});

我已经在 Chrome 中尝试过,但事件没有触发。

说我疯了,但我正在编写一个 Chrome 扩展程序,并想将 D+E+V 键一起推以强制它进入隐藏的开发者模式。

【问题讨论】:

标签: javascript jquery keypress jquery-events


【解决方案1】:

如果你想检测 dev 键都同时按下,你必须注意keydownkeyup 并保留已关闭的地图。当他们都失败时,触发你的事件。

例如:Live copy | source

var map = {68: false, 69: false, 86: false};
$(document).keydown(function(e) {
    if (e.keyCode in map) {
        map[e.keyCode] = true;
        if (map[68] && map[69] && map[86]) {
            // FIRE EVENT
        }
    }
}).keyup(function(e) {
    if (e.keyCode in map) {
        map[e.keyCode] = false;
    }
});

我假设您不在乎它们按什么顺序按下(因为可靠地按下会很痛苦),只要它们在某个时间点同时全部按下。

【讨论】:

  • mm 正如你所提到的,我认为顺序对于键盘快捷键很重要.. ctrl+vv+ctrl 不同
  • @Vega:修饰键是一锅鱼。
  • @DreamWave:不,keyup 处理程序会清除标志。
【解决方案2】:

类似于 Vega 的...但更简单

var down = {};
$(document).keydown(function(e) {
    down[e.keyCode] = true;
}).keyup(function(e) {
    if (down[68] && down[69] && down[86]) {
        alert('oh hai');
    }
    down[e.keyCode] = false;
});​

【讨论】:

  • 这真的很好,而且效果很好。如果您需要匹配一系列键,那么您可以通过推送到数组来检查顺序:而不是down[e.keyCode]=true,比如down.push(e.keyCode),并验证而不是这个:if(down[68]&&down[69]&&down[86]),就像这样:if(down[0]===68&&down[1]===69&&down[2]===86)
  • 我创建了一个fiddle 来补充 lu1s 的评论。
  • 像魅力一样工作,也感谢@lu1s 订购钥匙! :)
【解决方案3】:

也许更简单的组合键会更容易?

像 Shift + Alt + D 这样的东西怎么样? (您可能不应该使用 Control 键,因为大多数浏览器已经以一种或另一种方式解释 Ctrl+D)

这个代码是这样的:

if(e.shiftKey && e.altKey && e.keyCode == 68)
{
  alert('l33t!');
}

【讨论】:

  • 这不是问题的答案,是吗?
  • @ParthThakkar - 从问题中,您可以得出要求:“强制其进入隐藏的开发人员模式”。由于务实,我提出了一个简单的替代方案来实现相同的最终结果
  • 好吧......这可能是要走的路......我只是认为这不是所需问题的答案,所以我只是问......没有冒犯!)
  • 基于 Comments @GPlumb 中的讨论,您最好包含关于这是所考虑方法的替代方法的评论以及为什么...
【解决方案4】:

我得到了T.J.的回答。为想要避免使用 Jquery 的人使用纯 javascript 中的 Crowder

//A W S D simultaneously
var map = {65: false, 87: false, 83: false, 68: false};
document.body.addEventListener('keydown', function (e) {
    var e = e || event; //to deal with old IE
    if (e.keyCode in map) {
        map[e.keyCode] = true;
        if (map[65] && map[87]) {
            console.log('up left');
        }else if (map[83] && map[68]) {
            console.log('down right');
        }else if (map[87] && map[68]) {
            console.log('up right');
        }else if (map[83] && map[65]) {
            console.log('down left');
        }
    }
});
document.body.addEventListener('keyup', function (e) {
    if (e.keyCode in map) {
        map[e.keyCode] = false;
    }
});

【讨论】:

    【解决方案5】:

    您需要分别捕获三个关键事件,并仅在第三个事件之后触发您的操作。

    var keys = {
            d: { code: 100, pressed: false, next: 'e' },
            e: { code: 101, pressed: false, next: 'v' },
            v: { code: 118, pressed: false, next: 'd' }
        },
        nextKey = 'd';
    
    $(document).keypress(function(e) {
        if (e.keyCode === keys[nextKey].code) {
            keys[nextKey].pressed = true;
            nextKey = keys[nextKey].next;
        } else {
            keys.d.pressed = false;
            keys.e.pressed = false;
            keys.v.pressed = false;
            nextKey = 'd';
        }
    
        if (keys.d.pressed && keys.e.pressed && keys.v.pressed) {
            alert('Entering dev mode...');
        }
    });​
    

    当然有很多方法可以做到这一点。此示例不需要您同时按住按键,只需按顺序键入它们:d e v

    如果您使用了它,您可能希望在一段时间后对其进行扩充以清除 pressed 标志。

    这是working example


    免责声明:我意识到最初的问题是按键应该“一起按下”。这只是一个替代方案,因为其他回答者已经为一起按下的键提供了足够的解决方案。

    【讨论】:

    • 我在 Chrome 中对此进行了测试,但无法使用原始密钥代码。我以前遇到过这种情况,但我忘记了它们为什么不同。
    【解决方案6】:

    我尝试了三个最佳答案(截至本文为止),但没有一个对我有用。 他们没有重置密钥

    如果需要 3 个键来触发脚本,则在触发一次后 - 按 3 个键中的任何一个都会再次触发它。

    我刚刚编写了这个脚本,它运行良好。它使用 Shift+S 触发,但您可以轻松更改它。按下组合后会重置。

    var saveArray = new Array();
    saveArray[0] = false;
    saveArray[1] = false;
    
    $(document).ready(function(){
    
        $(document).keydown(function (f){
            if (f.keyCode == 16) {
                saveArray[0] = true;
            }
        });
    
        $(document).keyup(function (g){
            if(g.which == 16){
                saveArray[0] = false;
            }
        });
    
        $(document).keydown(function (h){
            if (h.keyCode == 83) {
                saveArray[1] = true;
                if(saveArray[0] == true && saveArray[1] == true){
                    saveArray[0] = false;
                    saveArray[1] = false;
                    keypressSaveFunction();
                }
            }
        });
    
        $(document).keyup(function (i){
            if (i.which == 83) {
                saveArray[1] = false;
            }
        });
    });
    
        function keypressSaveFunction(){
            alert("You pressed Shift+S");
        }
    

    小提琴:http://jsfiddle.net/9m8yswwo/13/

    【讨论】:

    • 如果用户继续按住 Shift 键并再次按下 S,这将不起作用。在 S 的 keydown 事件中强制 saveArray[0] = false (假设 Shift 键已释放)是一个非常可怕的 hack。另一方面,这可能就是这对你有用的原因。
    • 不要使用new Array()
    【解决方案7】:

    更现代的解决方案,利用arrow functionsrest parameters

    const multipleKeypress = (function($document) {
      // Map of keys which are currently down.
      const keymap = {}
      // Update keymap on keydown and keyup events.
      $document.on(
        "keydown keyup"
        // If the key is down, assign true to the corresponding
        // propery of keymap, otherwise assign false.
       ,event => keymap[event.keyCode] = event.type === "keydown"
      )
      // The actual function.
      // Takes listener as the first argument,
      // rest of the arguments are key codes.
      return (listener, ...keys) =>
        $document.keydown(() => {
          // Check if every of the specified keys is down.
          if (keys.every(key => keymap[key]))
            listener(event)
        })
    // Pass a jQuery document object to cache it.
    }($(document)))
    
    // Example usage:
    multipleKeypress(() => console.log("pressed"), 68, 69, 86)
    
    // Automatically focus the snippet result
    window.focus()
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <p>Try pressing <kbd>d</kbd>, <kbd>e</kbd> and <kbd>v</kbd> at once.</p>

    【讨论】:

      【解决方案8】:

      您应该使用 keydown 和 keyup 事件来“同时”处理多个键。

      input.on("keydown", function (e) {
                              if (e.which == 17) {
                                  isCtrl = true; // Ctrl
                                  return;
                              }
      
                              /* Ctrl and "c" */
                              if (isCtrl && e.which == 67) {
                                  //some code 
                              }
                          }).keyup(function (e) {
                              if (e.which == 17) {
                                  isCtrl = false; // no Ctrl
                              }
                          });
      

      【讨论】:

      • 不能为尚未定义的变量赋值。
      • 一开始没有定义的变量将是全局堆栈上的一个新变量。这应该只是一个例子,这将如何成为可能。如果你愿意,我可以提供一个 JSFiddle,但问题已经被标记为已解决...
      • 这是一个错误,不是一个特性,而且全局变量也不好。
      • 我知道 - 它应该只是对事件的演示,而不是 js 本身 ;)
      • 这仍然不能成为您使用不良编码实践的借口。
      【解决方案9】:

      如果我很好理解:例如小提琴,http://jsfiddle.net/gAtTk/(看看你的 js 控制台)

      此代码将允许您输入单词“dev”(在此示例中,最后将删除事件 keyup

      (function(seq) {
          var tmp = seq.slice();
          $(document).on("keyup.entersequence", function(e){
              if (!(e.keyCode === tmp.pop())) {
                 tmp = seq.slice();
              }
              else {
                 console.log(e.keyCode);  
                  if (!tmp.length) {
                     console.log('end');
                     $(document).off("keyup.entersequence");
                  }
              }
          });
      }([68,69,86].reverse()));
      

      【讨论】:

        【解决方案10】:

        使用此代码可让多个按键触发事件 + 100 毫秒后超时,以防止输入错误。 在这个例子中:如果在 100ms 的时间内按下 A,Z,E,就会触发该事件。

        var map = {65:false,90:false,69:false}; //Modify keyCodes here
        $(document).keydown(function(e){
            console.log(e.keyCode);
            map[e.keyCode] = e.keyCode in map ? true : map[e.keyCode] || false;
            var result = Object.keys(map).filter(function(key){
                return map[key];
            }).length === Object.keys(map).length ? true : false;
            if(result){
                //Your event here
                Object.keys(map).forEach(function(key){
                    map[key] = false;
                });
            }
            setTimeout(function(){
                map[e.keyCode] = false;
            },100);
        });
        

        【讨论】:

          【解决方案11】:

          如果您关心订单并且还需要按住一个键并点击另一个键(例如:Shift + DEL、DEL、DEL...),而无需抬起第一个键以再次触发事件...我修改了 @BlakePlumm 的 [fiddle] 评论,扩展了 @lu1s 对 @ParthThakkar 答案的评论。

          此外,使用 jQuery 的 .on() 允许您仅在某些元素上侦听键序列。将“body”更改为“input.selector”或其他任何内容。

          var map = [];
          var down = [];
          $(document).on('keydown','body', function(e) {
              if(!map[e.which]){
                  down.push(e.which);
                  if(down[0] === 68 && down[1] === 69 && down[2] === 86) {
                      console.log('D + E + V');
                  } else if(down[0] === 16 && down[1] === 46) {
                      console.log('SHIFT + DEL');
                  }
                  /* more conditions here */
              }
              map[e.which] = true;
          }).keyup(function(e) {
              map[e.which] = false;
          
              /* important for detecting repeat presses of
                 last key while holding first key(s)
                 (can be shortened. see fiddle) */
              var len = down.length;
              while (len--) {
                  if(down[len] === e.which) down.splice(len,1); //removes only the keyup'd key
              }        
              $('.alert').html('');
          });
          

          其他想法: 如果您只关心顺序 - 也就是说,只需按下第一个键,只要最后按下您的主要事件触发键(诸如 CTRL+SHIFT+TAB、TAB、TAB 之类的东西),添加此条件:

          else if(down.length>2) {
              if($.inArray(68,down)!=-1 && $.inArray(69,down)!=-1 && down[2] === 86) {
                  $('.alert').html('A hacky D+E+V was pressed');
              }
          }
          

          摆弄更多精彩的选项和现场演示:-http://jsfiddle.net/kstarr/4ftL1p3k/

          【讨论】:

            【解决方案12】:

            https://github.com/JesseBuesking/jquery.hotkeys.extended

            看看这个。您可能正在寻找这个。

            我们可以在多次按键时触发一个功能。 例如:p+t+k

             $(document).hotkeys('p', 't', 'k', function (){
                    //show blurbox
                    $('#popup').blurbox({
                        blur: 10, animateBlur: true, bgColor: 'rgba(255,255,0,0.2)'
                    })bb.show();
                });
            

            也许你正在寻找这个。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-11-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-11-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多