Skip to content

Instantly share code, notes, and snippets.

@RoboTeddy
Last active August 29, 2015 14:03
Show Gist options
  • Save RoboTeddy/a7eeda3ea59ca04e7a15 to your computer and use it in GitHub Desktop.
Save RoboTeddy/a7eeda3ea59ca04e7a15 to your computer and use it in GitHub Desktop.
Bacon.js keyboard
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