Mouseover effect

This script does not work reliably in WebTV.

Explorer 5 on Windows is very slow with mouseovers when you set the caching to 'Every time', because it reloads the images for each mouseover. For testing purposes, set the caching to 'Automatically', this is the default value anyway.

The most wanted script, no doubt, is the standard image-swap mouseover. When the user moves over an image within a link, the image changes slightly, giving a nice effect. In fact, you load a different image at the place the first image was.

This is an old, old script. I wrote it in 1998, updated it in 2000 and have used it many times. It is written with Netscape 3 compatibility in mind. If you're looking for a modern script that does the same, see the New mouseover script. It's far cleaner than this one, but only works in modern browsers.

First an example so that you can see the effect for yourself, then the actual script. Then I need to explain about the names of the images, both the actual files and the <img> tags. Then we declare some variables and go on to the explanations of the actual functions.
Finally, some words of caution when you combine this script with DHTML in Netscape 4.

Example

Move over the images below with your mouse to see the effect. (OK, I admit that they're not particularly beautiful)

The script


// Some variables

var base= "pix/mo_"
var nrm = new Array();
var omo = new Array();
var stuff = new Array('home','place');

// Pre-load part.

if (document.images)
{
	for (i=0;i<stuff.length;i++)
	{
		nrm[i] = new Image;
		nrm[i].src = base + stuff[i] + ".gif"
		omo[i] = new Image;
		omo[i].src = base + stuff[i] + "_omo.gif";
	}
}


// The functions: first mouseover, then mouseout

function over(no)
{
	if (document.images)
	{
		document.images[stuff[no]].src = omo[no].src
	}
}

function out(no)
{
	if (document.images)
	{
		document.images[stuff[no]].src = nrm[no].src
	}
}

In the HTML-page itself, you'll have to add the mouseover and mouseout event handlers to the <A>-tag.

<A HREF="whatever.html" onMouseOver="over(0)"
	onMouseOut="out(0)"><IMG
 	src="pix/mo_home.gif" NAME="home" etc.></A>

<A HREF="whatever.html" onMouseOver="over(1)"
	onMouseOut="out(1)"><IMG
	src="pix/mo_place.gif" NAME="place" etc.></A>

Names

This script relies on several things having the same name. First of all, give your images a name that helps you remember which name is which image. In the example I give my images the core names home and place.

Then, we start giving the image files and the HTML <img> tags their proper names.

This all has to do with the crucial array

var stuff = new Array('home','place');

As you see, the names of the images are repeated here so that the script knows what the names are. Now it is very easy to tell the script to change an image: we only have to call it by its name.

Nowadays the web standards say you really should use the id attribute instead of name. However, using id causes the script to break in older browsers (Netscape 4 and below). If older browsers are important for you, use name.

The variables

First of all we define some variables:

// Some variables

var base= "pix/mo_"
var nrm = new Array();
var omo = new Array();
var stuff = new Array('home','place');

base is the start of the name of each image file. In the example it is pix/mo_. The image files are in the directory pix and their names all start with mo_. I do this so that the images are all grouped together in the directory listing and the start of the name gives some clues about what these image files are for.

Then come two arrays, nrm and omo. Into these we're going to pre-load the images (see below) and when the actual changes take place the script takes the images from these arrays.

Finally the all-important array stuff in which the image names are written. Note that the names have to be between apostrophes and separated by commas.

The pre-loading

if (document.images)
{

Now we start working. First of all, we check if document.images is supported. If it isn't, nothing should happen because the browser would only give error messages.

	for (i=0;i<stuff.length;i++)
	{

If it is supported, we go through the entire array stuff. After all, each name in this array represents an image.

		nrm[i] = new Image;
		nrm[i].src = base + stuff[i] + ".gif"
		omo[i] = new Image;
		omo[i].src = base + stuff[i] + "_omo.gif";
	}
}

Now we produce the name of the first normal image, number 0 in the array:

pix/mo_ (base) + home (stuff[0]) + .gif

which makes pix/mo_home.gif. The image is stored in nrm[0].src where the script can easily reach it when the time for actual image changes comes.

Then we produce pix/mo_home_omo.gif in the same way and store it in omo[0].src. In this way we pre-load all necessary normal and mouseover images and store them in the arrays nrm[] and omo[].

There's another important consideration here: As soon as the .src property is assigned, the browser starts downloading the images. This is very useful, in that when the user scrolls his mouse over an image and the image is replaced by another one, he doesn't have to wait for the second image to be downloaded: it is already in his browser's cache.

Now we have finished the preparations and wait for the user to mouseover.

The functions

// The functions: first mouseover, then mouseout

function over(no)
{
	if (document.images)
	{
		document.images[stuff[no]].src = omo[no].src
	}
}

function out(no)
{
	if (document.images)
	{
		document.images[stuff[no]].src = nrm[no].src
	}
}

A very simple command is now sufficient to do the mouseover and -out. As soon as the user goes over an image, the function over() is called and given a number. For the image home this is 0, for place it is 1. We have pre-loaded them in this order, so the script should be given the correct number. It does not matter where the images are in the page, as long as the numbers conform to the array stuff.

When the user mouses over the Home image, the script is told to switch 0.

function over(no) <-- no = 0 in this case

Then we check if the browser supports document.images. If it doesn't, nothing should happen.

if (document.images)
{

Then it looks up what image it should change:

document.images[stuff[no]].src

Since no is 0, it searches for stuff[0],

document.images[stuff[0]].src

which is 'home'.

document.images['home'].src

It has now found the image it should change. What image should be loaded in its place?

document.images['home'].src = omo[no].src

Since no is still 0, it should load omo[0].src.

document.images['home'].src = omo[0].src

In the pre-loading script, we have ascertained that

omo[i].src = base + stuff[i] + "_omo.gif";

so

omo[0].src = base + stuff[0] + "_omo.gif";

which means

omo[0].src = "pix/mo_" + "home" + "_omo.gif";

which is pix/mo_home_omo.gif, the mouseover image for 'home'!

onMouseOut the same thing happens, except that the browser now puts the normal image (nrm[0], which is pix/mo_home.gif) in the correct place.

Finished! You now have your very own mouseover-script.
If you wish, you can add an onClick image swap to it.

Mouseovers in layers

The idea for the actual script courtesy of David Gestel.

One final word of caution: this script works in all browsers except in Netscape 4 when you put the images in a DHTML layer. (For more information about DHTML, see the Introduction to DHTML page)

The problem is that as soon you put the images in a DIV with a position declaration in the style sheet, Netscape 4 considers them moved from the document to a kind of sub-document called

document.layername.document

so that if you want to change an image, you need to do

document.layername.document.images[stuff[no]].src = etc.

So if you use DHTML layers with mouseover images inside them, you need to change the script a bit:

function over(no,id)
{
	if (document.layers && id)
	{
		document.layers[id].document.images[stuff[no]].src = omo[no].src
	}
	else if (document.images)
	{
		document.images[stuff[no]].src = omo[no].src
	}
}

function out(no,id)
{
	if (document.layers && id)
	{
		document.layers[id].document.images[stuff[no]].src = nrm[no].src
	}
	else if (document.images)
	{
		document.images[stuff[no]].src = nrm[no].src
	}
}

and (assuming there is a DIV ID="thelayer") call the script like

<a href="whatever.html" onmouseover="over(1,'thelayer')"
 onmouseout="out(1,'thelayer')">
<img src="pix/mo_place.gif" name="place" etc.> </a>

The trick is very simple. If Netscape 4 executes the script

if (document.layers

and the call gives a variable id to the function

&& id)

then call a special Netscape 4 routine

document.layers[id].document.images[stuff[no]].src = omo[no].src

So if you call the mouseover like above, Netscape 4 searches in the layer called thelayer for the correct image. No other browser does this, because for them it's not necessary.

In addition, if an image is not in a layer but in the document itself, simply call the mouseover in the old way without the ,'thelayer' bit. Then there is no variable id given to the function and document.layers is still true, but id doesn't exist and Netscape 4 executes the usual function.