简体   繁体   中英

Detect multiple keys on single keypress event in jQuery

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.

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.

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.

For example: 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;
    }
});

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.

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

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)

The code for this would be something like this:

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

I have answer from TJ Crowder in plain javascript for someone who would want to avoid 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;
    }
});

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 .

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.

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.

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.

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/

A bit more modern solution, takes advantage of arrow functions and rest 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> 

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

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

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

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

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

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.

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

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.

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.

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:

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/

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

 $(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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM