251

I thought this would be answered somewhere on Stack Overflow, but I can’t find it.

If I’m listening for a keypress event, should I be using .keyCode or .which to determine if the Enter key was pressed?

I’ve always done something like the following:

$("#someid").keypress(function(e) {
  if (e.keyCode === 13) {
    e.preventDefault();
    // do something
  }
});

But I’m seeing examples that use .which instead of .keyCode. What’s the difference? Is one more cross-browser friendly than the other?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
ScottE
  • 21,530
  • 18
  • 94
  • 131
  • 3
    Both of these are considered deprecated now, FYI. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode – CodeFinity Nov 27 '17 at 14:07

7 Answers7

231

Note: The answer below was written in 2010. Here many years later, both keyCode and which are deprecated in favor of key (for the logical key) and code (for the physical placement of the key). But note that IE doesn't support code, and its support for key is based on an older version of the spec so isn't quite correct. As I write this, the current Edge based on EdgeHTML and Chakra doesn't support code either, but Microsoft is rolling out its Blink- and V8- based replacement for Edge, which presumably does/will.


Some browsers use keyCode, others use which.

If you're using jQuery, you can reliably use which as jQuery standardizes things; More here.

If you're not using jQuery, you can do this:

var key = 'which' in e ? e.which : e.keyCode;

Or alternatively:

var key = e.which || e.keyCode || 0;

...which handles the possibility that e.which might be 0 (by restoring that 0 at the end, using JavaScript's curiously-powerful || operator).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 2
    Thanks T.J. Where would I find a reference for this? Not that I don't believe you, I'm just curious! ...I see you just added that, thanks. So, even for those not using jquery, .which is a better choice? – ScottE Dec 17 '10 at 14:55
  • 7
    @ScottE: If not using jQuery, you have to handle this explicitly yourself. I usually do it like this `var key = event.which || event.keyCode;` That will use `event.which` if it's defined and not falsey, or `event.keyCode` if `which` is undefined or falsey. Technically I should probably do `var key = typeof event.which === "undefined" ? event.keyCode : event.which;` but if `event.which` is `0` (can it be `0`?), I'm unlikely to care for the kinds of things I do. – T.J. Crowder Dec 17 '10 at 15:02
  • 2
    @ScottE, here is a basic reference: http://www.quirksmode.org/js/keys.html (it doesn't include `which`, which I think is only provided by jQuery but I'm not 100% sure, but it should get you started on seeing differences in browsers) – Mottie Dec 17 '10 at 15:05
  • 1
    @fudgey: `which` is provided for `keypress` by all browsers except IE. And quirksmode is not authoritative here. As a reference, the link that @T.J. Crowder posted is much better: http://unixpapa.com/js/key.html. – Tim Down Dec 18 '10 at 12:11
  • 5
    @T.J. Crowder: Yes, the event's `which` property can be zero, and this can make a big difference to most applications. For example, non-printable keys in Firefox have a `which` property of zero and the same `keyCode` property as `keydown`. The Home key has a `keyCode` of 36 on my PC in Firefox, which is the character code for "$", which would make it impossible to distinguish between the user pressing the Home key and the user typing a $ character using `event.which || event.keyCode`. – Tim Down Dec 18 '10 at 12:31
  • @Tim: Thanks, I figured it probably could be. I haven't needed to hook into anything where it was.... *yet*! – T.J. Crowder Dec 18 '10 at 18:11
  • @T.J. Crowder: Could you please explain why in [this question](http://stackoverflow.com/q/18177818/247243) `event.which` is not normalized? – Misha Moroshko Aug 12 '13 at 10:19
  • As of jQuery 1.11, it does not appear that jQuery fully normalizes the `event.which` property, at least under FireFox. As can be seen here: http://jsbin.com/sozoqiro/1/edit?html,console `event.which` and `event.keyCode` both have different values depending on what key you press. Pressing a printing character seems to populate `e.which` while the Tab key for instance populates `e.keyCode` and the Enter key populates both `e.which` and `e.keyCode` with the same value. In FireFox, the unpopulated property value is set to `0`. – DavidScherer Jun 06 '14 at 21:14
  • In Chrome, this seems to be normalized, but `keypress` does not seem to trigger for Tab keys in Chrome. – DavidScherer Jun 06 '14 at 21:19
  • 1
    Please note that KeyboardEvent.keyCode is deprecated – slykat Apr 14 '17 at 19:53
  • @DavidScherer also, `F5` does not trigger. Some keys cannot be captured/detected, and rightfully so! – pid Nov 13 '19 at 07:49
  • @slykat - So is `which`. :-) – T.J. Crowder Nov 13 '19 at 08:22
33

jQuery normalises event.which depending on whether event.which, event.keyCode or event.charCode is supported by the browser:

// Add which for key events
if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
   event.which = event.charCode != null ? event.charCode : event.keyCode;
}

An added benefit of .which is that jQuery does it for mouse clicks too:

