Skip to content

Instantly share code, notes, and snippets.

@andyearnshaw
Created April 26, 2014 23:32
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyearnshaw/11333894 to your computer and use it in GitHub Desktop.
Save andyearnshaw/11333894 to your computer and use it in GitHub Desktop.
Simple KeyboardEvent.key polyfill

Recently, I've been working on a Smart TV application targeted at both LG and Samsung models. I had problems keeping the main code platform independent because the key codes on events generated by the remote controls differed between the vendors. While LG's remote control keys generated fairly sane codes, Samsung's didn't, with the codes for numeric keys seeming completely random (for example, the numeric key 1 has the key code 101, but 5 has 9).

I eventually decided to polyfill KeyboardEvent.key, and allow passing a map to the polyfill so that the platform-dependent code could define their own keysets.

The property exposes itself on both the KeyEvent (non-standard) and KeyboardEvent (standard) objects and is ideal for use in specific, targeted environments.

/**
* Provides a default map for event.key in keyboard events
*/
(function (global) {
"use strict";
var defMap = {
13: 'Enter',
27: 'Escape',
33: 'PageUp',
34: 'PageDown',
37: 'ArrowLeft',
38: 'ArrowUp',
39: 'ArrowRight',
40: 'ArrowDown',
},
// Other printable characters
fcc = [ 32 ],
keyManager = global.keyManager = Object.create(Object, {
map: {
get: function () { return map; },
set: function (o) { map = o; }
}
}),
prop = { get: function () {
var code = this.which;
return map[code] || 'Unidentified';
}},
map = Object.create(defMap);
// Numpad
for (var i = 0; i <= 9; i++)
defMap[i + 96] = String(i);
// F keys
for (var i = 1; i < 25; i++)
defMap[i + 111] = 'F' + i;
// Printable characters
for (var i = 48; i < 91; i++)
defMap[i] = String.fromCharCode(i);
if (global.KeyboardEvent)
Object.defineProperty(global.KeyboardEvent.prototype, 'key', prop);
if (global.KeyEvent)
Object.defineProperty(global.KeyEvent.prototype, 'key', prop);
})(this);
// Sample key-map generator for Samsung Smart TV
(function () {
var keyMap = Object.create(keyManager.map),
lgKeys = {
'UP' : 'ArrowUp',
'DOWN' : 'ArrowDown',
'LEFT' : 'ArrowLeft',
'RIGHT' : 'ArrowRight',
'BACK' : 'BrowserBack',
'PAGE_DOWN' : 'ChannelDown',
'PAGE_UP' : 'ChannelUp',
'RED' : 'ColorF0Red',
'GREEN' : 'ColorF1Green',
'YELLOW' : 'ColorF2Yellow',
'BLUE' : 'ColorF3Blue',
'TOOLS' : 'ContextMenu',
'ENTER' : 'Enter',
'GUIDE' : 'Guide',
'INFO' : 'Info',
'PLAY' : 'MediaPlay',
'PAUSE' : 'MediaPause',
'STOP' : 'MediaStop',
'REWIND' : 'MediaRewind',
'FAST_FWD' : 'MediaForward',
};
Object.keys(lgKeys).forEach(function (p) {
keyMap[eventObj['VK_'+p]] = lgKeys[p];
});
keyManager.map = keyMap;
})();
// Sample key-map generator for Samsung Smart TV
(function () {
var keys = new window.Common.API.TVKeyValue(),
vals = {
'UP' : 'ArrowUp',
'DOWN' : 'ArrowDown',
'LEFT' : 'ArrowLeft',
'RIGHT' : 'ArrowRight',
'RETURN' : 'BrowserBack',
'CH_DOWN' : 'ChannelDown',
'CH_UP' : 'ChannelUp',
'RED' : 'ColorF0Red',
'GREEN' : 'ColorF1Green',
'YELLOW' : 'ColorF2Yellow',
'BLUE' : 'ColorF3Blue',
'TOOLS' : 'ContextMenu',
'ENTER' : 'Enter',
'GUIDE' : 'Guide',
'INFO' : 'Info',
'PLAY' : 'MediaPlay',
'PAUSE' : 'MediaPause',
'STOP' : 'MediaStop',
'RW' : 'MediaRewind',
'FF' : 'MediaForward',
'VOL_DOWN' : 'VolumeDown',
'MUTE' : 'VolumeMute',
'VOL_UP' : 'VolumeUp'
},
map = Object.create(keyManager.map);
for (var i = 0; i <= 9; i++)
map[keys['KEY_'+i]] = String(i);
Object.keys(vals).forEach(function (p) {
map[keys['KEY_'+p]] = vals[p];
});
keyManager.map = map;
})();
@jtenner
Copy link

jtenner commented Mar 12, 2015

This is absolutely amazing, and I plan on using this technique later.

I'll share it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment