It’s time to bring the keyboard back! When we first started doing things on the web, there wasn’t much to do. There were documents with hyperlinks that we can click on but that’s about it; that was 15 years ago. Thanks to the growth of sophisticated server-side tools such as PHP and client-side tools such as jQuery, we are now able to do so much more. Today, many traditional desktop applications have migrated to the web. During this migration, we seem to have neglected the keyboard and I think we’re missing out on a a great time-saving route to interact with the application. So, that is what this tutorial is about, getting the keyboard more exposure in user interaction for web applications.

The Danger

Keyboard enabling is not suitable for every web application. It is more suitable for applications with high-touch users like a front desk receptionist, banking, data entry clerk, or a developer working on code. In these situations, removing the hands from the keyboard slows things down, so features that are usually accessed by mouse clicks make more sense to be keyboard shortcuts.

For most desktop application, partial keyboard enabling already helps a lot. For some, such as vim, complete mastery is a steep process but the long-term advantages are rewarding (see Matthew Weier O’Phinney’s weblog and Andrei Zmievski’s slides). If you’re interested in seeing one of the more extreme examples of keyboard enabling a web application, take a look at what Google is doing with Gmail.

Structuring the application


There are many ways to introduce keyboard listeners to web applications. The structure of the keyboard listening mechanism can differ based on situation, but the general concerns are rather similar. We structure the keyboarding mechanism as above with the following in mind:

  • index.html simply defines the structure of the page that the user will be viewing while style.css defines the corresponding style of such a view. Nothing nontraditional here.
  • The behaviour of the application is defined in stubbedkeyboard.js (the stubbed keyboard component), which also acts as some kind of Ajax stub to communicate with the server. Here’s where jQuery is used to achieve unobtrusive Javascript. Since it is managing the behaviour of the application, the behaviour of the application upon keyboard events is defined here.
  • server.php resembles a typical PHP script that responds to user requests, traditionally via some kind of form post or link. The stubbed keyboard component is able to add key listeners to existing server functions that is involved in menu clicks.

What we’ll need

jQuery is very useful in this case for a variety of reasons, among which includes behavioral separation, support in the form of its utility functions, and of course the legendary selector. On top of that, we use the jQuery Hotkeys plugin to manage our keyboard listening.

For every event, there is…

The keymap defines the relationship that exists between shortcut combination (a keyboard event) and its corresponding listener function. We map each shortcut combination to a single function which may encapsulate a series of local or server actions. Local actions does not involve AJAX calls to the server and does not affect the application model residing in the server. It probably involves things like changes to the contents in the local view and some setup of visual cues to the user if necessary. Server actions on the other hand involves an Ajax call to a server, requires response from the server and may change the state and model of the server. An example of a server action is the writing of some content to the database or filesystem upon the Save action being triggered.

The above code snippet shows a listener function that involves local and server actions. We can do just about any JavaScript and jQuery within the function. Here, we use jQuery’s Ajax load() command to call the remote getLatestBlog() method. The returned result is loaded onto the <div> identified via the jQuery(‘#console .content’) selector.

We return false at the end because jQuery expects listeners to return a false to stop the event from propagating further up the DOM tree and to prevent execution of any related default actions (see jQuery ,Event docs).

Aside: We use the explicit ‘jQuery’ keyword instead of the $ alias in case portions of the example code is used with other libraries without the appropriate jQuery.noConflict() utility being called.

setIndicator() as its name suggests makes some changes on the view to reflect the current end-state and the intermediate state. To manage possible asynchronously, we do:

We use the ajaxStart() function to know when an Ajax command had been triggered and the ajaxComplete() function to know when an Ajax command had completed. This will usually take a negligible amount of time, but just in case or in situations where response actually is lengthy, we provide an assuring visual indicator to the end-user in the form of the usual style change (see #console .loading in style.css of the source code).

Binding it together

Here’s the crucial bit, we iterate each of our defined keyMap item and bind each keyboard event to the corresponding listener. The bind method is actually overridden by the HotKeys plugin, adding the capability to listen to shortcut key combination (the event in the code snippet above). So, make sure you include the plugin, otherwise we’ll get plain old keydown listened to instead.

setupMenu() is probably something we would had done already even without this keyboard feature but let’s go through it quickly here to embed one important point in keyboarding: visual cues. Unless you’re doing some kind of web-based vim, users of your web app can benefit from all forms of cues that the shortcut exists and be reminded of how to access it until they get familiar with it. This is where web apps can learn a lesson or two from their desktop forefathers. Here, the display returned from the server actually already has the alphabet that corresponds to the key that will trigger that menu bold but the possibilities are expansive.

The setupMenu() function above loads a JSON encoded menumap, creates the view and assign mouse listeners to it just for the sake of completeness. We could had defined the menumap just within the stubbedkeyboard.js script itself, but let’s define it remotely for variety. In case there is a need to control say keymap and menumap on the server-side, the same technique applies.



This is an example application demonstrating the use of keyboard shortcuts within web-based software. The source code shows:

  1. The use of jQuery and the HotKeys plugin to listen to keyboard events.
  2. The use of AJAX to communicate with a PHP server application.

The source code in this application accompanies the tutorial titled Keyboard Interfaces in Web Applications that can be found on

  1. Alt+A to view this information (About).
  2. Alt+B to view a sample blog.

A deliberate delay is placed on Blog loading to highlight asynchronicity handling.

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

The server.php script consists mostly of simple methods that returns a chunk of made-up HTML that our client-side stubbedkeyboard.js javascript will then load onto the page displayed to the user. These methods, such as getAbout() and getLatestBlog() could be called by any client-side event via a $_POST request, not just keyboard events. The intention here is to show how keyboard listening can be added easily on the client-side without affecting the server side at all. These methods could well had been implemented even before keyboarding came into consideration. The getMenu() method returns a JSON encoded array of menu items that the client-side script uses to construct the menu displayed to the user (see previous section). So, the server accepts $_POST requests from clients, using $_POST['method'] to identify which method to call and subsequently, what kind of content to return. A mandatory filter is applied to $_POST to safeguard the script against malicious requests.

Ajax and keyboard enabling

When keyboard enabling a web based application, expect to use ajax extensively. Ajax allows us to minimize communication between client and server. This is even more important when keyboard shortcuts are involved. In applications that use keyboard shortcuts, they will be executed often and we expect response to be fast if not instantaneous. For example, a keyboard shortcut for the “Save Document” action needs to operate quickly and in the background. forcing a page reload each time the user saves their document will void the benefit of having keyboard shortcut.


The keyboard can still play an important role in navigating and interacting with web applications. JavaScript and the JavaScript library, jQuery are good client-side tools that make keyboard enabling web applications painless and cross-browser. If you intend to keyboard enable a new project, it is good to start thinking about it in the early stages of development. For existing applications, keyboard listeners can be added in with some modifications but it’s not as easy as designing them in from the beginning.

Download source code