# KeyboardEvent Polyfill

Polyfill for the additional `KeyboardEvent` properties defined in the UI Events draft specifications:

* [UI Events](https://w3c.github.io/uievents/)
* [UI Events](https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm) (queryKeyCaps addition)

Demo: https://inexorabletash.github.io/polyfill/demos/keyboard.html

## Details

For all browsers (except IE8-) this adds the following properties to
KeyboardEvent instances:

* `event.code` - (string) identifies the physical key - [code values](https://w3c.github.io/uievents-code/)
* `event.key` - (string) printed representation of the key, or control key identifier - [key values](https://w3c.github.io/uievents-key/)
* `event.location` - (number) location of key (0 = standard, 1 = left, 2 = right, 3 = numpad)

It also adds a static method:

* `KeyboardEvent.queryKeyCap(code)` - yields a human readable label for the key

As a helper for IE8-, it also a non-standard function to the global namespace:

* `identifyKey(keyboardEvent)`

The keyboardEvent argument should be a keyup/keydown DOM event. After
calling this, the event will be populated with `code`, `key` and `location`
properties.

## Example

```js
// Applications that need logical key should use `key`:
div.onkeydown = function(e) {
  identifyKey(e); // for IE8-
  switch (e.key) {
    case 'ArrowLeft': map.scroll(-10, 0); break;
    case 'ArrowRight': map.scroll(10, 0); break;
    case 'ArrowUp': map.scroll(0, -10); break;
    case 'ArrowDown': map.scroll(0, 10); break;
  }
};

// Applications that need physical keys should use `code`:
div.onkeydown = function(e) {
  identifyKey(e); // for IE8-
  switch (e.code) {
    case 'KeyW': character.moveForward(); break;
    case 'KeyA': character.moveLeft(); break;
    case 'KeyS': character.moveBackward(); break;
    case 'KeyD': character.moveRight(); break;
  }
};
```

## Background: Keys vs. Characters

In most operating systems, physical key presses generate events
(keydown, keyup) which are delivered to applications but
simultaneously processed by the operating system to perform actions
or generate characters. For example:

* Keys: [A] - generate character 'a'
* Keys: [Shift] - no character generated
* Keys: [Shift]+[A] - generate character 'A'
* Keys: [9] - generate character '9'
* Keys: [Shift]+[9] - generate character '('
* Keys: [;:] - generate character ';'
* Keys: [Shift]+[;:] - generate character ':'
* Keys: [Alt]+[`~], [E] - generate e with grave accent
* Keys: [Alt]+[0],[1],[2],[8] - generate Euro symbol
* Keys: [Enter] - generate 0x0D character (maybe)
* Keys: [Esc] - generate 0x1B character (maybe)

And of course, for non-Latin languages things get even more
complicated including IMEs where multiple keystrokes may generate a
list of candidate characters in an OS- or application-provided
display, from which the user selects before the character is
presented to the application.

## Legacy Key Events

Keyboard events were implemented before a specification was
written; as such, the behavior across browsers is very different.
The HTML4 spec defines the model as sending 'keydown' and 'keyup'
events corresponding to physical actions with the keys (with
possibly repeated 'keydown' events due to auto-repeat), and
'keypress' events corresponding to the generation of a character.
The legacy properties identifying the key are:

```webidl
  readonly attribute unsigned long keyCode;
  readonly attribute unsigned long charCode;
  readonly attribute unsigned long which;
```

* `keyCode` is a OS/browser dependent code identifying the
  specific key; sent on keydown and keyup events

* `charCode` is the Unicode code point of character generated by
  key press sequence, sent on keypress events which generate
  character input

* `which` is only used in some browsers - it's basically like
  `charCode` combined with `keyCode`

For compatibility most browsers conform on the `keyCode` values
produced by Microsoft Internet Explorer on Windows. But some browsers deviate -
notably Firefox - and there several are OS- and browser-specific quirks.

IE's keyCode values derive from Windows Virtual Key Codes.
[MSDN](http://msdn.microsoft.com/en-us/library/dd375731(VS.85).aspx)

Safari and Chrome adopted the IE model and codes for compatibility
[webkit-dev](https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html)

Firefox (Mozilla/Gecko) uses a very similar set of codes, which differ
for a handful of keys for punctuation symbols.
[MDN](https://developer.mozilla.org/en/DOM/Event/UIEvent/KeyEvent)

Older versions of Opera also uses different codes for some non-alphabetic keys.
[dev.opera.com](http://dev.opera.com/articles/view/keyboard-accessible-web-applications-3/)

Other references:

*  http://unixpapa.com/js/key.html
*  http://turboajax.com/dojo/key_compat.html
*  http://msdn.microsoft.com/en-us/scriptjunkie/ff928319
*  http://www.usb.org/developers/devclass_docs/Hut1_11.pdf

## Emerging Standards and Directions

The [UI Events](https://w3c.github.io/uievents/) draft specification defines new
properties for `KeyboardEvent`:

```idl
  readonly attribute DOMString code;
  readonly attribute DOMString key;
  readonly attribute unsigned long location;
```

  `code` is a standardized key identifier mapping to a physical key
  on the device, rather like a USB code.

  `key` is a string giving the printed representation of the key,
  or other identifier.

  `location` is a number identifying the physical location of the
  key - standard, left vs. right, numpad, etc.

Earlier drafts of the specs use `keyLocation` instead of
`location`, `keyIdentifier` instead of `code`, and `keyChar` instead
of `key`. Some browsers (Chrome, Safari) have partial
implementation of these earlier properties.

Another [UI Events](https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm)
draft specification proposes a new method on `KeyboardEvent`:

```idl
  static DOMString queryKeyCap (DOMString code, optional DOMString locale);
```

For cross-browser legacy mappings, see:

  http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/Note-KeyProps.html

## Known Issues

* Win/Chrome, Win/Safari, Win/IE, Win/Firefox - PrintScreen and Scroll only generate keyup events
* Win/Chrome - Apps doesn't send keyup
* Win/Opera - Tab moves focus even if cancelled; need explicit workaround to return focus
* Windows w/ Apple's Bootcamp: Backquote, BackSlash and Quote are mixed up in Chrome and IE
