9.9 Reading Which Noncharacter Key Was Pressed
NN 6, IE 4
9.9.1 Problem
You want to initiate a script
action based on whether the user pressed one of the noncharacter
keyboard keys.
9.9.2 Solution
Use the onkeydown or onkeyup event
handler to read the code number associated with the noncharacter key.
You can read this value from the event object's
keyCode property in IE 4 or later and Netscape
6 or later.
The following function (which also invokes the
getElementStyle(
) function from Recipe 11.12) moves an
absolute-positioned element in five-pixel increments in the direction
of the keyboard arrow key that the user presses:
function handleArrowKeys(evt) {
evt = (evt) ? evt : ((window.event) ? event : null);
if (evt) {
var top = getElementStyle("moveableElem", "top", "top");
var left = getElementStyle("moveableElem", "left", "left");
var elem = document.getElementById("moveableElem");
switch (evt.keyCode) {
case 37:
elem.style.left = (parseInt(left) - 5) + "px";
break;
case 38:
elem.style.top = (parseInt(top) - 5) + "px";
break;
case 39:
elem.style.left = (parseInt(left) + 5) + "px";
break;
case 40:
elem.style.top = (parseInt(top) + 5) + "px";
break;
}
}
}
document.onkeyup = handleArrowKeys;
This example uses the onkeyup event handler
because the onkeydown event is broken in Netscape
7 (and neither onkeyup nor
onkeydown works in Netscape
6.x). This is too bad: when you use
onkeydown in IE, holding the key down until it
goes into auto-repeat causes the onkeydown event
to fire repeatedly, moving the positioned element in the same
direction over and over (a desirable user interface behavior).
9.9.3 Discussion
Key codes are different from character codes.
Each physical key on the keyboard has a code associated with it. For
example, while the "2" key in the
top row of character keys and the
"2" key on the numeric keypad
generate the same character codes, each key creates a distinct key
code during onkeydown and
onkeyup events. Key codes for regular alphanumeric
keys are the same regardless of whether the Shift key is down at the
time. Appendix B lists the key codes for a typical
English-language PC keyboard.
Designing an application around the noncharacter keys is tricky
because each browser and operating system has its own default
behavior for things like function and navigation keys. To prevent
scripts from hijacking the application entirely, browsers do not let
you block events that are native to the application or operating
system. Thus, in the function shown in the Solution, where the four
arrow navigation keys are used to move an element, if the page is
scrollable at all, the default scrolling action also occurs in
addition to the repositioning of the element. No amount of returning
false or canceling event bubbling prevents the
normal action from taking place. (Although in this case, if you
assign focus to an empty text input field, the default of moving the
cursor has no apparent action, and the page doesn't
scroll.)
If you wish to program a function key to
initiate some action, you should plan to do so only on one browser
platform on one operating system whose key behaviors you can predict.
Even in just the Windows environment, you need to make sure that a
function key you wish to program truly has no default
action—something that isn't always apparent
just by trolling through the browser's menus. Some
function key assignments are implemented to perform actions not
listed in any menu. Test, test, test!
These same kinds of cautions apply to attempts at scripting keyboard
combinations to act as scripted shortcuts. You cannot override
browser-defined keyboard shortcuts and finding unused two-key
combinations across browsers will be a challenge. It is easier to
find accelerator combinations utilizing two or more modifier keys.
For example, the following
onkeyup event handler function invokes the
runSpecial( ) function when the user holds down
Ctrl-Alt and then presses and releases the
"P" key in IE 4 or later and
Netscape 7 or later:
function handleAccelerator(evt) {
evt = (evt) ? evt : ((window.event) ? event : null);
if (evt) {
if (evt.keyCode = = 80 && evt.ctrlKey && evt.altKey) {
runSpecial( );
}
}
}
document.onkeyup = handleAccelerator;
When coding accelerator key behavior, it is best to bind the keyboard
event to the document node because that node has
the greatest scope. Keyboard events that occur inside nested nodes
(such as text input fields or text areas) will bubble up to the
document node unless cancelled along the way. If
such an event occurs inside an editable text field, the target of the
event is the text field element. Thus, you could create a
context-sensitive help feature with
Ctrl-Alt-F2 providing details about the field while the user is
editing it:
function showHelp(elem) {
var elemID = elem.id;
switch (elemID) {
case "name":
alert("Enter your full name.");
break;
case "email":
alert("We will be contacting you with your access code. \n" +
"Make sure the address is accurate and up to date.");
break;
...
}
}
function handleAccelerator(evt) {
evt = (evt) ? evt : ((window.event) ? event : null);
var elem = (evt.target) ? evt.target :
((evt.srcElement) ? evt.srcElement : null);
if (evt) {
// for Ctrl+Alt+F2
if (evt.keyCode = = 113 && evt.ctrlKey && evt.altKey) {
showHelp(elem);
}
}
}
document.onkeyup = handleAccelerator;
You can't use F1 in this case, because IE for
Windows triggers the application help system with any keyboard
combination involving the F1 function key.
9.9.4 See Also
Recipe 9.1 for equalizing disparate event model objects; Recipe 9.6
for equalizing event target references; Recipe 9.8 for reading
character key values; Recipe 9.10 for reading modifier key status
during keyboard-event processing.
|