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.

Revisions

  1. RoboTeddy revised this gist Jul 5, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions keyboard.coffee
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    Bacon = require 'Bacon'
    _ = require 'underscore'
    $ = require 'jquery'
    # Reference: http://unixpapa.com/js/key.html

    # IE = IE keycodes (webkit, IE)
  2. RoboTeddy created this gist Jul 5, 2014.
    103 changes: 103 additions & 0 deletions keyboard.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,103 @@
    Bacon = require 'Bacon'
    _ = require 'underscore'
    # 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