4

Can I know the number of keys pressed at the same time in Javascript?

If so, how can I have an array of their keyCode?

Alexandre Khoury
  • 3,896
  • 5
  • 37
  • 58
  • 3
    It should be noted, just for completion sake, that it's impossible for two keys to be pressed at the *SAME* time. Javascript is, inherently, synchronous (this also leaves out the extreme difficulty of physically doing something at the SAME TIME). It would be impossible for two keyPress events to be fired at the same time. What this is means is one of the few suggestions below is the right approach: Track every time a key is pressed. When the two keys you want to be pressed are pressed in succession, and at a minimal time in between each press, you have your key stroke. – Jason L. Jul 15 '12 at 16:50
  • @JasonL. - "It should be noted, just for completion sake, that it's impossible for two keys to be pressed at the SAME time." Would you kindly press F4 and Alt at the same time. – Travis J Jul 20 '12 at 21:18
  • 1
    @TravisJ I just did it and nothing happened - Mac User – Alexandre Khoury Jul 20 '12 at 21:23
  • @Mageek - Nothing eh? Did you try Q + ⌘? – Travis J Jul 20 '12 at 21:25
  • @TravisJ That is not being processed by javascript and the key presses are not happening in a single-threaded environment where it is impossible for two things to happen at the same time. http://en.wikipedia.org/wiki/Single_threading – Jason L. Jul 20 '12 at 21:29
  • @TravisJ Nothing too ! (:D It works only if you press ⌘ then Q) – Alexandre Khoury Jul 20 '12 at 21:30
  • 1
    @TravisJ: You can be holding two keys at the same time, but JavaScript cannot detect two keys being pressed at the same time. What you're referring to is a Meta key like Alt and Ctrl. If those are pressed, then that is detectable; however, arbitrary key combinations cannot be detected directly. – Dancrumb Jul 21 '12 at 20:27

3 Answers3

11

You can listen for keydown and keyup events.

var keys = { length: 0 };

document.onkeydown = function(e){
    if(!keys[e.keyCode])   {
        keys[e.keyCode] = true;
        keys.length++;
    }
}

document.onkeyup = function(e){
    if(keys[e.keyCode])   {
        keys[e.keyCode] = false;
        keys.length--;
    }
}

Then all the keys that are true are the ones that are pressed currently.

Fiddle demo thanks to @Esailija: http://jsfiddle.net/maniator/Gc54D/

