New JavaScript Mouse Events: NN/MSIE Compatibility | WebReference

New JavaScript Mouse Events: NN/MSIE Compatibility


Navigator / Explorer Compatibility
when is JavaScript 1.1 not JavaScript 1.1?

Things used to be so easy. Netscape would develop a new version of JavaScript with every primary release of Navigator. Microsoft would modify its JScript to conform. Presently the situation is confused.

Netscape has moved JavaScript closer to Java with some Perl thrown in by way of Regular Expressions. Microsoft has an expanded version of JavaScript to conform to its Document Object Model. Both companies proclaim that their versions comply with the new ECMAScript standard (based on the outdated JavaScript 1.1). The W3C work on a standard DOM will hopefully make the versions converge. But all this is another story we can discuss another time.

Recapping the Problem

Let's look at the problem from the previous page again:

Netscape Navigator 2.xx and Microsoft Internet Explorer 3.xx recognize only onMouseOver and do not have an Image object. (JavaScript 1.0)
Navigator 3.xx recognizes onMouseOver and onMouseOut and has an Image object. (JavaScript 1.1)
Navigator 4.xx and Explorer 4 recognize all four event handlers and have an Image object. (JavaScript 1.2)

add to this:
Explorer 3.02 (JScript 2.0) has the above limitations but recognizes LANGUAGE="JavaScript1.1".
Explorer's scripting engines are insertable, updatable modules so it's possible for different users to have different compatibility with the same browser version.

Confused? Don't be. Arranging for compatibility between browsers is not as difficult as the above may imply.

Laying Out the Solution

1. Define the Problem

Our problem is not whether the user is using this-or-that browser version.
Our problem is not whether the user's scripting engine is this-or-that version.

Our problem is that we don't want the user's browser to crash/hang-up/display errors. If we can throw a few scripting tricks their way, well that's a bonus.

2. Declare the Solution

If we look at the problem in this, almost cynical, fashion, then the solution is simple: Make sure that browsers read only the commands/scripts they understand.

3. Some Help from HTML parsing

Event handlers in HTML tags are treated as HTML and ignored by browsers that do not understand it, as is standard parsing practice. Thus, onMouseDown and onMouseUp will only be read by NN4 and IE4, both of which have an Image object. This function, therefore, remains as is:

function rollPress(imName,down) {
    if (down) { document.images[imName].src = imName + "down.gif" }
         else { document.images[imName].src = imName + "over.gif" }

4. Images please, over and out

Any browser that understands the Images object has a built-in Images array, as discussed earlier. The conditional statement if (document.images) will, therefore, return true for Image object browsers and if (!document.images) will return true for non-Image browsers.
Our over-out function is modified to filter out incapable browsers by catching them in the first line and returning them:

function rollOver(imName,over) {
    if (!document.images) {return};
    if (over) { document.images[imName].src = imName + "over.gif" }
         else { document.images[imName].src = imName + "up.gif" }

5. Avoid Duplication

The function that handles onClick should return non-Image browsers as well as version 4 browsers, since the latter do not need the press simulation. We need to identify NN4 and MSIE4, but we should not use the usual browser-detection scripts, because of the modular scripting engine problem we discussed above. What is unique to these two? What are their distinguishing marks?

The browser wars have led to different DOMs, giving us unique identifiers. Communicator has a built-in layers array which it uses to index positioned elements created through CSS or the <LAYER> tag. Explorer has a built-in all array, which it uses to reference... well, everything. Early in our script, we should assign true/false to a variable which we will reference later:

if (document.layers || document.all) {ver4 = true}
                                else {ver4 = false};
or, with less typing:
ver4 = (document.layers || document.all) ? true : false;
or, better still:
ver4 = (document.layers || document.all) ? 1 : 0;
Then, modify our simulator function:
function rollClick(imName) {
    if (!document.images || ver4) {return};
    document.images[imName].src = imName + "down.gif";
    dummy = setTimeout("document.images[imName].src = \"" + imName + "over.gif\"",100);

6. Fix preload array.

Finally, enclose your preloading in a conditional so it occurs only with qualifying browsers:

if (document.images) {
    arImageSrc = new Array (
        "../images/imButthat.jpg" )
    arImageList = new Array ();
    for (counter in arImageSrc) {
        arImageList[counter] = new Image();
        arImageList[counter].src = arImageSrc[counter];

7. Sorry for the scare.

Our apologies for the long-winded build up to what is, essentially, a couple of lines of code. These are code snippets that we will be using again and again in the weeks to come, so a detailed introduction seemed necessary.

Putting It All Together

Let's take all the code that we have introduced, tighten it up, and see the complete script for our effect:

Produced by Peter Belesis and

All Rights Reserved. Legal Notices.
Created: 07/31/97
Revised: 11/09/97