在jQuery中检测单个按键事件上的多个键

时间:2022-01-27 00:11:03

Is it at all possible to combine a mixture of keypress' to fire a single event?

是否有可能结合使用混合按键来触发一个事件?

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

I've tried it in Chrome but the event doesn't fire.

我已经在Chrome上试过了,但是这个事件没有发生。

Call me crazy but I am writing a Chrome extension and want to push D+E+V keys together to force it into a hidden developer mode.

你可以说我疯了,但我正在写一个Chrome扩展,我想把D+E+V键推到一起,迫使它进入隐藏的开发模式。

12 个解决方案

#1


65  

If you want to detect that the d, e, and v keys were all down at the same time, you have to watch both keydown and keyup and keep a map of the ones that are down. When they're all down, fire your event.

如果你想要检测出d, e,和v的键都在同时下降,你必须同时观察按键和按键,并保存一个按键的地图。当他们都倒下的时候,启动你的事件。

For example: Live copy | source

例如:Live copy |源代码。

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

I assume you don't care what order they're pressed down in (as that would be a pain to reliably press) as long as they're all down at the same time at some point.

我猜你不会在意它们被按下的顺序(因为要想可靠地按下会很痛苦),只要它们在同一时刻都被按下。

#2


18  

Similar to Vega's...but simpler

类似于维加的…但更简单

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

#3


8  

Perhaps a simpler key combination would be easier?

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

How about something like Shift + Alt + D? (You probably shouldn't use the Control key because most browsers already interpret Ctrl+D in one way or another)

比如平移+ Alt + D?(您可能不应该使用控制键,因为大多数浏览器已经以这样或那样的方式解释了Ctrl+D)

The code for this would be something like this:

它的代码是这样的:

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

#4


1  

You would need to capture the three key events separately and fire your action only after the third one.

您需要分别捕获这三个关键事件,并只在第三个事件之后才启动操作。

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...');
    }
});​

There's a number of ways to do this of course. This example doesn't require you to hold the keys down simultaneously, just that you type them in order: d e v.

当然有很多方法可以做到这一点。本例不要求您同时按住键,只需按d ev的顺序输入它们。

If you used this, you might want to augment it to clear the pressed flags after some time interval.

如果您使用了这个,您可能希望在一些时间间隔之后增加它来清除被压的标记。

Here's a working example.

这是一个工作示例。


Disclaimer: I realize the original question said that the keys should be "pressed together". This is just an alternative as other answerers have already provided sufficient solutions for the keys being pressed together.

免责声明:我知道原来的问题说钥匙应该“按在一起”。这只是另一种选择,因为其他应答者已经为键被压在一起提供了足够的解决方案。

#5


1  

I tried the three top answers (as of this post), and none of them worked for me. They didn't reset the keys.

我尝试了三个最常见的答案(在这篇文章中),但没有一个对我有效。他们没有重置钥匙。

If it took 3 keys fire the script, after firing it once - pressing any one of the 3 keys would fire it again.

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

I just wrote this script and it's working very well. It uses Shift+S to fire, but you can easily change that. It resets after pressing the combination.

我刚写了这个脚本,它运行得很好。它使用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");
    }

Fiddle: http://jsfiddle.net/9m8yswwo/13/

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

#6


1  

A bit more modern solution, takes advantage of arrow functions and rest parameters:

更现代一点的解决方案,利用箭头函数和rest参数:

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>

#7


1  

I have answer from T.J. Crowder in plain javascript for someone who would want to avoid Jquery.

我从T.J. Crowder那里得到了一些简单的javascript答案,希望避开Jquery。

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

#8


0  

You should use the keydown and keyup events, to handle more then one key "at the same time".

您应该使用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
                        }
                    });

#9


0  

if I well understood : example fiddle, http://jsfiddle.net/gAtTk/ (look at your js console)

如果我理解的很好:示例fiddle, http://jsfiddle.net/gAtTk/(查看您的js控制台)

this code will let you enter the word "dev" (and in this example, at the end the event keyup is removed)

这段代码将允许您输入“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


0  

Use this code to have an event triggered by multiple key presses + Timeout after 100ms to prevent mistypes. In this example : if A,Z,E are pressed within a time period of 100ms, the event will be triggered.

使用此代码使多个键按+ 100ms后超时触发事件,以防止出现错误。在本例中:如果按A、Z、E的时间间隔为100ms,则事件将被触发。

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


-1  

If you care about the order and also need to hold a key and tap another (ex: Shift + DEL, DEL, DEL...), without having to lift up on the first key to get the event to fire again... I've modified @BlakePlumm's [fiddle] comment which extended @lu1s' comment on @ParthThakkar's answer.

如果你关心订单,还需要拿一个钥匙和另一个(ex: Shift + DEL, DEL, DEL…),而不需要在第一把钥匙上举起来让事件再次发生……我修改了@BlakePlumm的[fiddle]注释,扩展了@lu1s对@ParthThakkar的回复的注释。

Also, using jQuery's .on() allows you to listen for the key sequence only on certain elements. Change 'body' to 'input.selector' or whatever else.

此外,使用jQuery的.on()允许您只在某些元素上监听键序列。改变“身体”的输入。选择器”或其他。

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

Additional thoughts: If you only kinda care about the order - that is, the first keys just need to be down, as long as your main event-firing key is pressed last (stuff like CTRL+SHIFT+TAB, TAB, TAB), add this condition:

附加的想法:如果你只关心顺序——也就是说,只要你的主事件触发键按在最后(比如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');
    }
}

fiddle with more glorious options and live demo: - http://jsfiddle.net/kstarr/4ftL1p3k/

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

