{"id":2826,"date":"2013-02-22T00:08:12","date_gmt":"2013-02-22T06:08:12","guid":{"rendered":"http:\/\/bililite.com\/blog\/?p=2826"},"modified":"2015-01-12T16:34:29","modified_gmt":"2015-01-12T22:34:29","slug":"parsing-keydown-events","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2013\/02\/22\/parsing-keydown-events\/","title":{"rendered":"Parsing <code>keydown<\/code> events"},"content":{"rendered":"<p><strong>This post is obsolete; the <code>$.keymap<\/code> has changed significantly. Documentation is now at <a href=\"\/blog\/2015\/01\/12\/rethinking-keymap\/\">http:\/\/bililite.com\/blog\/2015\/01\/12\/rethinking-keymap\/<\/a><\/strong>.<\/p>\r\n<p>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 <a href=\"http:\/\/api.jquery.com\/keypress\/\"><code>keypress<\/code><\/a> events, so I have to use <a href=\"http:\/\/api.jquery.com\/keydown\/\"><code>keydown<\/code><\/a> to get the <code>event.which<\/code> (and I have to use jQuery to normalize <em>that<\/em> across browsers), and then I have a random keyboard code and a bunch of modifier key flags to work with. The <a href=\"http:\/\/www.w3.org\/TR\/DOM-Level-3-Events\/#keys-keyvalues\">W3C once tried to rationalize<\/a> 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 <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.forms.sendkeys.aspx\">Microsoft's sendkeys<\/a>). Thus:<\/p>\r\n<ul>\r\n<li>Pressing the 'a' key gives <code>$.keymap(event) == 'a'<\/code><\/li>\r\n<li>Pressing the 'a' key with shift held gives <code>$.keymap(event) == 'A'<\/code><\/li>\r\n<li>Pressing the 'a' key with control held gives <code>$.keymap(event) == '^A'<\/code><\/li>\r\n<li>Pressing the 'a' key with alt held gives <code>$.keymap(event) == '%A'<\/code><\/li>\r\n<li>Pressing the 'a' key with control and alt held gives <code>$.keymap(event) == '^%A'<\/code><\/li>\r\n<li>Pressing the 'Esc' key gives <code>$.keymap(event) == '{esc}'<\/code><\/li>\r\n<li>Pressing the 'Esc' key with shift held gives <code>$.keymap(event) == '+{esc}'<\/code><\/li>\r\n<li>Pressing the '*' key on the numeric keypad gives <code>$.keymap(event) == '{multiply}'<\/code><\/li>\r\n<li>Pressing the '1' key on the numeric keypad with control held gives <code>$.keymap(event) == '^{1}'<\/code><\/li>\r\n<\/ul>\r\n<p><a href=\"\/inc\/jquery.keymap.js\">Download the code<\/a>.<\/p>\r\n<p><a href=\"\/blog\/blogfiles\/keymap.html\">See the demo<\/a>.<\/p>\r\n<!--more-->\r\n<p>David Mauro has a <a href=\"http:\/\/dmauro.github.com\/Keypress\/\">cool library<\/a> that allows you to capture keystrokes and assign callbacks, but it not's exactly the same thing. Jonathan Tang has a <a href=\"http:\/\/jonathan.tang.name\/code\/js_keycode\">older project<\/a> that is similar. John Resig's <a href=\"https:\/\/github.com\/jeresig\/jquery.hotkeys\/blob\/master\/jquery.hotkeys.js\">jquery.hotkeys<\/a> largely does the reverse, turning strings into keycodes.<\/p>\r\n<h3>Modifier Keys<\/h3>\r\n<p>Shift is indicated with <code><strong>+<\/strong><\/code>, except for normal printing characters which use the correct character; thus <code><strong>A<\/strong><\/code> rather than <code><strong>+a<\/strong><\/code> and <code><strong>#<\/strong><\/code> rather than <code><strong>+3<\/strong><\/code>. Control characters are indicated with <code><strong>^<\/strong><\/code>, with alphabetic characters capitalized; thus <code><strong>^A<\/strong><\/code>, not <code><strong>^a<\/strong><\/code> (actually pressing shift-control-A is indicated with <code><strong>+^A<\/strong><\/code>. Similarly, alt characters are indicated with <code><strong>%<\/strong><\/code>.<\/p>\r\n<h3>Special Keys<\/h3>\r\n<p>The keys <strong>%<\/strong>, <strong>^<\/strong>, <strong>+<\/strong> and <strong>{<\/strong> are represented by  <code><strong>{%}<\/strong><\/code>, <code><strong>{^}<\/strong><\/code>, <code><strong>{+}<\/strong><\/code> and <code><strong>{{}<\/strong><\/code>, since they are otherwise special. Other special keys are:<\/p>\r\n<ul>\r\n<li><code><strong>{backspace}<\/strong><\/code><\/li>\r\n<li><code><strong>{delete}<\/strong><\/code><\/li>\r\n<li><code><strong>{enter}<\/strong><\/code><\/li>\r\n<li><code><strong>{esc}<\/strong><\/code><\/li>\r\n<li><code><strong>{insert}<\/strong><\/code><\/li>\r\n<li><code><strong>{tab}<\/strong><\/code><\/li>\r\n<li><code><strong>{space}<\/strong><\/code><\/li>\r\n<li><code><strong>{pgdn}<\/strong><\/code><\/li>\r\n<li><code><strong>{pgup}<\/strong><\/code><\/li>\r\n<li><code><strong>{end}<\/strong><\/code><\/li>\r\n<li><code><strong>{home}<\/strong><\/code><\/li>\r\n<li><code><strong>{leftarrow}<\/strong><\/code> (rather than <code>{left}<\/code>, for consistency with my <a href=\"http:\/\/bililite.com\/blog\/2011\/01\/23\/improved-sendkeys\/\" title=\"Improved sendkeys\"><code>sendkeys<\/code><\/a> plugin)<\/li>\r\n<li><code><strong>{rightarrow}<\/strong><\/code><\/li>\r\n<li><code><strong>{uparrow}<\/strong><\/code><\/li>\r\n<li><code><strong>{downarrow}<\/strong><\/code><\/li>\r\n<li><code><strong>{0}<\/strong><\/code> for the numeric keypad <strong>0<\/strong>, and similarly for the other numbers<\/li>\r\n<li><code><strong>{.}<\/strong><\/code> for the numeric keypad decimal point<\/li>\r\n<li><code><strong>{add}<\/strong><\/code> for the numeric keypad <strong>+<\/strong><\/li>\r\n<li><code><strong>{subtract}<\/strong><\/code> for the numeric keypad <strong>-<\/strong><\/li>\r\n<li><code><strong>{multiply}<\/strong><\/code> for the numeric keypad <strong>*<\/strong><\/li>\r\n<li><code><strong>{divide}<\/strong><\/code> for the numeric keypad <strong>\/<\/strong><\/li>\r\n<\/ul>\r\n<h3><code>$.keymap.normalize<\/code><\/h3>\r\n<p>To help with keeping macro definitions consistent, <code>$.keymap.normalize<\/code> is a utility function that does a simple job of normalizing the keymap strings. Thus, <code class=\"language-javascript\" >$.keymap.normalize('%^a')<\/code> returns <code class=\"language-javascript\" >'^%A'<\/code>. It also accounts for <a href=\"http:\/\/polarhome.com\/vim\/manual\/v71\/intro.html#key-notation\">VIM<\/a> and <a href=\"https:\/\/github.com\/jeresig\/jquery.hotkeys\/blob\/master\/jquery.hotkeys.js\">jquery.hotkeys<\/a> notation; thus both <code class=\"language-javascript\" >$.keymap.normalize('&lt;C-A&gt;')<\/code> and <code class=\"language-javascript\" >$.keymap.normalize('ctrl+a')<\/code> return <code class=\"language-javascript\" >'^A'<\/code>. Please look at the source for <a href=\"\/inc\/jquery.keymap.js\"><code>$.keymap.normalize<\/code><\/a> for all the translations.<\/p>\r\n<h3>Localizing<\/h3>\r\n<p>There are four objects for translating keycodes to character representations: <code>$.keymap.normal<\/code> for the unmodified keys and <code>$.keymap.shift<\/code>, <code>$.keymap.ctrl<\/code> and <code>$.keymap.alt<\/code> for the modified keys (only set if the modified keys should use a representation different from the default, which is the normal key plus <code><strong>+<\/strong><\/code>, <code><strong>^<\/strong><\/code> or <code><strong>%<\/strong><\/code>). For the standard US keyboard, they are:<\/p>\r\n<pre><code class=\"language-javascript\" >$.keymap.normal = {\r\n\t8: \"{backspace}\", 9: \"{tab}\", 13: \"{enter}\", 27: \"{esc}\", 32: \"{space}\", 33: \"{pgup}\",\r\n\t34: \"{pgdn}\", 35: \"{end}\", 36: \"{home}\", 37: \"{leftarrow}\", 38: \"{uparrow}\", 39: \"{rightarrow}\", 40: \"{downarrow}\",\r\n\t45: \"{insert}\", 46: \"{delete}\", 48: \"0\", 49: \"1\", 50: \"2\", 51: \"3\", 52: \"4\", 53: \"5\", 54: \"6\", 55: \"7\", 56: \"8\", 57: \"9\",\r\n\t65: \"a\", 66: \"b\", 67: \"c\", 68: \"d\", 69: \"e\", 70: \"f\", 71: \"g\", 72: \"h\", 73: \"i\", 74: \"j\", 75: \"k\",\r\n\t76: \"l\", 77: \"m\", 78: \"n\", 79: \"o\", 80: \"p\", 81: \"q\", 82: \"r\", 83: \"s\", 84: \"t\", 85: \"u\", 86: \"v\",\r\n\t87: \"w\", 88: \"x\", 89: \"y\", 90: \"z\", 96: \"{0}\", 97: \"{1}\", 98: \"{2}\", 99: \"{3}\", 100: \"{4}\", 101: \"{5}\",\r\n\t102: \"{6}\", 103: \"{7}\", 104: \"{8}\", 105: \"{9}\", 106: \"{multiply}\", 107: \"{add}\", 108: \"{unused}\",\r\n\t109: \"{subtract}\", 110: \"{.}\", 111: \"{divide}\", 112: \"{f1}\", 113: \"{f2}\", 114: \"{f3}\", 115: \"{f4}\",\r\n\t116: \"{f5}\", 117: \"{f6}\", 118: \"{f7}\", 119: \"{f8}\", 120: \"{f9}\", 121: \"{f10}\", 122: \"{f11}\",\r\n\t123: \"{f12}\", 186: \";\", 187: \"=\", 188: \", \", 189: \"-\", 190: \".\", 191: \"\/\", 192: \"`\", 219: \"[\",\r\n\t220: \"\\\\\", 221: \"]\", 222: \"'\"\r\n}\r\n$.keymap.shift = {\r\n\t48: \")\", 49: \"!\", 50: \"@\", 51: \"#\", 52: \"$\", 53: \"{%}\", 54: \"{^}\",\r\n\t55: \"&amp;\", 56: \"*\", 57: \"(\", 186: \";\", 187: \"{+}\", 188: \"&lt;\", 189: \"_\",\r\n\t190: \"&gt;\", 191: \"?\", 192: \"~\", 219: \"{{}\", 220: \"|\", 221: \"}\",\r\n\t222: \"\\\"\"\r\n}\r\n$.keymap.ctrl = {};\t\r\n$.keymap.alt = {};\t\r\n<\/code><\/pre>\r\n<p>Replace them as needed; for instance, for a British keyboard set $.keymap.shift[51] = '\u00a3' etc. Note that capitalizing shifted letters is part of the normalizing code, not subject to these arrays.<\/p>\r\n<h3>Hotkeys<\/h3>\r\n<p>I added a plugin to allow defining \"hotkeys\"; event handlers for specific sequences of keystrokes. For example:<\/p>\r\n<pre><code class=\"language-javascript\" >$.keymap.hotkeys('keydown');\r\n$('body').on('keydown', '+%A', function() { alert('You pressed shift-control-A') });<\/code><\/pre>\r\n<p>The details are in <a href=\"http:\/\/bililite.com\/blog\/2013\/03\/20\/hotkeys-with-keymap\/\" title=\"hotkeys with keymap\">another post<\/a>.<\/p>\r\n\r\n<p>Hope this turns out to be useful to someone!<\/p>","protected":false},"excerpt":{"rendered":"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 [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2826"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=2826"}],"version-history":[{"count":26,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2826\/revisions"}],"predecessor-version":[{"id":3427,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/2826\/revisions\/3427"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=2826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=2826"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=2826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}