Keystrokes for jQuery December 30, 2009 15 Comments
Background
First off, I hope everyone had fun over the holidays – I certainly did! With the release of jQuery 1.4 jQuery 1.4 on the horizon for early in the new year, I decided I wanted to try out some of its new functionality. I’ve been reading blogs of some of the jQuery core developers and I found a post by Brandon Aaron to be very interesting. He talks about adding custom events to jQuery using its special event API. So I started making my custom event plugin and then realized that you could not bind the event to the same element twice. Meaning, you can’t do this:
$(document).bind('myevent', { data: ['some data'] }, function(event){ }); $(document).bind('myevent', { data: ['more data'] }, function(event){ });
So I tried using namespaces and it still would only fire the first event bind, not the second. Wow, what a drag. Then I found that Brandon wrote a new article about two new methods that were added to the custom event hook: add and remove . They both get fired on an event “bind” and “unbind” – perfect! Uh oh, these two methods are not available in the latest stable release of jQuery (1.3.2). They are only available in the release of jQuery 1.4! So yes, unfortunately, you have to upgrade to jQuery 1.4.2 (or greater) to use this plugin.
What is Keystrokes? (Hot keys)
Keystrokes is a jQuery plugin that can capture a sequence of keys that are pressed. It would come in pretty handy if you were doing a web application and wanted to allow the users to use hot keys. It can even detect combo keys like ‘shift+ctrl’. It would operate exactly as you type it. In this case, the user would hold down shift, hit ctrl and the event you specified would fire.
This plugin has been tested in: Firefox 3.5, Safari 4, Opera 10 and IE 7+. It might work in IE 6 but I’m not promising anything.
Setting it up
Make sure these are in the head of your document
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load('jquery','1.4.2');</script>
<script type="text/javascript" src="js/jquery.keystrokes.min.js"></script>Adding a basic event
$(document).bind('keystrokes', { // The key pattern you set your element to listen for keys: ['i', 'p'] }, function(event){ // Throw a notification to the user what keys they successfully typed alert('You typed : <em>' + event.keystrokes.stack_item.keys.join(', ') + '</em>'); });
If this is done correctly, when the user hits i then p, you will get an alert notification. See the demo page for a full the full effect.
Adding a basic event that unbinds itself upon successful key strokes
$(document).bind('keystrokes.SingleItem', { // The key pattern you set your element to listen for keys: ['m', 'arrow down+r'] }, function(event){ // Unbind this event after it's been successfully typed $(this).unbind(event.keystrokes.stack_item.name); alert('You typed : <em>' + event.keystrokes.stack_item.keys.join(', ') + '</em>. You cannot type it again because it has been unbound!'); });
Adding a more complex notification that contains multiple key sets
$(document).bind('keystrokes.OtherNameSpace', [ { // Define typed keys in sequence keys: ['h', 'shift+p+o'], // If false, this will not execute the main callback, only the "success" callback on this stack item proceedToMainCallback: false, // The callback bound to this specific stack item success: function(event){ alert('You typed : <em>' + event.keystrokes.stack_item.keys.join(', ') + '</em>. This has "proceedToMainCallback: false" so it will not call the main callback for this bound event.</em>'); } }, { // Define typed keys in sequence keys: ['j', 'k'], // The callback bound to this specific stack item success: function(event){ alert('You typed : <em>' + event.keystrokes.stack_item.keys.join(', ') + '</em>'); } }, { // Define typed keys in sequence keys: ['arrow up+comma+k', 1, 2, 3], // The callback bound to this specific stack item success: function(event){ alert('You typed : <em>' + event.keystrokes.stack_item.keys.join(', ') + '</em>'); } } // The main callback that gets called with every successful key sequence // This can be skipped by setting 'proceedToMainCallback: false' as an option in a stack item ], function(event){ // Maybe get the whole stack.. if you want? var stack = event.keystrokes.stack; // Get the specific stack item that was successfully typed var data_keys = event.keystrokes.stack_item.keys.join(', '); // Shout it out! alert('<span>This is the main callback for selected successful keystrokes. To skip this call, just set "proceedToMainCallback: false" in your stack item: </span> ' + data_keys); } );
Key set options
Below is a list of all possible options that go with a key set.
| Key | Default Value | Type | Description |
|---|---|---|---|
| keys | [] (required) | Array | The specified key sequence you wish to listen for. Example: ['shift+ctrl', 'o', 1, 5, 'space'] |
| customValidation | null | Function | You can run your own validation and decide whether the user completed the key sequence the way you wanted them to. See the demo for an example. |
| success | null | Function | If you are using an array of key sets as seen in the advanced example, you can specify a callback unique to that key set. |
| proceedToMainCallback | true | Boolean | If you’ve specified a ‘success’ callback (see above) and you don’t want to have the main callback executed, set this to false. This is more commonly used in the advanced example. |
String list
Below is a table of all possible key strings you can enter in your keys array.
| Key Code | String |
|---|---|
| 8 | backspace |
| 9 | tab |
| 13 | enter |
| 16 | shift |
| 17 | ctrl |
| 18 | alt |
| 19 | pause/break |
| 20 | caps lock |
| 27 | escape |
| 33 | page up |
| 32 | space |
| 34 | page down |
| 35 | end |
| 36 | home |
| 37 | arrow left |
| 38 | arrow up |
| 39 | arrow right |
| 40 | arrow down |
| 44 | print screen |
| 45 | insert |
| 46 | delete |
| 48 | 0 |
| 49 | 1 |
| 50 | 2 |
| 51 | 3 |
| 52 | 4 |
| 53 | 5 |
| 54 | 6 |
| 55 | 7 |
| 56 | 8 |
| 57 | 9 |
| 59 | semi-colon |
| 61 | add |
| 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 |
| 91 | left window key |
| 92 | right window key |
| 93 | select key |
| 96 | numpad 0 |
| 97 | numpad 1 |
| 98 | numpad 2 |
| 99 | numpad 3 |
| 100 | numpad 4 |
| 101 | numpad 5 |
| 102 | numpad 6 |
| 103 | numpad 7 |
| 104 | numpad 8 |
| 105 | numpad 9 |
| 106 | multiply |
| 107 | add |
| 109 | subtract |
| 110 | decimal point |
| 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 |
| 144 | num lock |
| 145 | scroll lock |
| 182 | my computer (multimedia keyboard) |
| 183 | my calculator (multimedia keyboard) |
| 186 | semi-colon |
| 187 | equal sign |
| 188 | comma |
| 189 | dash |
| 190 | period |
| 191 | forward slash |
| 192 | tilde |
| 219 | open bracket |
| 220 | back slash |
| 221 | close bracket |
| 222 | single quote |
| 224 | command |
You can also add/modify to the string list by adding this line above your event calls:
// Simply supply the key code and the string you wish to use. $.extend($.event.special.keystrokes.codes, { 13 : 'my enter key' });
If you have something like Firebug and you want to do some debugging, you can add this line above your event calls:
$.event.special.keystrokes.debug = true;
Now, if you open up your console, you will be able to see what keys the script thinks you’re typing. If you hit a key that’s not registered in our string list, it will output that key code to the console and notify you. This makes it easy for you to do your own customizations.
By default, Keystrokes ignores when you’re typing keys in any input/textarea field. If you want to track keys on an input field you have to bind it directly to that input element.

Jordan, keep impressing us!
However got some problems in JQuery 1.4.2
+ some bug found - if you focused in any input, plugin stops working ((
before you bind any keystroke events.
1 more question: JQuery 1.4.2 fires error (missing namespace) - is that plugin or Jquery 1.4.2 bug?
this jquery keystrokes is really usefull
thanks Jordan :)
regards
btu what happen if you type
keys: [1, 5],
keys: [5],
keys: [1, 5, 5],
how the script knows to wait until the sequence is done?
Or even better, captureInputFields could be an option for bind, like this:
$(document).bind('keystrokes', { keys: ['ctrl+s'], captureInputFields: true }, ....)
Now I have to do complcated workarounds for global hotkeys, like
$(document).add('input[type=text]').bind('keystrokes', { keys: ['ctrl+s'] }, ....)
(I never know when i missed some element types.)
It only handles sequences ?