#12


-1  

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

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

Check this out. You might be looking for this.

看看这个。你可能在找这个。

We can trigger a function on multiple key press. eg: p+t+k

我们可以在多个按键上触发一个函数。例如: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();
    });

maybe your looking for this.

也许你在找这个。

#1


65  

If you want to detect that the d, e, and v keys were all down at the same time, you have to watch both keydown and keyup and keep a map of the ones that are down. When they're all down, fire your event.

如果你想要检测出d, e,和v的键都在同时下降,你必须同时观察按键和按键,并保存一个按键的地图。当他们都倒下的时候,启动你的事件。

For example: Live copy | source

例如:Live copy |源代码。

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

I assume you don't care what order they're pressed down in (as that would be a pain to reliably press) as long as they're all down at the same time at some point.

我猜你不会在意它们被按下的顺序(因为要想可靠地按下会很痛苦),只要它们在同一时刻都被按下。

#2


18  

Similar to Vega's...but simpler

类似于维加的…但更简单

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

#3


8  

Perhaps a simpler key combination would be easier?

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

How about something like Shift + Alt + D? (You probably shouldn't use the Control key because most browsers already interpret Ctrl+D in one way or another)

比如平移+ Alt + D?(您可能不应该使用控制键,因为大多数浏览器已经以这样或那样的方式解释了Ctrl+D)

The code for this would be something like this:

它的代码是这样的:

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

#4


1  

You would need to capture the three key events separately and fire your action only after the third one.

您需要分别捕获这三个关键事件,并只在第三个事件之后才启动操作。

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...');
    }
});​

There's a number of ways to do this of course. This example doesn't require you to hold the keys down simultaneously, just that you type them in order: d e v.

当然有很多方法可以做到这一点。本例不要求您同时按住键,只需按d ev的顺序输入它们。

If you used this, you might want to augment it to clear the pressed flags after some time interval.

如果您使用了这个,您可能希望在一些时间间隔之后增加它来清除被压的标记。

Here's a working example.

这是一个工作示例。


Disclaimer: I realize the original question said that the keys should be "pressed together". This is just an alternative as other answerers have already provided sufficient solutions for the keys being pressed together.

免责声明:我知道原来的问题说钥匙应该“按在一起”。这只是另一种选择,因为其他应答者已经为键被压在一起提供了足够的解决方案。

#5


1  

I tried the three top answers (as of this post), and none of them worked for me. They didn't reset the keys.

我尝试了三个最常见的答案(在这篇文章中),但没有一个对我有效。他们没有重置钥匙。

If it took 3 keys fire the script, after firing it once - pressing any one of the 3 keys would fire it again.

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

I just wrote this script and it's working very well. It uses Shift+S to fire, but you can easily change that. It resets after pressing the combination.

我刚写了这个脚本,它运行得很好。它使用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");
    }

Fiddle: http://jsfiddle.net/9m8yswwo/13/

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

#6


1  

A bit more modern solution, takes advantage of arrow functions and rest parameters:

更现代一点的解决方案,利用箭头函数和rest参数:

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>

#7


1  

I have answer from T.J. Crowder in plain javascript for someone who would want to avoid Jquery.

我从T.J. Crowder那里得到了一些简单的javascript答案,希望避开Jquery。

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

#8


0  

You should use the keydown and keyup events, to handle more then one key "at the same time".

您应该使用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
                        }
                    });

#9


0  

if I well understood : example fiddle, http://jsfiddle.net/gAtTk/ (look at your js console)

如果我理解的很好:示例fiddle, http://jsfiddle.net/gAtTk/(查看您的js控制台)

this code will let you enter the word "dev" (and in this example, at the end the event keyup is removed)

这段代码将允许您输入“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


0  

Use this code to have an event triggered by multiple key presses + Timeout after 100ms to prevent mistypes. In this example : if A,Z,E are pressed within a time period of 100ms, the event will be triggered.

使用此代码使多个键按+ 100ms后超时触发事件,以防止出现错误。在本例中:如果按A、Z、E的时间间隔为100ms,则事件将被触发。

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


-1  

If you care about the order and also need to hold a key and tap another (ex: Shift + DEL, DEL, DEL...), without having to lift up on the first key to get the event to fire again... I've modified @BlakePlumm's [fiddle] comment which extended @lu1s' comment on @ParthThakkar's answer.

如果你关心订单,还需要拿一个钥匙和另一个(ex: Shift + DEL, DEL, DEL…),而不需要在第一把钥匙上举起来让事件再次发生……我修改了@BlakePlumm的[fiddle]注释,扩展了@lu1s对@ParthThakkar的回复的注释。

Also, using jQuery's .on() allows you to listen for the key sequence only on certain elements. Change 'body' to 'input.selector' or whatever else.

此外,使用jQuery的.on()允许您只在某些元素上监听键序列。改变“身体”的输入。选择器”或其他。

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

Additional thoughts: If you only kinda care about the order - that is, the first keys just need to be down, as long as your main event-firing key is pressed last (stuff like CTRL+SHIFT+TAB, TAB, TAB), add this condition:

附加的想法:如果你只关心顺序——也就是说,只要你的主事件触发键按在最后(比如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');
    }
}

fiddle with more glorious options and live demo: - http://jsfiddle.net/kstarr/4ftL1p3k/

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

#12


-1  

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

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

Check this out. You might be looking for this.

看看这个。你可能在找这个。

We can trigger a function on multiple key press. eg: p+t+k

我们可以在多个按键上触发一个函数。例如: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();
    });

maybe your looking for this.

也许你在找这个。