Detecting arrow key presses in JavaScript

619,658

Solution 1

Arrow keys are only triggered by onkeydown, not onkeypress.

The keycodes are:

  • left = 37
  • up = 38
  • right = 39
  • down = 40

Solution 2

On key up and down call function. There are different codes for each key.

document.onkeydown = checkKey;

function checkKey(e) {

    e = e || window.event;

    if (e.keyCode == '38') {
        // up arrow
    }
    else if (e.keyCode == '40') {
        // down arrow
    }
    else if (e.keyCode == '37') {
       // left arrow
    }
    else if (e.keyCode == '39') {
       // right arrow
    }

}

Solution 3

event.key === "ArrowRight"...

More recent and much cleaner: use event.key. No more arbitrary number codes! If you are transpiling or know your users are all on modern browsers, use this!

node.addEventListener('keydown', function(event) {
    const key = event.key; // "ArrowRight", "ArrowLeft", "ArrowUp", or "ArrowDown"
});

Verbose Handling:

switch (event.key) {
    case "ArrowLeft":
        // Left pressed
        break;
    case "ArrowRight":
        // Right pressed
        break;
    case "ArrowUp":
        // Up pressed
        break;
    case "ArrowDown":
        // Down pressed
        break;
}

Modern Switch Handling:

const callback = {
    "ArrowLeft"  : leftHandler,
    "ArrowRight" : rightHandler,
    "ArrowUp"    : upHandler,
    "ArrowDown"  : downHandler,
}[event.key]
callback?.()

NOTE: The old properties (.keyCode and .which) are Deprecated.

"w", "a", "s", "d" for direction, use event.code

To support users who are using non-qwerty/English keyboard layouts, you should instead use event.code. This will preserve physical key location, even if resulting character changes.

event.key would be , on Dvorak and z on Azerty, making your game unplayable.

const {code} = event
if (code === "KeyW") // KeyA, KeyS, KeyD

Optimally, you also allow key remapping, which benefits the player regardless of their situation.

P.S. event.code is the same for arrows

key Mozilla Docs

code Mozilla Docs

Supported Browsers

Solution 4

Possibly the tersest formulation:

document.onkeydown = function(e) {
    switch (e.keyCode) {
        case 37:
            alert('left');
            break;
        case 38:
            alert('up');
            break;
        case 39:
            alert('right');
            break;
        case 40:
            alert('down');
            break;
    }
};

Demo (thanks to user Angus Grant): http://jsfiddle.net/angusgrant/E3tE6/

This should work cross-browser. Leave a comment if there is a browser where it does not work.

There are other ways to get the key code (e.which, e.charCode, and window.event instead of e), but they should not be necessary. You can try most of them out at http://www.asquare.net/javascript/tests/KeyCode.html. Note that event.keycode does not work with onkeypress in Firefox, but it does work with onkeydown.

Solution 5

Use keydown, not keypress for non-printable keys such as arrow keys:

function checkKey(e) {
    e = e || window.event;
    alert(e.keyCode);
}

document.onkeydown = checkKey;

The best JavaScript key event reference I've found (beating the pants off quirksmode, for example) is here: http://unixpapa.com/js/key.html

Share:
619,658
mihsathe
Author by

mihsathe

Updated on July 19, 2022

