Fuck browser keyboard events

In the HTML5 era programming in Javascript with browser APIs is mostly a joy. But sometimes you find a rough edge, in particular keyboard events. My zipdecode example had a simple problem: ordinary number keys worked, but not the numeric keypad. Because I was using the event.keyCode field, this ancient bit of savagery that tells me what button was pressed as opposed to what the user typed and both 48 and 96 mean 0. So I thought I’d try to update my code to the modern HTML5 way. Some things I learned:

  • Here’s a very simple tool for exploring keyCode.
  • String.fromCharCode() sometimes works for translating keyCodes to strings, but not always.
  • Here’s a very detailed guide to keyboard event behavior in various browsers. A bit outdated. The QuirksMode guide also has useful info but doesn’t cover what’s inside the event objects. Also maybe this StackOverflow question and this one.
  • keypress is the synthetic event fired off indicating “a user meant to type this thing”. If you can use it, use it. However it’s not always fired off, depending on the browser. (Ie: no left arrow in chrome). Also you can’t use it to suppress default behavior like backspace navigation.
  • keydown is the low level event fired when the switch is depressed. if you preventDefault() the event, in Chrome it means keypress is never fired but in Firefox it is fired anyway. (I think; didn’t test carefully.)
  • Any of the following fields of the event object may contain what button was pressed: char, charCode, key, keyCode, which. Most docs say “which” is the reliable choice (except for IE), but MDN notes it’s deprecated and says you should use key instead. Only “key” is not implemented in Firefox. Ha ha! Also while these fields are likely to be fileld out in a keypress event, they’re less likely to be present in a keydown event.

I was going to finish this blog post with a summary of the right modern way to do things, but I don’t think there is one yet. Then I was going to say this is a temporary state of affairs, but most of the HTML5-era questions I’m reading date back to 2010 so, um, not new.

I suspect the browser API mavens are scared to touch keyboard events. Partly it’s hard to specify because of internationalization, and partly it’s hard to implement because of cross-OS compatibility issues. I’ll note that jQuery apparently doesn’t have a library to solve this once and for all, either.

Update consider the d3.keybinding.js library from MapBox, for the iD editor.