Last active
August 29, 2015 14:03
-
-
Save RoboTeddy/a7eeda3ea59ca04e7a15 to your computer and use it in GitHub Desktop.
Bacon.js keyboard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Bacon = require 'Bacon' | |
_ = require 'underscore' | |
$ = require 'jquery' | |
# Reference: http://unixpapa.com/js/key.html | |
# IE = IE keycodes (webkit, IE) | |
# MZ = Mozilla keycodes (gecko) | |
# Opera = Opera keycodes (opera) | |
# US locale specific. About as well as can be done without browser detection. | |
keyCodeToKeyName = _.extend({}, [ | |
# General Keys (IE, MZ, Opera) | |
_.object([x, String.fromCharCode(x).toLowerCase()] for x in [65..90]), | |
{32: 'space', 13: 'enter', 9: 'tab', 27: 'esc', 8: 'backspace'}, | |
# Modifier Keys (IE, MZ, Opera) | |
{16: 'shift', 17: 'control', 18: 'alt', 20: 'capslock', 144: 'numlock'}, | |
# Number Keys (IE, MZ, Opera) | |
{ | |
49: '1', 50: '2', 51: '3', 52: '4', 53: '5', 54: '6', 55: '7', 56: '8', | |
57: '9', 48: '0' | |
}, | |
# Symbol Keys (No Opera due to collisions) | |
{ | |
# IE (these appear not to collide with MZ or Opera) | |
186: ';', 187: '=', 189: '-', | |
# MZ (these appear not to collide with IE or Opera) | |
59: ';', 61: '=', 109: '-', | |
# IE, MZ | |
188: ',', 190: '.', 191: '/', 192: '`', 219: '[', 220: '\\', 221: ']', | |
222: '\'' | |
}, | |
# Arrow Keys (IE, MZ, Opera) | |
{37: 'left', 38: 'up', 39: 'right', 40: 'down'}, | |
# Special Keys (IE, MZ, Opera) | |
{ | |
45: 'insert', 46: 'delete', 36: 'home', 35: 'end', 33: 'pageup', | |
34: 'pagedown' | |
}, | |
# Function Keys (IE, MZ, Opera) | |
_.object([x + 111, "F#{x}"] for x in [1..19]), | |
# Keypad Keys (IE, MZ) (No Opera due to collisions) (assumes numlock is off) | |
{ | |
110: '.', 96: 'num0', 97: 'num1', 98: 'num2', 99: 'num3', 100: 'num4', | |
101: 'num5', 102: 'num6', 103: 'num7', 104: 'num8', 105: 'num9', | |
107: 'num+', 109: 'num-', 106: 'num*', 111: 'num/' | |
}, | |
# Branded Keys (IE, MZ) (No Opera due to collisions) | |
# Combined windows 'start' and mac 'command' keys rather than having synonyms | |
{ | |
# IE, MZ | |
91: 'start_or_command', | |
92: 'start_or_command', # refers to windows right-side 'start' key | |
93: 'menu', # windows 'menu' key. collides with mac rightside 'command' key | |
# MZ | |
224: 'start_or_command' | |
} | |
]...) | |
fullScreenEventNames = [ | |
'webkitfullscreenchange', 'mozfullscreenchange', 'fullscreenchange' | |
] | |
isTextInputFocused = do -> | |
selector = "input[type=text], input[type=password], input:not([type]), | |
textarea" | |
$(document).asEventStream('focus', selector) | |
.awaiting($(document).asEventStream('blur', selector)) | |
.skipDuplicates() | |
keyboard = | |
downs: (keyNames, enabledDuringTextInput = false) -> | |
keyNames = if _.isArray(keyNames) then keyNames else [keyNames] | |
$(document).asEventStream('keydown') | |
.filter((event) -> keyCodeToKeyName[event.keyCode] in keyNames) | |
.filter(isTextInputFocused.not().or(enabledDuringTextInput)) | |
ups: (keyNames, enabledDuringTextInput = false) -> | |
keyNames = if _.isArray(keyNames) then keyNames else [keyNames] | |
$(document).asEventStream('keyup') | |
.filter((event) -> keyCodeToKeyName[event.keyCode] in keyNames) | |
.filter(isTextInputFocused.not().or(enabledDuringTextInput)) | |
isDown: (keyName, enabledDuringTextInput = false) -> | |
Bacon.mergeAll([ | |
keyboard.downs(keyName, enabledDuringTextInput).map(true) | |
keyboard.ups(keyName).map(false) | |
$(window).asEventStream('blur').map(false) | |
$(window).asEventStream(fullScreenEventNames.join ' ').map(false) | |
]).toProperty(false).skipDuplicates() | |
characters: (character) -> throw "Not implemented yet!" | |
module.exports = keyboard |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment