This tutorial is for Dojo 1.6 and may be out of date.

Up to date tutorials are available.

Keyboard Events with Dojo

In this tutorial, we will be exploring Dojo's event normalization and dojo.keys and how Dojo makes it easy to handle keyboard events.

Getting Started

Keyboard events fire when keys are pressed on the keyboard. This includes all keys, letters, numbers, symbols, punctuation, as well as the Escape, function, Enter, Tab, and keypad keys. Every keypress fires an event which may be captured and handled.

Browser support and implementations of keyboard event handling varies. Using Dojo to handle keyboard events allows you to write code that will run properly across virtually all browsers.

Keyboard Events

Listening for keyboard events in the browser allows you to implement a user interface that not only feels like a native application, it gives you a greater control over the UI.

onkeypress
Fires when any key is pressed and repeats until the key is released. onkeypress can be used for the majority of keyboard event handling.
onkeydown
Fires when any key is pressed and repeats until the key is released. onkeypress will fire after onkeydown in most cases.
onkeyup
Fires when the key is released.

Most key presses fire all three events, but there may be variations between browsers. The next demo allows you to see the keyboard events fired as you press keys. Take some time to experiment with different keys and combinations.

Dojo normalizes keyboard events, enabling you to use the dojo.keys constants to test for keyboard input of non-printable keys. Let's say we want to create a form that will allow element traversal using the up and down arrows or enter key. We can start with this simple example:

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.6.3/dojo/dojo.xd.js"> </script>
<body>
	<h1>Press any key</h1>
	keyCode value: <input type="text" id="keyCode" size="2">
</body>
dojo.connect(document, "onkeyup", function(event) {
	dojo.byId("keyCode").value = event.keyCode;
});
View Demo

This example shows how simple it is to capture keyboard events on form elements and doing something (logging to the console) using Dojo's normalized events and dojo.keys. This was accomplished using:

You will notice, however, that our example doesn't behave as expected, and some functionality is missing - such as handling the enter key. In our next example we'll fill in some missing details.

The KeyboardEvent object

As you can see below, when a keyboard event fires, a KeyboardEvent is passed to the event handler. This event object contains a lot of information about the event, but typically the piece most needed is the keyCode value. This is the Unicode value of the key pressed.

Moving on (pun intended), we can make this simple example more elegant and functional using the power of Dojo:

<body>
    <h1>Press Up/Down Arrow Keys or Enter</h1>
    <input type="text" id="input1" value="up">
    <input type="text" id="input2" value="down">
	<input type="submit" id="send" value="Send">
</body>
dojo.query("input[type='text']").connect("onkeydown", function(event) {
	switch(event.keyCode) {
		case dojo.keys.UP_ARROW:
			event.preventDefault();
			//preventing the default behavior in case your browser
			// uses autosuggest when you hit the down or up arrow.
			log("up arrow has been pressed");
			break;
		case dojo.keys.DOWN_ARROW:
			event.preventDefault();
			//preventing the default behavior in case your browser
			// uses autosuggest when you hit the down or up arrow.
			log("down arrow has been pressed");
			break;
		case dojo.keys.ENTER:
			log("enter has been pressed");
			break;
		default:
			log("some other key: " + event.keyCode);
	}
});
View Demo

With just a few changes, we've eliminated some redundant code, as well as making our script more powerful — allowing us to handle more than one type of key press in a single function callback, as well as handling multiple elements. By using dojo.query, we can make use of the connect method for the NodeList that dojo.query returns. This works exactly the same as the normal dojo.connect() function, except that all the nodes in the NodeList are targeted.

The previous example uses some powerful pieces of Dojo, but in order to fully complete our task of using keyboard events to traverse our form, we need to add a couple more pieces to our example. See the new example for a fully functional example:

<body>
	<h1>Press Up/Down Arrow Or Enter Keys to traverse form.</h1>
	<h2>Home/End will go to the beginning or end.</h2>
	<form id="traverseForm">
		First Name: <input type="text" id="firstName">
		Last Name: <input type="text" id="lastName">
		Email Address: <input type="text" id="email">
		Phone Number: <input type="text" id="phone">
		<input type="submit" id="send" value="send">
	</form>
</body>
dojo.require("dojo.NodeList-traverse");

var inputs = dojo.query("input");

dojo.connect(dojo.byId("traverseForm"), "onkeydown", function(event) {
	var node = dojo.NodeList(event.target);
	var nextNode;

	switch(event.keyCode) {
		case dojo.keys.UP_ARROW:
			nextNode = node.prev("input");
			if(nextNode[0]){
				//if not first element
				nextNode[0].focus();
				//moving the focus from the current element to the previous
			}
			break;
		case dojo.keys.DOWN_ARROW:
			nextNode = node.next("input");
			if(nextNode[0]){
				//if not last element
				nextNode[0].focus();
				//moving the focus from the current element to the next
			}
			break;
		case dojo.keys.HOME:
			inputs[0].focus();
			break;
		case dojo.keys.END:
			inputs[inputs.length - 2].focus();
			break;
		case dojo.keys.ENTER:
			event.preventDefault();
			//prevent default keeps the form from submitting when the enter button is pressed
			//on the submit button
			if(event.target.type !== "submit"){
				nextNode = node.next("input");
				if(nextNode[0]){
					//if not last element
					nextNode[0].focus();
					//moving the focus from the current element to the next
				}
			}else {
				// submit the form
				log("form submitted!");
			}
			break;
		default:
			log("some other key: " + event.keyCode);
	}
});
View Demo

In the above demo, we use dojo.connect to add an onkeydown event listener to our form. When an onkeydown event fires, if the key matches the dojo.keys keyCode for the up arrow, down arrow, enter key, home key, or end key, the appropriate action is taken. We use dojo.keys here to simplify matching the event keyCode to its corresponding key.

Conclusion

Dojo's event normalization using dojo.connect makes it increasingly simple to handle keyboard input inside of the often changing and conflicting browser environment. Using dojo.connect and dojo.keys, we created a form that expanded upon the default behavior of the up/down arrows and enter key. With this new knowledge, think of ways that you can use Dojo's event normalization and event delegation to increase the usability of your web application.

Resources

Find more details about the tools we used in this tutorial: