Keyboard events in Javascript are broken

Jan. 30, 2013
comments

The venerable computer keyboard. You probably have one. In Javascript we can get keyboard events, but they are completely useless if you are differently-abled, if you try to make an accessible rich internet application or game or if you just have a different keyboard layout.

The following blog post examines the technical barriers to make a web based game or web based rich client application accessible for everybody.

Contents

What is a keyboard?

As you can see, it has keys, lots of em.

Each key is labelled in some way, such that when you search a key, you can find it. As time goes by, you learn all these symbols, and have them memorized.

Games, i18n and accessability

I am sure you want your next application or game to be enjoyed by as many people as possible. There are a few things you need to do:

  • People with different keyboard layouts than your own should have no difficulty using your application.
  • Differently-abled persons might have different ideas about what combinations of keys are easy for them to press and reach.

The bane of German keyboards

You might have played a web game once in a while. There is a kind of control scheme where the keys Z and X would be used to control something. That's a good idea right? X and Z are right next to each other, aren't they?

US English keyboard layout

Swiss German keyboard layout

Ooops! But it's just swiss german right? That's barely 7 million people, or so. Nope, sorry dude, it's the same in Czech, Germany, Austria, Hungary, Poland and Slavic Latin. In Turkish the X and Z are at completely different places, and you won't even have an X and Z in Arabic, Armenian and so on.

Make it configurable stupid

So how do we make sure that we can do that? After all, different keyboard layouts and differently-abled persons come in all kinds of variants, how can you make sure to make things pleasant for everybody?

The answer is fairly straightforward, you make it configurable. I'm sure you know what I mean, but just to make it perfectly clear a couple screenshots how that usually looks.

Blender:

Gimp:

Minecraft:

Great Idea, let's do it in Javascript... NOT

So what do we need in order to make key mapping work in our Javascript web application? We will need the following:

  • The description of a key we can show a user that should match what is printed on his keys (the primary character or function)
  • A unique numeric key-code for each key such that when the user presses the key in any combination of modifiers, that we get the same key code.

There are two javascript key events for when a key is pressed. keypress and keydown.

  • keyCode: the numeric keyCode
  • which: some arbitrary mixture of charCode and keyCode
  • charCode: the numeric charCode, we can use String.fromCharCode to convert that to a printable character.

By some reading of Mozillas MDN all three attributes are depreceated anyway.

Keypress is broken

The keypress event does not deliver a "keyCode" or "which". It does deliver a "charCode", but the char code changes depending on modifier keys and it can be the same character for different keys. For example the key "1".

  • When pressed above the keyboard: "1"
  • When pressed with shift: "=" (in german it's "+")
  • When pressed from the numeric pad: "1"
  • When pressed from the numeric pad with shift: no event at all.

Keypress also does not deliver events for most non printable keys. So this event is a dud, we can't use it reliably for anything.

Keydown is broken

Keydown is better, it gets triggered for every key that is pressed, also the non printable ones. However the keydown event does not deliver a charCode (and it would be useless anyway). It does however deliver a keyCode, that sounds promising. But keyCode is also broken:

  • The same keyCode is triggered for different keys
  • It has the same problem as the keypress, keycodes change based on modifier keys (such as shift)
  • The keycodes cannot be converted to a key description because that would require knowledge of the users keyboard layout.

There is a standard for that isn't there?

The DOM Level 3 Events standard section on keyboard events looks like it tries to solve some of these issues.

  • char: "char holds the character value of the key pressed."
  • key: "key holds the key value of the key pressed. If the value is has a printed representation, it must match the value of the KeyboardEvent.char attribute"
  • location: "The location attribute contains an indication of the location of the key on the device"

This smells like it is modified characters in the char member. We have already established that this is of no use for shortcuts. The same gets dragged into the key member since it has to match the char member. And the location member is not a unique numeric key code, it is one of half a dozen indicators where in a group of keys a key might be (numpad etc.). So this standard is of no use to games and rich web applications needing keyboard shortcuts.

There is a corresponding discussion on the topic which I kicked off at www-dom@w3.org

But at this point in time, at least it does not matter because nobody even implements this standard.

Crap

Update: Event Level 4 standard

It has been pointed out to me in comments and on mailing lists that there exists a standard attempting to solve this very issue. Jipee!

The standard is Event Level 4 and it does indeed solve the unmodified key identifier problem.

There are in my opinion still issues with it:

  • While it does introduce a unmodified human readable "code" attribute, that code might not mean anything to a user. So instead of "ctrl+alt+/" it would read as "ctrl+alt+ForwardSlash". Localization of a key into a users locale primary key symbol (if printable) is still something that is desired.
  • This is a minor point, but for reasons of efficiency a numeric key-code additionally would also be nice.

This is my keyboard, please let me use it

Dear W3C, WhatWG, Google, Mozilla, Apple et. Al. Below you will find a concise recommendation what Games and WebApplications will need to support keyboard actions/shortcuts.

  • A unique numeric identifier for each key pressed that is the same regardless of modifiers pressed.
  • A unique, user readable description (a short string) of the primary unmodified symbol (printable) or function (non printable) belonging to that key regardless of modifiers pressed.