Comments

  • mihsathe
    mihsathe almost 2 years

    How do I detect when one of the arrow keys are pressed? I used this to find out:

    function checkKey(e) {
        var event = window.event ? window.event : e;
        console.log(event.keyCode)
    }
    

    Though it worked for every other key, it didn't for arrow keys (maybe because the browser is supposed to scroll on these keys by default).

  • Tim Down
    Tim Down about 13 years
    Some browsers do trigger keypress events for arrow keys, but you're right that keydown always works for arrow keys.
  • eshellborn
    eshellborn almost 11 years
    What does the second line do?
  • eshellborn
    eshellborn almost 11 years
    'e = e || window.event;'
  • ketan
    ketan almost 11 years
    It will get the event
  • xorcus
    xorcus over 10 years
    If you press %, you also get keyCode 37
  • None
    None over 10 years
    @xorcus -- No, you get 53 with a keydown event. You get 37 with keypress, which is a different thing
  • Michael Calvin
    Michael Calvin over 10 years
    To clarify, 'e || window.event' means that if 'e' is a defined value, it will be the result of the '||' expression. If 'e' is not defined, 'window.event' will be the result of the '||' expression. So it's basically shorthand for: e = e ? e : window.event; Or: if (typeof(e) === "undefined") { e = window.event; }
  • Mark Rhodes
    Mark Rhodes over 10 years
    It's to make it work on old versions of IE (pre IE9) where the event was not passed into the handler function.
  • alexrogers
    alexrogers about 9 years
    Just to note keyCode is a number and === should ideally be used
  • ketan
    ketan about 9 years
    @alexrogins have you checked? jsfiddle.net/AjKjU/86 and jsfiddle.net/AjKjU/87.
  • alexrogers
    alexrogers about 9 years
    Sorry, I don't understand your what your fiddle is showing. Have I checked what? I have edited your answer, please can you approve it as it is correct? Should be jsfiddle.net/AjKjU/88
  • Joel Peltonen
    Joel Peltonen about 9 years
    @ketan the point was that keyCode is a number and should be checked like keyCode === 32, not keyCode == '32' or keyCode === '32'.
  • animaacija
    animaacija almost 9 years
    short is good: if ([37,38,39,40].indexOf(e.keyCode)!=-1){ console.log('arrow pressed') }
  • pmrotule
    pmrotule almost 9 years
    @1nfiniti onkeyup won't consider the repeated call of the keydown event when you hold the arrow down.
  • Juribiyan
    Juribiyan over 8 years
    keypress won't work with arrow keys. You have to use $(document).on('keydown', function() {...}) instead
  • Grief
    Grief over 8 years
    Doesn't it worth to put arrs outside of the function? No need to recreate it every call
  • papo
    papo over 7 years
    I am getting $0 is not defined var targetElement = typeof $0 !== 'undefined' ? $0 : document.body; or just: var targetElement = document.body; is ok
  • MrCroft
    MrCroft over 7 years
    :( arrow key presses not being visible on "keypress" puts serious limitations. You practically can't do things like "if (evt.which === 40) { itemIndex +=1; scrollToFunction(...);" on "keypress" - which should keep scrolling as long as you don't take your finger off the arrow key. If we are forced to do that on keydown or keyup, then it will only triger the event ONCE, and we'd have to keep stroking the keydown arrow to scroll to a newly marked element in a list, instead of just holding down the arrow key.
  • None
    None over 7 years
    @MrCroft - or also listen to onkeyup and stop the event there. Realistically you shouldn't be modifying UI behavior with Javascript, however.
  • MrCroft
    MrCroft over 7 years
    @MarkKahn yeah, it's just that you have to listen to 2 events to be able to accomplish functionality that should have been accessible through 1 event alone, in my opinion. It is possible though, yeah... Nothing's really impossible, there are always ways to do it. I just think it should have been accessible altogether through the keypress event alone. Unfortunately, it's not.
  • v010dya
    v010dya almost 7 years
    Thank you for using key and not keyCode, that was deprecated.
  • Simon
    Simon almost 6 years
    Note from MDN: Internet Explorer, Edge (16 and earlier), and Firefox (36 and earlier) use "Left", "Right", "Up", and "Down" instead of "ArrowLeft", "ArrowRight", "ArrowUp", and "ArrowDown".
  • ecoe
    ecoe almost 5 years
    useful tool for confirming keycodes: blog.pothoven.net/2008/05/…
  • ashleedawg
    ashleedawg over 4 years
    I had to look up the definition of terse, then I (sprightfully) postulated that tersest was an improper conjugation; alas, I concede: my solicitude was refutable.
  • The Fool
    The Fool over 4 years
    keyup is most of the time what you want
  • CTS_AE
    CTS_AE about 4 years
    If you care about quick response then key up is "slow" for example if you made a game, you wouldn't want to act upon when the key is let go, you want to act as soon as the key registers, so you would want to do it on key down, but make sure not to repeat the key being held down until the key triggers it's associated key up and then you can reset it ready for another key down.
  • relief.melone
    relief.melone over 3 years
    as event.keyCode is deprecated this should be the accepted answer
  • Dmitry Koroliov
    Dmitry Koroliov about 3 years
    Now keypress has been marked as deprecated
  • Boogie
    Boogie about 2 years
    keyCode is deprecated. Please see developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCo‌​de Use key instead ie e.key === 'ArrowDown'
  • Iglesias Leonardo
    Iglesias Leonardo about 2 years
    I just loved the modern switch handling