Detect multiple keys on single keypress event in jQuery

64,603

Solution 1

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.

Solution 2

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

Solution 3

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

Solution 4

I have answer from T.J. 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;
    }
});

Solution 5

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>
Share:
64,603

Related videos on Youtube

remarsh
Author by

remarsh

Updated on July 09, 2022

Comments

  • remarsh
    remarsh almost 2 years

    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.

    • yent
      yent about 12 years
      The keyCode can represent only one key. Try to use a combination of keydown + keyup + flags to detect this.
    • Diodeus - James MacFarlane
      Diodeus - James MacFarlane about 12 years
    • Michał Perłakowski
      Michał Perłakowski over 8 years
      Consider changing the accepted answer to this. It presents more modern and general approach.
  • Selvakumar Arumugam
    Selvakumar Arumugam about 12 years
    mm as you have mentioned, i think the order is important for keyboard shortcuts.. ctrl+v is not same as v+ctrl
  • T.J. Crowder
    T.J. Crowder about 12 years
    @Vega: Modifier keys are a different kettle of fish.
  • Parth Thakkar
    Parth Thakkar about 12 years
    that isn't the answer to the question, is it?
  • lu1s
    lu1s about 12 years
    This is really good and will work well. If you need to match a sequence of the keys, then you may check the order by pushing to an array: Instead of down[e.keyCode]=true, say down.push(e.keyCode) and validate instead of this: if(down[68]&&down[69]&&down[86]), as this: if(down[0]===68&&down[1]===69&&down[2]===86).
  • gplumb
    gplumb about 12 years
    @ParthThakkar - From the question, you can derive the requirement: "to force it into a hidden developer mode". Being pragmatic, I suggested a simple alternative to acheive the same end result
  • Parth Thakkar
    Parth Thakkar about 12 years
    all right...that may be the way to go...i just thought that wasn't the answer to the required question, so i just asked that...no offence!)
  • FishBasketGordo
    FishBasketGordo about 12 years
    I tested this in Chrome, and it wasn't working with the original key codes. I've ran across this before, but I forget why they're different.
  • Blake Plumb
    Blake Plumb over 11 years
    I created a fiddle to complement lu1s comment.
  • poshest
    poshest over 8 years
    This won't work if the user continues to hold the Shift key down and presses S a second time. Forcing saveArray[0] = false in the S's keydown event (which makes an assumption that the Shift key was released) is a pretty horrible hack. On the other hand, it may just be the reason this worked for you.
  • Michał Perłakowski
    Michał Perłakowski over 8 years
    You can't assign a value to a variable which has not been yet defined.
  • Michał Perłakowski
    Michał Perłakowski over 8 years
    Please don't use new Array().
  • Cindy Meister
    Cindy Meister over 8 years
    Based on this discussion in Comments @GPlumb, it would probably be a good idea for you to include the remarks about this being an althernative to the considered approach and why...
  • kapsiR
    kapsiR over 8 years
    A variable without being defined at first would be a new variable on the global stack. This should just be an example how this would be possible. If you want, I can provide a JSFiddle, but the question is already marked as resolved...
  • Michał Perłakowski
    Michał Perłakowski over 8 years
    This is a bug, not a feature, and also global variables are bad.
  • kapsiR
    kapsiR over 8 years
    I know that - it should just be a demostration of the events, not of js itself ;)
  • Michał Perłakowski
    Michał Perłakowski over 8 years
    Which still doesn't excuse you from using bad coding practices.
  • kapsiR
    kapsiR over 8 years
    I will do better practise next time I post anything
  • T.J. Crowder
    T.J. Crowder about 8 years
    @DreamWave: No, the keyup handler clears the flags.
  • Sebastian Manuelli
    Sebastian Manuelli almost 3 years
    Working like a charm, also thank you @lu1s for the keys order ! :)