Home Articles FAQs XREF Games Software Instant Books BBS About FOLDOC RFCs Feedback Sitemap
irt.Org

Related items

Man-Handling Events #3

Man-Handling Events #1

Events and Event Handlers

Man-Handling Events #2

You are here: irt.org | Articles | JavaScript | Events | Man-Handling Events #2 [ previous next ]

Published on: Sunday 5th December 1999 By: Ryan Detert

Man-Handling Events #2

Introduction

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.

Capturing a Key Press Event

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;

Cancelling a Key Press Event

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>

Event Handler Support

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

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

onkeyup fires when a keyboard key is released. The same keys as the onkeydown event will trigger onkeyup.

onkeypress

onkeypress fires when any alphanumeric key is held. This includes the following:

Reading The Actual Key

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>

Getting More Than You Bargained For At Times

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

Working Examples

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.

Conclusion

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.

Related items

Man-Handling Events #3

Man-Handling Events #1

Events and Event Handlers

©2018 Martin Webb