| Click Here for Previous | JavaScript Tutorial Home | Click Here for Next |
|
|
||
I want to launch a child window and establish event handlers for it. How is this done? It's not difficult, but unfortunately, the methods for Netscape4 and IE are different.
In Example 2-1 we saw how to cause a separate, or "child" window to pop up. Below is a form containing buttons and a text region for launching and writing to a child window. There's nothing really new in this part, except calling JavaScript from button and text elements instead of from links. That actually turned out to be harder to get right than I expected. For one thing, I learned that Netscape buffers the output to the page until it completes a line. Hence the <BR> appended whenever we write text.
Here's the HTML for the controls:
<form name="buttons"
onSubmit="showMe(document.buttons.writeText.value); return false">
<input NAME="launchButton" TYPE="button" VALUE="Launch Window"
onClick="launchChildW()">
<input name="writeStuff" type="button" value="Write Stuff"
onclick="showMe(document.buttons.writeText.value)">
<input NAME="writeText" TYPE="text" VALUE="write stuff here...">
</form>
|
And here's the JavaScript code that they invoke.
<script type="text/javascript" language="JavaScript">
var childW = null;
function launchChildW() {
if (childW != null) childW.window.close();
wopts = 'width=300,height=500,resizable=1,alwaysRaised=1,scrollbars=1';
childW = window.open('', 'childW', wopts);
if (childW != null) {
childW.document.open()
childW.document.bgColor = "ccffcc";
childW.document.write('<br>');
if (childW.opener == null) {
childW.opener = self;
}
} else {
alert("Failed to open child window");
}
}
function showMe(txt) {
if (childW == null) {
// alert("it wasn't open"); return false;
launchChildW();
}
// Note: NN4 won't actually display anything until the line is complete
// Hence the <BR> is required to flush the text.
childW.document.writeln(txt + "<BR>");
}
//-->
</script>
|
This method only works with Netscape Navigator. Press the following button to enable several event handlers for the child window.
Now try clicking in the child window. You should see messages indicating when the "mouseDown", "mouseUp" and "Click" events occur. Here's the HTML code for the button:
<form name="buttons2">
<input name="enableButton" type="button" value=
"Enable Child Click Handler" onclick="enableChild()">
</form>
|
For some reason, by holding the mouse button down for more than a second or so, I am able to confuse the event handling system so that it no longer recognizes "Click". No ideas yet on why this occurs...
The JavaScript code for enableChild() is
below:
function handleMe(evnt) {
// an event object is normally passed to event handlers.
showMe(evnt.type + " fired... ");
}
function enableChild() {
if (childW == null) launchChildW();
// Here's the Netscape 4 method...
// Intercept several types of events from the child window.
childW.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP);
// Register handlers for the various events
childW.onClick = handleMe;
childW.onMouseDown = handleMe;
childW.onMouseUp = handleMe;
}
|
The comments in the code are pretty self-explanatory. Consult the Netscape documentation for more info.
Unfortunately, IE behaves somewhat differently. The first thing you will notice, if you try it, is that IE gags on the JavaScript statement:
childW.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP); |
I searched the web at length for a good discussion of the differences, or even for some good documentation on IE's model. While there's an abundance of web-based material on how to use Netscape's events, I was surprised to find much less for IE. What there is mostly discusses the theory of the "bubble-up" event model in a single document (Ryan Detert's IRT tutorial is good at this). The best overall discussion I found is Danny Goodman's article referred to at the top of this page. However even that did not reveal all.
Here is a summary of what needs to change for this code to work in IE:
onClick) must be
in all-lowercase (i.e. onclick). Fortunately
the lowercase names are compatible with both browsers.
event object to an event
handler, like this:
function handleMe(evnt) {
// an event object is normally passed to event handlers.
showMe(evnt.type + " fired... ");
}
|
But in IE the event object is not passed to the event
handler but is stored as a property of the window
object. Here's the (almost) equivalent code for IE:
function handleMe() {
// The event object is a property of the window.
showMe(window.event.type + " fired... ");
}
|
I called it "almost" equivalent because here the identity of the
window object is hard-coded and not actually correct
for our test case -- we will use childW
instead.
type property is pretty much the same on
both. The Goodman article has a good summary.
document
object, not the enclosing window object.
Netscape was fine the other way, but can be made to
work compatibly by calling captureEvents on
the childW.document object
instead of just childW.
In order to make this all work, we need code to distinguish between Netscape and IE browsers. Here is what Danny Goodman used in his article, it will do fine for present purposes:
var isNav4, isIE4
if (parseInt(navigator.appVersion.charAt(0)) >= 4) {
isNav4 = (navigator.appName == "Netscape") ? true : false
isIE4 = (navigator.appName.indexOf("Microsoft" != -1)) ? true : false
}
|
Using the isNav4 and isIE4 flags along with
the code changes described in the preceding section we can now write
our event code so that it works with both browsers. Here are the new
versions of handleMe and
enableChild. The other routines were not modified.
function handleMe(evnt) {
// Netscape passes an event object to event handlers,
// but IE passes nothing. Note that childW is hard-wired.
if (isNav4) showMe(evnt.type + " fired... ")
else if (isIE4) showMe(childW.event.type + " fired... ")
else alert("Unknown browser type");
}
function enableChild() {
if (childW == null) launchChildW();
if (isNav4) {
// Intercept several types of events from the child window.
childW.document.captureEvents(Event.CLICK | Event.MOUSEDOWN | Event.MOUSEUP);
}
// Register handlers for the various events
// lowercase event names are NS/IE compatible
childW.document.onclick = handleMe;
childW.document.onmousedown = handleMe;
childW.document.onmouseup = handleMe;
}
|
This seems to work fine on both browsers. However, a topic for further investigation is to learn why Netscape sometimes stops handling the click event.
- Netscape JavaScript Developer's Guide
- See the section on Events
- Netscape JavaScript Reference Manual
- Refer to the section on Events
- Danny Goodman's article Dueling Event Models: A Cross-Platform Look.
- This is a very good article. I wish I had found it sooner.
- IRT.org
- See Ryan Detert's article Man-Handling Events #1. This is a good article, but it did not reveal the key points needed to get this working on IE. (IRT is where I got the idea for putting the pale green boxes around code examples.)
| Click Here for Previous | JavaScript Tutorial Home | Click Here for Next |
|
|
|
|
|
|