You are here: irt.org | Articles | JavaScript | Events | Man-Handling Events #2 [ previous next ]
Published on: Sunday 5th December 1999 By: Ryan Detert
The previous event handling article covered the basic concepts and limitations of the event handling in Netscape and Explorer, in this article we will cover event handlers associated with key presses - introduced in JavaScript 1.2.
Generally, whenever you want to catch a key press, you add the appropriate event handler to an HTML tag, e.g.:
<form> <input type="text" onKeyPress="handler()"> </form>
When the user press a key in the above form, the handler() method is invoked. In NN4 an Event object, in this case the keyboard information, is passed as an argument to the handler() method. This keyboard information can then be manipulated like any regular object. In MSIE4+ the keyboard information instead bubbles up the DOM hierarchy until the Event object reaches the window object or is cancelled. Look at the following example:
<form> <input type="text" onKeyPress="handler()"> </form> <script language="JavaScript"><!-- function handler(e) { // In NN4, e now holds the keyboard information // For MSIE4, we can use the event object property: if (document.all) { e = window.event; } alert(e); } //--></script>
It is also possible to register a script function that will be used for all the key presses in a document by going:
<script language="JavaScript"><!-- document.onkeypress = handler;
In NN4, a keypress can be cancelled by returning false from within the event handling method. Similarly, this can be done in MSIE4 by setting the event's returnValue to false, e.g.:
<script language="JavaScript"><!-- function handler(e) { if (document.all) { e = window.event; } if (document.layers) return false; else if (document.all) e.returnValue = false } //--></script>
The following three event handlers are all new as of JavaScript 1.2:
Event Handler | Objects |
---|---|
onkeydown | Document, Image, Link, form text fields |
onkeyup | Document, Image, Link, form text fields |
onkeypress | Document, Image, Link, form text fields |
onkeydown fires when any valid keyboard key is pressed. Valid keys include:
In IE5, the event also fires for the following keys:
Also in IE5, the following keys and key combinations can be cancelled
onkeyup fires when a keyboard key is released. The same keys as the onkeydown event will trigger onkeyup.
onkeypress fires when any alphanumeric key is held. This includes the following:
Reading the actual key is a simple task. In Explorer use the keyCode event object property. In Netscape you use the which event object property. In both browsers this will return the ASCII unicode value.
<script language="JavaScript"><!-- function handler(e) { if (document.all) { e = window.event; } var key; if (document.layers) key = e.which; if (document.all) key = e.keyCode alert('Unicode value of key pressed was ' + key); } //--></script>
If you would like to convert this number to an alphanumeric character, use the following method:
String.fromCharCode(ascii_value [, another_ascii] [, ...]);
For instance:
<script language="JavaScript"><!-- function handler(e) { if (document.all) { e = window.event; } var key; if (document.layers) key = e.which; if (document.all) key = e.keyCode var chr = String.fromCharCode(key); alert('Character representation of pressed was ' + chr); } //--></script>
Likewise, to convert a character back to its ASCII equivalent you may use:
stringObject.charCodeAt(index);
For example:
<script language="JavaScript"><!-- function handler(e) { if (document.all) { e = window.event; } var key; if (document.layers) key = e.which; if (document.all) key = e.keyCode var chr = String.fromCharCode(key); alert('Character representation of pressed was ' + chr); alert('Unicode value of key pressed was ' + chr.charcodeAt(1)); } //--></script>
When using these key press handlers, each browser handles the keypresses a little bit differently. For instance, some handlers will read SHIFT + 'd' as a single capital 'D', whereas others will read each key press separately.
In Explorer onkeypress will NOT detect SHIFT + 'd' as two separate keypresses. However, the onkeydown and onkeyup handlers WILL detect something like SHIFT + 'd' as two separate keyboard entries. These two handlers will take a little bit of explaining so here it goes. Since the SHIFT key, for example, can be read separately, there is no need for IE to have to distinguish between capital and lowercase characters. If you were to press the 'f' key, IE would automatically interpret it as the unicode value for a capital 'F'. This also holds true for the number keys. A '3' key can only be read as '3' and pressing SHIFT will not cause it to be read as a '#'. Simply put the onkeydown and onkeyup handlers only detect which key is down and aren't really meant for regular use like the onkeypress handler.
Now, to read the SHIFT, ALT, or CTRL keys you may either check to see whether the window.event property equals one of their unicode values, or you may use IE's macro aliases: window.event.shiftKey, window.event.altKey, or window.event.ctrlKey respectively. For example, to detect a SHIFT key press you may do either of the following:
if (window.event.keyCode == 16) ... // Or if (window.event.shiftKey) ...
It is also important to note that the above code will only work for the onkeydown handler. This is because onkeyup will only read SHIFT, ALT, and CTRL as a depression and will not assign it a value.
For Netscape, the rules change a little bit as ALL keyboard event handlers will read each individual keypress! So how do you allow SHIFT + 'd' to be read as just one character? Well, the answer lies in the modifiers event object property. This will allow you to detect whether a modifier (SHIFT, CTRL, or ALT key) has been pressed. Netscape also has macro aliases for these keys which are Event.SHIFT_MASK, Event.CONTROL_MASK, and Event.ALT_MASK respectively. The modifier object property will return one of these values according to which key is being pressed. So, to detect ONLY a capital 'D' you may do the following for onkeydown and onkeypress:
function getKeyDown_KeyPress(e) { if( !e.modifiers || (e.modifiers == Event.SHIFT_MASK) && e.which) alert(String.fromCharCode(e.which)); }
To do the same with onkeyup you must do the same thing but this time with bit-wise logic. This is because, like Explorer, the onkeyup handler will read the shift key but will not interpret it as a modifier or give it a value of some sort.
function getKeyUp(e) { if( ~e.modifiers | (e.modifiers == Event.SHIFT_MASK) & e.which) alert(String.fromCharCode(e.which)); }
Below is a table of modifier values that can either be entered manually (e.g. Event.SHIFT_MASK) or returned automatically by using userObject.modifiers:
Modifier | Value (10b) | Value(2b) |
---|---|---|
SHIFT_MASK | 4 |
100 |
CTRL_MASK | 2 |
010 |
ALT_MASK | 1 |
001 |
To get any combinations of keypresses Netscape simply bit-wise OR's the values. For example a SHIFT and CONTROL combination would be 100(2b) | 010(2b) = 110(2b) = 6(10b).
Through all of this gibberish here is a table to help simplify things:
Event | ALT Detect | Control Detect | SHIFT Detect | ALT Maskable | CONTROL Maskable | SHIFT Maskable | Browser | Code Transfer |
---|---|---|---|---|---|---|---|---|
onkeypress | No |
No |
Yes w/ other keys |
No | No | Yes | IE |
No |
onkeydown | Yes |
Yes |
Yes |
Yes | Yes | Yes | IE |
Yes |
onkeyup | Yes |
Yes |
Yes |
No | No | No | IE |
Yes |
onkeypress | No |
Yes |
Yes |
No | Yes | Yes | NN |
Yes |
onkeydown | No |
Yes |
Yes |
No | Yes | Yes | NN |
Yes |
onkeyup | No |
Yes |
Yes |
No | No | No | NN |
No |
The first example, shows how to stop the user typing the letter J or j into the two form fields:
<script language="JavaScript"><!-- function noLetterJ(e) { var myChar; if (document.all) { e = window.event; myChar = String.fromCharCode(e.keyCode); } else if (document.layers) var myChar = String.fromCharCode(e.which); if (myChar == 'J' || myChar == 'j') { if (document.layers) return false; else if (document.all) e.returnValue = false } } document.onkeypress = noLetterJ; //--></script> <form> <input type="text" onKeyPress="return noLetterJ(event)"> <br> <textarea onKeyPress="return noLetterJ(event)"></textarea> </form>
Which you can try for yourself:
The second working example shows how to toggle a help screen when the user press h or H:
<html> <head> <script language="JavaScript"><!-- var isHelping = false; var state, helpState; var object; function getChar(e) { var myChar; if (document.all) { e = window.event; myChar = String.fromCharCode(e.keyCode); } else if (document.layers) myChar = String.fromCharCode(e.which); switch(myChar.toUpperCase()) { case 'H': object = 'HelpMe'; state = helpState = (!isHelping) ? 'visible' : 'hidden'; isHelping = !isHelping; break; default: return false; } if (document.all) { document.all[object].style.visibility = state; document.all[object].style.pixelTop = 10; document.all[object].style.pixelLeft = 3; } else if (document.layers) { document.layers[object].visibility = state; document.layers[object].top = 10; document.layers[object].left = 3; } } document.onkeypress = getChar; //--></script> </head> <body bgcolor="#FFFFFF" text="#0000FF" link="#FF0000" vlink="#FF0000" alink="#00FF00"> <span id="HelpMe" style="position:absolute; visibility: hidden;"> <table border="1" cellspacing="0" cellpadding="0"><tr><td> <table border="0" cellspacing="0" cellpadding="0"> <tr> <td colspan="2" bgcolor="#FFFFFF"><strong>Instructions for re-starting Win95:</strong></td> </tr> <tr> <td bgcolor="#FFFFFF"><img src='arrow.gif'></td> <td bgcolor="#FFFFFF">Click 'Start'</td> </tr> <tr> <td bgcolor="#FFFFFF"><img src='arrow.gif'></td> <td bgcolor="#FFFFFF">Click 'Sh<u>u</u>t Down...'</td> </tr> <tr> <td bgcolor="#FFFFFF"><img src='arrow.gif'></td> <td bgcolor="#FFFFFF">Select 'Restart'</td> </tr> <tr> <td bgcolor="#FFFFFF"><img src='arrow.gif'></td> <td bgcolor="#FFFFFF">Click OK</td> </tr> </table> </td></tr></table> </span> <p> This example works perfectly on MSIE4+ and non Unix NN4+: </p> <ul> <li>press h to toggle the help screen. </ul> <p> In NN4+ on Unix - this example needs a little help: </p> <ul> <li>click the text field, to give it focus, <li>type h into the form field to toggle the help screen. </ul> <form> <input type="text"> </form> </body> </html>
You can try out the second example for yourself.
Reading keyboard input from a single browser is fairly simple, however, integrating your code with Explorer and Netscape can be fairly complex. Nonetheless, allowing keyboard input to be accessed through scripting makes web pages much more robust and capable. It opens new doors and brings web scripting technology one step closer to that of a real application.