Naftali
  • 144,921
  • 39
  • 244
  • 303
  • 1
    Note that `onkeydown` fires constantly as they key is held down so it will inflate the `.length` – Esailija Jul 11 '12 at 18:09
  • If you press on a key like `o` and you wait, `keys.length` will keep getting higher but you're still pressing one key. – Alexandre Khoury Jul 11 '12 at 18:09
  • @Esailija I fixed it so that it should not do that ^_^ – Naftali Jul 11 '12 at 18:10
  • @Neal Very good, but there is a bug with me. If I press `Command`+`Shift`+`Z` then I remove my fingers, length keeps at 1. – Alexandre Khoury Jul 11 '12 at 18:14
  • @Mageek hmm that seems to happen when you press buttons and then click out of the window before depressing the keys – Naftali Jul 11 '12 at 18:19
  • @Mageek I don't see the issue you are talking about on my side. What browser/OS versions are you running on? – MMeah Jul 17 '12 at 05:32
  • @MMeah Firefox/Mac But it's only with the specific keys – Alexandre Khoury Jul 17 '12 at 11:27
  • 1
    I tried this on MAC OSX (10.7) and [forked (new link)](http://jsfiddle.net/insertusernamehere/sfU4k/) your fiddle to see what happens. Thus the **cmd**-key is some sort of system-key it seems to behave like this: When pressing **cmd + anykey** and then release **anykey** the JavaScript won't fire. When pressing **cmd + anykey** and release the **cmd-key** and than release **anykey** it works just fine. It seems like the system is locking the keys from the content as it thinks you might want to interact with the browser's key commands. – insertusernamehere Jul 17 '12 at 16:42
1

This should do the trick. It is similar to Neal's, but should fix a few issues, including the leaving-the-window bug and the negative-numbers-of-keys bug. I also streamlined the message writing code a bit. I replaced the timer loop for writing the number of keys message with an on-demand system, added a safety mechanism for decrementing the length index, and added the clearKeys to switch all keys to up when the user leaves the window. The code still has two bugs: it will not recognize keys that are still held down after a new window has been opened and closed (they must be released and re-pushed), and I can't get it to recognize more then six keys (I suspect this isn't related to this code, but the computer/browser...).

var keys = {
    length: 0
};

window.onkeydown = function(e) {
    if (!keys[e.keyCode]) {
        keys[e.keyCode] = true;
        keys.length++;
        document.body.innerHTML = "You are pressing " + keys.length + " keys at the same time.";
    }
}

window.onkeyup = function(e) {
    if (keys[e.keyCode]) {
        keys[e.keyCode] = false;
        if (keys.length) {
            keys.length--;
        }
        document.body.innerHTML = "You are pressing " + keys.length + " keys at the same time.";
    }
}

function clearKeys() {
    for (n in keys) {
        n = false
    };
    keys.length = 0;
    document.body.innerHTML = "You are pressing " + 0 + " keys at the same time.";
}

document.body.innerHTML = "You are pressing 0 keys at the same time.";
window.onblur = clearKeys;
mindoftea
  • 816
  • 6
  • 16
  • Not more than 6 keys is not a problem, but it has the bug I described here: http://stackoverflow.com/questions/11438668/keys-pressed-at-the-same-time/11490193#comment15177132_11490193 – Alexandre Khoury Jul 15 '12 at 09:24
1

Since you want the number of keys pressed at the same time and an array of their key codes I suggest you use the following function:

var getKeys = function () {
    var keys = [];

    window.addEventListener("blur", blur, false);
    window.addEventListener("keyup", keyup, false);
    window.addEventListener("keydown", keydown, false);

    return function () {
        return keys.slice(0);
    };

    function blur() {
        keys.length = 0;
    }

    function keyup(event) {
        var index = keys.indexOf(event.keyCode);
        if (index >= 0) keys.splice(index, 1);
    }

    function keydown(event) {
        var keyCode = event.keyCode;
        if (keys.indexOf(keyCode) < 0)
        keys.push(keyCode);
    }
}();

When you call getKeys it will return an array of all the keys pressed at the same time. You can use the length property of that array to find the number of keys pressed at the same time. Since it uses addEventListener it works cooperatively with other code on the page as well.

I tested the above function and it always returns the correct keys pressed even when you switch to another window while holding down a key (it removes that key from the array). If you hold a key and switch back then it recognizes that a key is pressed and it pushes in onto the array. Hence I can testify that there are no bugs in the above code. At least not on the browser I tested it on (Opera 12.00).

I was able to press 8 keys at the same time (A, S, D, F, J, K, L and ;). This number seems OS specific as I can only press 4 left hand keys and 4 right hand keys at the same time. For example after I press A, S, D and F, and then I press another left hand (let's say G) then it won't recognize the last key. This is probably because the OS knows how humans type and so it only allows four interrupts for each of the left and right hand keys. The OS I am using is Ubuntu 12.04.

You can see the code in action on this fiddle. I used a Delta Timer instead of setInterval to display the results after every 50 ms. You may also wish to read the following answer as well.

Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • It's very good, but there is still a bug :( When I hold `Command`+`Shift`+`Z` or `Command`+`Shift`+`X`, then I release my fingers, it's still displaying 1 key pressed. (And I discovered that if you press a letter after that and then release it, the result come back to 0). – Alexandre Khoury Jul 15 '12 at 09:22
  • I see that you are using a Macintosh. Well that seems to be an OS specific issue. I tried the same key combinations on Ubuntu and it works like a charm. Note that `Ctrl` is the equivalent of `Command` on an IBM keyboard. – Aadit M Shah Jul 15 '12 at 09:34