Current Articles | RSS Feed
Web application developers should strive to provide as good an interface for their web apps as other programmers do with desktop programs. One simple enhancement is to provide keyboard shortcuts to main functions, as sites such as Gmail, Google Docs, and Twitter do. Experienced users welcome keyboard shortcuts because they offer the ability to work faster, letting users perform operations without having to remove their hands from the keyboard.
Since the Web's early days, HTML has offered access keys, which let you quickly navigate to a specific field by means of an ALT+key combo. More recently, and more sophisticated, are hot keys, which are specific to a single application and let users invoke any function or perform any given procedure. You'll probably want to use both types of shortcuts in your web pages, so let's quickly look at access keys, then move on to implementing hot keys, first by hand, then in a much easier way by using the Keyboard Shortcuts JavaScript library, either directly or through jQuery.
Access keys provide quick shortcuts to navigate to a given web form field. If you set the accesskey attribute of a form field to, say, "A," users can quickly go to the corresponding field by pressing a key combination. The exact combination depends on the browser: CTRL+A or CTRL+OPT+A on a Mac, or ALT+A on Windows or Linux, except on Firefox, which requires ALT+SHIFT+letter in order to reserve ALT+letter combinations for its own usage, and Opera, which expects SHIFT+ESC in order to list the set of available access keys. Standards, anybody? The code below defines a simple web form with three fields, each with an access key.
accesskey
<html><head> <title>Keyboard Access Keys Demo</title></head><body> <h1>Keyboard Access Keys Demo</h1> <label for="nameField"><u>N</u>ame:</label> <input id="nameField" type="text" accesskey="n" title="Press access key N to enter the user's name"/> <br> <label for="addressField"><u>A</u>ddress:</label> <input id="addressField" type="text" accesskey="A" title="Press access key A to enter the user's address"/> <br> <label for="phoneField">P<h></u>one:</label> <input id="phoneField" type="text" accesskey="H" title="Press access key H to enter the user's phone number"/> <br></body></html>
Browsers do not provide any visual feedback as to available access keys, so it's up to you as the form designer to provide some cues to users. I opted for the common solution of underlining a letter in the label, because that convention is often used on desktop programs. You could use the title attribute, but a user would have to use the mouse and hover over the field in order to learn about the shortcut.
title
Despite access keys being a standard, you can still face problems with specific browsers that reserve certain key combinations for their own usage. For example, in Firefox, you cannot use P or S as access keys (because ALT+SHIFT+P and ALT+SHIFT+S are reserved by Mozilla, in addition to ALT+letter combos) unless you are willing to change the browser's configuration by navigating to about:config and setting ui.key.contentAccess to 4 and ui.key.chromeAccess to 5. No web developers should expect their application to depend on users making this sort of change. You might consider browser detection in order to use alternative combinations, but this approach still requires some experimentation in order to verify that everything works as planned. So, generally speaking, you have to do extensive testing to ensure that your access keys actually work as planned.
about:config
Now that we have dealt with access keys and HTML, let's move on to some programming, as hot keys do require some JavaScript work and are a tad trickier to get right. If you want to define your own hotkeys, the standard solution would have you define a document.onkeydown function (or document.onkeypress, but be aware that there are slight differences in the actual keycodes returned by each), detect what key and which modifier keys (Shift, Alt, Control, etc.) were pressed, and, depending on all that, take an appropriate course of action. For example:
document.onkeydown
document.onkeypress
<html><head> <title>Keyboard Hot Keys Demo #1</title> <script type="text/javascript"> document.onkeydown = function(e) { e = e || window.event; // because of Internet Explorer quirks... k = e.which || e.charCode || e.keyCode; // because of browser differences... if (k == 49 && !e.altKey && !e.ctrlKey && !e.shiftKey) { document.getElementById("check1").checked = true; } else if (k == 65 && e.altKey && !e.ctrlKey && !e.shiftKey) { document.getElementById("check2").checked = true; } else if (k == 66 && e.altKey && e.ctrlKey && !e.shiftKey) { document.getElementById("check3").checked = true; } else if (k == 90 && e.altKey && e.ctrlKey && e.shiftKey) { document.getElementById("check4").checked = true; } else { return true; // it's not a key we recognize, move on... } return false; // we processed the event, stop now. } </script></head><body> <h1>Keyboard Hot Keys Demo #1, with pure JavaScript</h1> <input type="checkbox" id="check1">Key "1" was pressed<br> <input type="checkbox" id="check2">Key combo "ALT+A" was pressed<br> <input type="checkbox" id="check3">Key combo "ALT+CTRL+B" was pressed<br> <input type="checkbox" id="check4">Key combo "ALT+CTRL+SHIFT+Z" was pressed<br> <br> A nice box to type in: <input type="text"></body></html>
The screen defined by the code above, when loaded, looks like this:
You can type in the text box, or use any of several keys that tick designated checkboxes. Of course, you have to consider some browser quirks in order to determine the keycode that corresponds to whatever the user pressed. Also, you'll have to remember the codes for all keys, particularly in the case of special and function keys. Don't forget to cancel the keyboard event if you recognized the key combo, or else the hot key will "bubble up" and also be interpreted by the browser, which you don't want to happen!
Note the first couple of lines in the onkeydown function, which take into account browser quirks and differences, and the return lines that allow or block the default key processing. While this sort of coding works, it's not very clear, and cannot easily conditionally enable or disable specific actions; for example, a "Save" function shouldn't be enabled unless something has been entered, and valid keypresses (such as "1" in the example) shouldn't be processed while entering text. Also, being able to dynamically add or remove shortcuts would be a plus.
onkeydown
return
While you could enhance the code to allow for these requirements, you can do better by using the Keyboard Shortcuts function, as we shall see.
For a better way to work with hotkeys, we need simple methods to add and remove function processing code. Specifically for single-key hotkeys, we must be able to enable and disable hotkey recognition and processing in input and textarea fields, so users can type normally. We also want to be able to tie events to specific fields, instead of associating them with the complete document.
The Keyboard Shortcuts JavaScript library provides all these features. Download it and let's rework our example to use it:
<html><head> <title>Keyboard Hot Keys Demo #2</title> <script src="shortcut.js" type="text/javascript"></script> <script type="text/javascript"> function initKeys() { shortcut.add("1", function() { document.getElementById("check1").checked = true; }, {"disable_in_input":true} ); shortcut.add("Alt+A", function() { document.getElementById("check2").checked = true; }, {"target":document.getElementById("myText")} ); shortcut.add("Alt+Ctrl+B", function() { document.getElementById("check3").checked = true; }); shortcut.add("Alt+Ctrl+Shift+Z", function() { document.getElementById("check4").checked = true; }); } window.onload = initKeys; </script></head><body> <h1>Keyboard Hot Keys Demo #2, with "Keyboard Shortcuts" library</h1> <input type="checkbox" id="check1">Key "1" was pressed<br> <input type="checkbox" id="check2">Key combo "ALT+A" was pressed<br> <input type="checkbox" id="check3">Key combo "ALT+CTRL+B" was pressed<br> <input type="checkbox" id="check4">Key combo "ALT+CTRL+SHIFT+Z" was pressed<br> <br> A nice box to type in: <input type="text" id="myText"><br> Another nice box to type in: <input type="text" id="myText2"><br> <button type="button" onclick="shortcut.remove('ALT+A');">Disable the ALT+A hotkey</button></body></html>
And here's a screenshot showing that some hotkeys were pressed:
To add a hotkey, we call the shortcut.add() function. (shortcut is a JavaScript variable created by the shortcut.js script.) This function has three parameters:
shortcut.add()
shortcut
shortcut.js
By using the third parameter, you can refine how and when hotkeys are recognized:
type
keydown
keyup>
keypress
disable_in_input
false
target
document
propagate
You can also remove a hotkey shortcut with a statement like shortcut.remove("ALT+A");, but be careful; there is a bug in the current version of the library, and if you assigned several methods to the same hotkey with different target values, only the latest shortcut will be removed, and the rest will still be active. If you load the page above and click on the button at the bottom, the ALT+A function will be disabled.
shortcut.remove("ALT+A");
If you use jQuery for web development, of course you could still use the Keyboard Shortcuts library, and work with $(...) instead of document.getElementById(...), but you can go one better by using the Hotkeys plugin. This plugin is based upon (but independent from) the Keyboard Shortcuts library, and works in a jQuery-ish way by using bind and unbind methods to set and reset hot keys. Download the plugin and you'll be able to write hotkey processing code as below.
$(...)
document.getElementById(...)
bind
unbind
<html><head> <title>Keyboard Hot Keys Demo #3</title> <script src="jquery.min.js" type="text/javascript"></script> <script src="jquery.hotkeys.js" type="text/javascript"></script> <script type="text/javascript"> function onAltA() { document.getElementById("check2").checked = true; } function initKeys() { $(document).bind("keydown", "1", function() { document.getElementById("check1").checked = true; }); $("#myText").bind("keydown", "Alt+A", onAltA); $(document).bind("keydown", "Alt+Ctrl+B", function() { document.getElementById("check3").checked = true; }); $(document).bind("keydown", "Alt+Ctrl+Shift+Z", function() { document.getElementById("check4").checked = true; }); } window.onload = initKeys; </script></head><body> <h1>Keyboard Hot Keys Demo #3, with jQuery plugin</h1> <input type="checkbox" id="check1">Key "1" was pressed<br> <input type="checkbox" id="check2">Key combo "ALT+A" was pressed<br> <input type="checkbox" id="check3">Key combo "ALT+CTRL+B" was pressed<br> <input type="checkbox" id="check4">Key combo "ALT+CTRL+SHIFT+Z" was pressed<br> <br> A nice box to type in: <input type="text" id="myText"><br> Another nice box to type in: <input type="text" id="myText2"><br> <button type="button" onclick="$('#myText').unbind('keydown', onAltA);">Disable the ALT+A hotkey</button></body></html>
The web page that this code creates looks exactly like the example with the Keyboard Shortcuts library, so we'll skip a screenshot.
The bind() method here associates a function with a keyboard event. By default, events are not recognized in text areas; in order to get ALT+A to work in the first text box, you must bind it specifically. If you don't wish to propagate an event, use the preventBubble parameter in the jQuery bind call. There's an error in the documentation about how to unbind an event; the correct way is $().unbind(theKeyCombination, theFunction) as shown in the web page above. (Also note that we had to use a named function, instead of an anonymous one, in order to be able to unbind the event code.)
bind()
preventBubble
$().unbind(theKeyCombination, theFunction)
Despite browser differences and restrictions, the use of access keys and hot keys enhances the usability of your web applications, and makes advanced users happier without bothering common users. Use them widely in your own code; it isn't that hard with the Keyboard Shortcuts library and code like we've seen here.
Allowed tags: <a> link, <b> bold, <i> italics