// Add which for click: 1 === left; 2 === middle; 3 === right
// Note: button is not normalized, so don't use it
if ( !event.which && event.button !== undefined ) {
    event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
}
David Tang
  • 92,262
  • 30
  • 167
  • 149
  • 2
    `var key = event.which || event.charCode || event.keyCode` – Anne van Rossum Jul 04 '14 at 09:03
  • @anne-van-rossum, `event.wich == null && ...` test for null or undefined only. your `event.wich || ...` test for _falsy_ (undefined, null, false, 0, '', etc) – aMarCruz May 22 '15 at 11:54
  • @aMarCruz Falsy on purpose. E.g. https://bugs.webkit.org/show_bug.cgi?id=16735 with Webkit reporting `0`. And I don't think checking for `""` or `[]` hurts. – Anne van Rossum May 24 '15 at 08:50
22

If you are staying in vanilla Javascript, please note keyCode is now deprecated and will be dropped:

This feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped. Avoid using it and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any tim

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

Instead use either: .key or .code depending on what behavior you want: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

Both are implemented on modern browsers.

slykat
  • 856
  • 1
  • 11
  • 18
  • **.code** corresponds to physical location of the key on the keyboard whereas **.key** corresponds to the character generated by the key pressed regardless of location. – Christopher Sep 22 '17 at 15:36
  • 1
    Both 'code' and 'key' have quirks in modern browsers. Using the "Try it out" example on MDN https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code in different browsers shows that IE11/IE Edge don't implement 'code' and the 'key' implementation doesn't match the implementation in Chrome/FF/Safari (differences appear to mainly be in control characters like Escape and Enter). I think using a library might be easiest unless you're willing to account for these vagaries yourself. I really want this to be the answer, but IE screws this one up :-( – Akrikos Feb 14 '18 at 15:43
  • Hmm... actually it doesn't look too bad to implement key in a cross browser way. Regular alphanumeric keys just return their value and for control keys (escape, enter, tab, etc) appear implemented identically in most browsers except IE11/Edge which implement an older version of the spec, so at least there are only two possible values for each key. – Akrikos Feb 14 '18 at 15:53
  • I would advise using `key` instead of `code`. For example, if you have a keyboard with media control keys, pressing Play/Pause outputs "MediaPlayPause" for `key` and "" for `code`. – thdoan Mar 21 '18 at 22:45
  • IMO nothing will ever be dropped from browser implementations because this would break many existing sites and libraries. – cskwg Jul 19 '21 at 07:42
9

I'd recommend event.key currently. MDN docs: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key

event.KeyCode and event.which both have nasty deprecated warnings at the top of their MDN pages:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/which

For alphanumeric keys, event.key appears to be implemented identically across all browsers. For control keys (tab, enter, escape, etc), event.key has the same value across Chrome/FF/Safari/Opera but a different value in IE10/11/Edge (IEs apparently use an older version of the spec but match each other as of Jan 14 2018).

For alphanumeric keys a check would look something like:

event.key === 'a'

For control characters you'd need to do something like:

event.key === 'Esc' || event.key === 'Escape'

I used the example here to test on multiple browsers (I had to open in codepen and edit to get it to work with IE10): https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code

event.code is mentioned in a different answer as a possibility, but IE10/11/Edge don't implement it, so it's out if you want IE support.

Akrikos
  • 3,595
  • 2
  • 24
  • 22
6

look at this: https://developer.mozilla.org/en-US/docs/Web/API/event.keyCode

In a keypress event, the Unicode value of the key pressed is stored in either the keyCode or charCode property, never both. If the key pressed generates a character (e.g. 'a'), charCode is set to the code of that character, respecting the letter case. (i.e. charCode takes into account whether the shift key is held down). Otherwise, the code of the pressed key is stored in keyCode. keyCode is always set in the keydown and keyup events. In these cases, charCode is never set. To get the code of the key regardless of whether it was stored in keyCode or charCode, query the which property. Characters entered through an IME do not register through keyCode or charCode.

Pickmeup101
  • 319
  • 3
  • 4
4

In Firefox, the keyCode property does not work on the onkeypress event (will only return 0). For a cross-browser solution, use the which property together with keyCode, e.g:

var x = event.which || event.keyCode;  // Use either which or keyCode, depending on browser support
Pankaj Chauhan
  • 1,623
  • 14
  • 12
3

A robust Javascript library for capturing keyboard input and key combinations entered. It has no dependencies.

http://jaywcjlove.github.io/hotkeys/

hotkeys('ctrl+a,ctrl+b,r,f', function(event,handler){
    switch(handler.key){
        case "ctrl+a":alert('you pressed ctrl+a!');break;
        case "ctrl+b":alert('you pressed ctrl+b!');break;
        case "r":alert('you pressed r!');break;
        case "f":alert('you pressed f!');break;
    }
});

hotkeys understands the following modifiers: , shift, option, , alt, ctrl, control, command, and .

The following special keys can be used for shortcuts: backspace, tab, clear, enter, return, esc, escape, space, up, down, left, right, home, end, pageup, pagedown, del, delete and f1 through f19.

小弟调调
  • 1,315
  • 1
  • 17
  • 33
  • It does shim Array.prototype.indexOf though, so if you're using this in another library, it may not be suitable as it modifies the global scope. It also appears to use the deprecated `event.keyCode`. – Akrikos Feb 14 '18 at 16:17
  • This library didn't detect Fn on my Vaio laptop. – thdoan Mar 21 '18 at 22:27