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.

Download It! (v2.0)

Demo It!

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.