Skip to content

Parsing keydown events

This post is obsolete; the $.keymap has changed significantly. Documentation is now at http://bililite.com/blog/2015/01/12/rethinking-keymap/.

I've been playing around with creating an online editor, and one thing it needs is keyboard shortcuts. Control keys and the like don't register keypress events, so I have to use keydown to get the event.which (and I have to use jQuery to normalize that across browsers), and then I have a random keyboard code and a bunch of modifier key flags to work with. The W3C once tried to rationalize all this, but no one picked up on it. So I wrote a jQuery plugin to turn the event into a friendlier string (using a notation based on Microsoft's sendkeys). Thus:

  • Pressing the 'a' key gives $.keymap(event) == 'a'
  • Pressing the 'a' key with shift held gives $.keymap(event) == 'A'
  • Pressing the 'a' key with control held gives $.keymap(event) == '^A'
  • Pressing the 'a' key with alt held gives $.keymap(event) == '%A'
  • Pressing the 'a' key with control and alt held gives $.keymap(event) == '^%A'
  • Pressing the 'Esc' key gives $.keymap(event) == '{esc}'
  • Pressing the 'Esc' key with shift held gives $.keymap(event) == '+{esc}'
  • Pressing the '*' key on the numeric keypad gives $.keymap(event) == '{multiply}'
  • Pressing the '1' key on the numeric keypad with control held gives $.keymap(event) == '^{1}'

Download the code.

See the demo.

David Mauro has a cool library that allows you to capture keystrokes and assign callbacks, but it not's exactly the same thing. Jonathan Tang has a older project that is similar. John Resig's jquery.hotkeys largely does the reverse, turning strings into keycodes.

Modifier Keys

Shift is indicated with +, except for normal printing characters which use the correct character; thus A rather than +a and # rather than +3. Control characters are indicated with ^, with alphabetic characters capitalized; thus ^A, not ^a (actually pressing shift-control-A is indicated with +^A. Similarly, alt characters are indicated with %.

Special Keys

The keys %, ^, + and { are represented by {%}, {^}, {+} and {{}, since they are otherwise special. Other special keys are:

  • {backspace}
  • {delete}
  • {enter}
  • {esc}
  • {insert}
  • {tab}
  • {space}
  • {pgdn}
  • {pgup}
  • {end}
  • {home}
  • {leftarrow} (rather than {left}, for consistency with my sendkeys plugin)
  • {rightarrow}
  • {uparrow}
  • {downarrow}
  • {0} for the numeric keypad 0, and similarly for the other numbers
  • {.} for the numeric keypad decimal point
  • {add} for the numeric keypad +
  • {subtract} for the numeric keypad -
  • {multiply} for the numeric keypad *
  • {divide} for the numeric keypad /

$.keymap.normalize

To help with keeping macro definitions consistent, $.keymap.normalize is a utility function that does a simple job of normalizing the keymap strings. Thus, $.keymap.normalize('%^a') returns '^%A'. It also accounts for VIM and jquery.hotkeys notation; thus both $.keymap.normalize('<C-A>') and $.keymap.normalize('ctrl+a') return '^A'. Please look at the source for $.keymap.normalize for all the translations.

Localizing

There are four objects for translating keycodes to character representations: $.keymap.normal for the unmodified keys and $.keymap.shift, $.keymap.ctrl and $.keymap.alt for the modified keys (only set if the modified keys should use a representation different from the default, which is the normal key plus +, ^ or %). For the standard US keyboard, they are:

$.keymap.normal = {
	8: "{backspace}", 9: "{tab}", 13: "{enter}", 27: "{esc}", 32: "{space}", 33: "{pgup}",
	34: "{pgdn}", 35: "{end}", 36: "{home}", 37: "{leftarrow}", 38: "{uparrow}", 39: "{rightarrow}", 40: "{downarrow}",
	45: "{insert}", 46: "{delete}", 48: "0", 49: "1", 50: "2", 51: "3", 52: "4", 53: "5", 54: "6", 55: "7", 56: "8", 57: "9",
	65: "a", 66: "b", 67: "c", 68: "d", 69: "e", 70: "f", 71: "g", 72: "h", 73: "i", 74: "j", 75: "k",
	76: "l", 77: "m", 78: "n", 79: "o", 80: "p", 81: "q", 82: "r", 83: "s", 84: "t", 85: "u", 86: "v",
	87: "w", 88: "x", 89: "y", 90: "z", 96: "{0}", 97: "{1}", 98: "{2}", 99: "{3}", 100: "{4}", 101: "{5}",
	102: "{6}", 103: "{7}", 104: "{8}", 105: "{9}", 106: "{multiply}", 107: "{add}", 108: "{unused}",
	109: "{subtract}", 110: "{.}", 111: "{divide}", 112: "{f1}", 113: "{f2}", 114: "{f3}", 115: "{f4}",
	116: "{f5}", 117: "{f6}", 118: "{f7}", 119: "{f8}", 120: "{f9}", 121: "{f10}", 122: "{f11}",
	123: "{f12}", 186: ";", 187: "=", 188: ", ", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[",
	220: "\\", 221: "]", 222: "'"
}
$.keymap.shift = {
	48: ")", 49: "!", 50: "@", 51: "#", 52: "$", 53: "{%}", 54: "{^}",
	55: "&", 56: "*", 57: "(", 186: ";", 187: "{+}", 188: "<", 189: "_",
	190: ">", 191: "?", 192: "~", 219: "{{}", 220: "|", 221: "}",
	222: "\""
}
$.keymap.ctrl = {};	
$.keymap.alt = {};	

Replace them as needed; for instance, for a British keyboard set $.keymap.shift[51] = '£' etc. Note that capitalizing shifted letters is part of the normalizing code, not subject to these arrays.

Hotkeys

I added a plugin to allow defining "hotkeys"; event handlers for specific sequences of keystrokes. For example:

$.keymap.hotkeys('keydown');
$('body').on('keydown', '+%A', function() { alert('You pressed shift-control-A') });

The details are in another post.

Hope this turns out to be useful to someone!

Post a Comment

Your email is never published nor shared. Required fields are marked *