If you haven’t experimented with cross-browser event handling scripts, this might be just the primer for you. This example utilizes three event handlers: onclick, onmousemove, and onkeypress. When you first click anywhere in the document space, the JavaScript captures the initial x and y coordinates of the mouse-pointer arrow with respect to the browser window. After that, the status bar displays the x and y coordinates as the user moves the pointer arrow around. Clicking once again “turns off” the coordinate tracking and calculates the pixel distance between the point the user first clicked and current location. You can see this in Figure 6.7 and Figure 6.8.
Independent of the mouse action, you can also type any sequence of keys on your keyboard. The status bar will then display each of the individual keys you type. When you finish, choose the “Show Keys” button, and you’ll get a JavaScript alert dialog box that displays the cumulative sequence of keys you entered up to that point. Figure 6.9 shows this. Choose “OK,” and you start again from scratch.
By now you’re familiar with the intricacies of coding
cross-browser stylesheets. You know: LAYER
tags in
one browser, DIV
tags in the other.[3] Things
don’t change much for the good when it comes to the event
models, either. If you check the source code in
events.html,
you’ll
find the following two lines of JavaScript:
document.onclick = enableEffects; document.onkeypress = keepKeys;
The onclick event handler is associated with
function enableEffects()
, and the
onkeypress event handler is associated with
function keepKeys()
. Both functions are shown
below. Notice that neither function has any parentheses in the
syntax. That is, the code does not look like this:
document.onclick = enableEffects(); document.onkeypress = keepKeys();
Using parentheses would call each method the moment each line was interpreted. You don’t want that: the event handlers are associated by a reference to the functions, instead. Look at the code in Example 6.5.
Example 6-5. events.js
1 var keys = ''; 2 var change = true; 3 var x1, x2, y1, y2; 4 5 function enableEffects(ev) { 6 if(change) { 7 if(document.layers) { 8 x1 = ev.screenX; 9 y1 = ev.screenY; 10 document.captureEvents(Event.MOUSEMOVE); 11 } 12 else { 13 x1 = event.screenX; 14 y1 = event.screenY; 15 } 16 document.onmousemove = showXY; 17 } 18 else { 19 if (document.layers) { 20 x2 = ev.screenX; 21 y2 = ev.screenY; 22 document.releaseEvents(Event.MOUSEMOVE); 23 } 24 else { 25 x2 = event.screenX; 26 y2 = event.screenY; 27 document.onmousemove = null; 28 } 29 window.status = 'Start: (' + x1 + ',' + y1 + 30 ') End: (' + x2 + ',' + y2 + ') Distance: ' + 31 (Math.round (Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2)))) + ' pixels'; 32 } 33 change = !change; 34 } 35 36 function showKeys() { 37 if (keys != '') { 38 alert('You have typed: ' + keys); 39 window.status = keys = ''; 40 } 41 else { alert('You have to type some keys first.'), } 42 } 43 44 function showXY(ev) { 45 if (document.all) { ev = event; } 46 window.status = 'X: ' + ev.screenX + ' Y: ' + ev.screenY; 47 } 48 49 function keepKeys(ev) { 50 if (document.layers) { 51 keys += String.fromCharCode(ev.which); 52 window.status = 'Key pressed: ' + String.fromCharCode(ev.which); 53 } 54 else { 55 keys += String.fromCharCode(event.keyCode); 56 window.status = 'Key pressed: ' + String.fromCharCode(event.keyCode); 57 } 58 }
Function enableEffects()
is the epicenter for the
click
and
mouseover
events. I call
your attention to lines 6, 18, and 33:
if (change) { .... else { .... change = !change;
The variable change starts as
true
and is changed to its opposite (i.e., to
false
, back to true
, and so
forth) during every call. Since clicking calls
enableEffects()
and change is
true
the first time, that brings lines 7-15, shown
here, into effect:
if(document.layers) { x1 = ev.screenX; y1 = ev.screenY; document.captureEvents(Event.MOUSEMOVE); } else { x1 = event.screenX; y1 = event.screenY; }
These lines capture x and y coordinates and enable the
onmousemove
event handler. If
document.layers
exists, the user has Navigator.
The event object created on the fly is reflected in the argument
passed to the function, named ev in this case.
Global variables x1 and y1
are set to the respective x and y coordinates where the
user first clicks (contained in screenX and
screenY ). Then the call to the document method
captureEvents()
causes the
mousemove
event to be
intercepted.[4]
If document.layers
does not exist, the script
assumes the user has Internet Explorer and takes appropriate actions
to do the same as above. Microsoft’s event model, however,
defines an event object as event. That’s
where properties screenX and screenY
will be waiting. No additional method calls are required
for event capturing in MSIE, which leads us to line 16:
document.onmousemove = showXY;
The onmousemove event handler is then assigned
by reference to function showXY()
in both
browsers. Let’s have a quick look at
showXY()
:
function showXY(ev) { if (document.all) { ev = event; } window.status = 'X: ' + ev.screenX + ' Y: ' + ev.screenY; }
The call to showXY()
each time the mouse moves
displays the x and y coordinates of the mouse-pointer arrow. The x
and y values are referenced in the same cross-browser manner as
before. showXY()
is called repeatedly as the user
moves the mouse around. This happens until the user decides to click
again, which puts in another call to
enableEffects()
. However, variable
change is false
this time
around, so lines 19-31 get the call:
if (document.layers) { x2 = ev.screenX; y2 = ev.screenY; document.releaseEvents(Event.MOUSEMOVE); } else { x2 = event.screenX; y2 = event.screenY; document.onmousemove = null; } window.status = 'Start: (' + x1 + ',' + y1 + ') End: (' + x2 + ',' + y2 + ') Distance: ' + Math.round(Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2))) + ' pixels';
Variables x1 and y1 hold
the values of the starting click location. Now variables x2
and y2 are set to the values of the
stopping click location. There is no longer a need to keep processing
the onmousemove event handler. So with
Navigator, the releaseEvents()
method is called to
cease interception of the mousemove
event. The
same result is performed by setting
document.onmousemove
equal to null
in MSIE.
All that remains is to display the distance between the starting and stopping points. Do you recall the distance formula? You may have used it in ninth grade Geometry class. That’s the same formula here in lines 29-31.
That takes care of the onclick and
onmouseover event handlers, leaving only
onkeypress. Remember that
document.onkeypress
was set to call function
keepKeys()
during the loading of
events.html. Here is
keepKeys()
, lines 49-58:
function keepKeys(ev) { if (document.layers) { keys += String.fromCharCode(ev.which); window.status = 'Key pressed: ' + String.fromCharCode(ev.which); } else { keys += String.fromCharCode(event.keyCode); window.status = 'Key pressed: ' + String.fromCharCode(event.keyCode); } }
Using the same browser detection technique, empty string variable
keys is set to itself plus the string equivalent
of the key pressed. This happens with
String.fromCharCode()
, regardless of browser.
JavaScript 1.2, however, represents the keystrokes as ISO Latin-1
characters. JScript uses Unicode
representations. The number in
JavaScript is stored in the which
property of
the event object. The number for JScript is reflected in the
event.keyCode
property. So the user types a
number of keys, then selects the “Show Keys” button. This
function alerts the value of keys, then sets it
to an empty string.
[3] Actually, you can use DIV
tags for
positioning in Netscape Navigator 4.x as long as you include a value
for “position” in the STYLE
attribute.
However, until Netscape comes on board with the document object
model, using the LAYER
tag gives you access to all
the properties of the Layer object.
[4] At least some versions of NN4.x seem to respond only intermittently to the mouse clicks. That is, sometimes you have to click twice to start or stop the tracking. I haven’t found any supporting documentation about such a bug.
18.117.111.1