Dynamic HTML: The Definitive Reference, 2rd Ed.Dynamic HTML: The Definitive ReferenceSearch this book

6.6. Understanding Keyboard Event Data

If you examine the Events module of the DOM Level 2 recommendation, you may notice that keyboard events are nowhere to be found. As the W3C working group discovered, keyboard events in a Unicode world are tricky things to mold into an acceptable standard. But keyboard events in one form or another have been implemented in browsers since Netscape 4 and IE 4. Even though the Version 6 browsers carry forward the concepts from earlier days, the drafts of future W3C DOM Level 3 Events module indicate that keyboard event processing may take on new syntax in the future. In the meantime, we have "old-fashioned" keyboard events, with processing that is not always straightforward due to differences in event object details across browser versions.

The most important data related to a keyboard event is the identity of either the physical key being activated or the character generated by that key. These are not the same things. Every key has a numeric code associated with it. For example, a U.S. English keyboard assigns the number 65 to the key labeled A. That same key, however, can produce at least two different characters (A and a) on every U.S. computer, and even more characters on operating systems like the Macintosh (where the Option and Option-Shift modifier keys let that A key generate even more characters).

It so happens that the code "65" is also the ASCII and Unicode value of the uppercase A letter (this isn't a coincidence as much as it reflects the English-centric basis of early computing). The character codes for the A and a characters are 65 and 97, respectively. For some scripting tasks, the character code is important—such as whether the character is a numeral, regardless of whether the user pressed a top row keyboard key or a numeric keypad key; for other tasks, the key pressed is important—such as whether the user pressed the PageDown key (which doesn't have a character associated with it).

Complicating the issue is that the IE event object has only one property value that conveys a code for a keyboard event (event.keyCode). IE 5/Mac and Netscape 6 have a second property (charCode) that conveys additional event information. To expose both the key and character codes, even with only one property, the browsers let the different keyboard events deliver different information. To read the key code, use only the onkeydown or onkeyup events; use the onkeypress event to read the character code.

You must still reconcile the event object property differences among the browsers to work with keyboard events. The key code for the onkeydown and onkeyup events is available from the keyChar property of the IE and Netscape 6 event objects. For the onkeypress event's character code, use the keyCode property for IE and charCode property for Netscape 6. IE 5/Mac provides the same character code data for both properties of an onkeypress event.

To see how these different events and properties expose codes to scripts, Example 6-1 dynamically displays as many keyboard-related event object properties as the browser supports (see Figure 6-2). In the course of processing each event type, the event listener functions display the keyCode properties for all browsers. If a browser also supports the charCode property, its values appear in the table.

You can witness interesting characteristics of the onkeydown and onkeyup events when you use modifier keys. For example, if you type an uppercase A by pressing and holding the Shift key before typing the A key, you see that the onkeydown event fires, and that the keycode for the Shift key (16) appears in the keyCode property. But when you then press the A key, a new event object comes on the scene, with its own keyChar property value.

Note that this is not how your scripts detect whether a modifier key is pressed during a keyboard or other event. The event object in both models has Boolean properties—altKey, ctrlKey, and shiftKey—that your character key event handler can inspect. If the keyChar property of an onkeydown event indicates the C key, and if the event object's ctrlKey value is true, the user has typed Ctrl-C.

Example 6-1. Keyboard events and codes

<html>
<head>
<title>Keyboard Events and Codes</title>
<style type="text/css">
body {font-family:Arial, sans-serif}
h1 {text-align:right}
td {text-align:center}
</style>
<script language="JavaScript" type="text/javascript">
// array of table cell ids
var tCells = ["downKey", "pressKey", "upKey", "downChar", "pressChar", 
"upChar", "keyTarget", "character"];
  
// clear table cells for each key down event
function clearCells( ) {
    for (var i = 0; i < tCells.length; i++) {
        document.getElementById(tCells[i]).innerHTML = "&mdash;";
    }
}
  
// display target node's node name
function showTarget(evt) {
    var node = (evt.target) ? evt.target : ((evt.srcElement) ? 
               evt.srcElement : null);
    if (node) {
        document.getElementById("keyTarget").innerHTML = node.nodeName;
    }
}
  
// decipher key down codes
function showDown(evt) {
    clearCells( );
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt) {
        document.getElementById("downKey").innerHTML = evt.keyCode;
        if (evt.charCode) {
            document.getElementById("downChar").innerHTML = evt.charCode;
        }
        showTarget(evt);
    }
}
  
// decipher key press codes
function showPress(evt) {
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt) {
        document.getElementById("pressKey").innerHTML = evt.keyCode;
        if (evt.charCode) {
            document.getElementById("pressChar").innerHTML = evt.charCode;
        }
        showTarget(evt);
        var charCode = (evt.charCode) ? evt.charCode : evt.keyCode;
        // use String method to convert back to character
        document.getElementById("character").innerHTML = 
            String.fromCharCode(charCode);
    }
}
  
// decipher key up codes
function showUp(evt) {
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt) {
        document.getElementById("upKey").innerHTML = evt.keyCode;
        if (evt.charCode) {
            document.getElementById("upChar").innerHTML = evt.charCode;
        }
        showTarget(evt);
    }
}
  
// set page-wide event listeners
document.onkeydown = showDown;
document.onkeypress = showPress;
document.onkeyup = showUp;
</script>
</head>
<body>
<h1>Key and Character Codes vs. Event Types</h1> 
<hr>
<p>Enter some text with uppercase and lowercase letters:<br>
<form>
<input type="text" id="entry" size="60" 
       onkeydown="showDown(event)" 
       onkeypress="showPress(event)" 
       onkeyup="showUp(event)">
</textarea></p>
</form>
<table border="2" cellpadding="5" cellspacing="5">
<caption>Keyboard Event Properties</caption>
<tr><th>Data</th><th>keydown</th><th>keypress</th><th>keyup</th></tr>
<tr><td>keyCode</td>
    <td id="downKey">&mdash;</td>
    <td id="pressKey">&mdash;</td>
    <td id="upKey">&mdash;</td>
</tr>
<tr><td>charCode</td>
    <td id="downChar">&mdash;</td>
    <td id="pressChar">&mdash;</td>
    <td id="upChar">&mdash;</td>
</tr>
<tr><td>Target</td>
    <td id="keyTarget" colspan="3">&mdash;</td>
</tr>
<tr><td>Character</td>
    <td id="character" colspan="3">&mdash;</td>
</tr>
</table>
</body>
</html>

Figure 6-2 shows some sample output for Example 6-1.

Figure 6-2

Figure 6-2. Viewing keyboard event data

Regardless of the operating system you use, you should try Example 6-1 on at least two different browsers. This way you can see how the three events stuff values into event object properties in different event models.



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.