Lots of high-res images can really spruce up a Web site. But
they can also slow it down—images are files, files use bandwidth, and bandwidth
is directly related to wait times. It’s time you get yourself an education on
how to speed things up with a little trick called image preloading.

Image preloading

The way a browser normally works, images are loaded only
after an HTTP request is sent for them, either passively via an <img> tag
or actively through a method call. So if you have JavaScript that swaps an image
on mouseover, or changes an image automatically after a timeout, you can expect
to wait anywhere from a few seconds to a few minutes while the image is
retrieved from the server. This is especially noticeable if you have a slow
connection to the Internet, or if the images being retrieved are very
large…and the delay usually ruins the effect you were hoping for.

Some browsers try to mitigate this problem by storing the
images in the local cache so that subsequent calls to the image are satisfied
immediately…but there’s still a delay the very first time the image is
needed. Preloading is a technique where the image is downloaded to the cache
before it’s needed. That way when the image is really needed it can be
retrieved from the cache and displayed immediately.

The Image() object

The simplest way to preload an image is to instantiate a new
Image() object in JavaScript and pass it the URL of the image you want
preloaded. Say we have an image called heavyimagefile.jpg, which we want to
display when the user mouses over an already-displayed image. In order to
preload this image for faster response time, we simply create a new Image()
object, called heavyImage, and load
it simultaneously to the page with the onLoad() event handler:

<html>
<head>
<script language = "JavaScript">
function preloader()
{
heavyImage = new Image();
heavyImage.src = "heavyimagefile.jpg";
}
</script>
</head>
<body onLoad="javascript:preloader()">
<a href="#" onMouseOver="javascript:document.img01.src='heavyimagefile.jpg'">
<img name="img01" src="justanotherfile.jpg"></a>
</body>
</html>

Note that the image tag does not itself handle onMouseOver()
and onMouseOut() events, which is why the <img> tag in the example above
has been enclosed in an <a> tag, which does include support for those
event types.

Loading multiple images with arrays

In practice, you will probably need to preload more than
just one image; for example, in a menu bar containing multiple image rollovers,
or if you’re trying to create a smooth animation effect. This is not difficult;
all you need to do is make use of JavaScript’s arrays, as in the example below:

<script language="JavaScript">

function preloader()
{

     // counter
     var i = 0;

     // create object
     imageObj = new Image();

     // set image list
     images = new Array();
     images[0]="image1.jpg"
     images[1]="image2.jpg"
     images[2]="image3.jpg"
     images[3]="image4.jpg"

     // start preloading
     for(i=0; i<=3; i++)
     {
          imageObj.src=images[i];
     }

}

</script>

In the above example, you define a variable i and an Image() object cleverly named imageObj. You then define a new array
called images[], where each array
element stores the source of the image to be preloaded. Finally, you create a
for() loop to cycle through the array and assign each one of them to the
Image() object, thus preloading it into the cache.

The onLoad() event handler

Like many other objects in JavaScript, the Image() object
also comes with some event handlers. The most useful of these is undoubtedly
the onLoad() handler, which is invoked when the image has completed loading.
This handler can be hooked up with a custom function to perform specific tasks
after the image has completed loading. The following example illustrates this
by displaying a “please wait” screen while the image loads, and then
sending the browser to a new URL once it’s finished loading.

<html>
<head>
<script language="JavaScript">

// create an image object
objImage = new Image();
    
// set what happens once the image has loaded objImage.onLoad=imagesLoaded();
    
// preload the image file
objImage.src='images/image1n.gif';

// function invoked on image load
function imagesLoaded()
{   
     document.location.href='index2.html';
}

</script>
</head>

<body>

Please wait, loading images...

</body>
</html>

Of course, you can also create an array of images and loop
over it, preloading each one and keeping track of the number of images loaded
at each stage. Once all the images are loaded, the event handler can be
programmed to take the browser to the next page (or do any other task).

Preloading and Multi-State Menus

Now, how about using all the theory you just learned in an
actual application? This next one is a little piece of code I recently had
occasion to write – a menu bar consisting of buttons (image links), each of
which can be in any one of three states: normal, hover and click. Since the
buttons have multiple states, it is necessary to use image preloading to ensure
that the menu responds quickly to changes in its state. The code in Listing A illustrates this.

The HTML code in Listing A sets up a menu bar consisting of
four buttons, each of which has thee states: normal, hover, and click. The
requirements are as follows:

  • On
    mouse move over a button in normal state, it changes to hover state. On
    mouse out, it goes back to normal state.
  • On
    mouse click on a button, it changes to its click state. It remains in this
    state until another button is clicked.
  • If a
    button is clicked, no other button may be in click state. Other buttons
    can only be in their hover or normal states.
  • Only
    one button may be clicked at a time.
  • Only
    one button can be in hover state at a time.

The first task is to set up arrays holding the images for
each state of the menu. The <img> elements corresponding to these array
elements are also created in the HTML document body, and named sequentially.
Note that array values are indexed starting from 0, while the corresponding
<img> elements are named starting from 1—this gives rise to certain
calculation adjustments in the latter half of the script.

The preloadImages() function takes care of loading all the
images into the cache, so that response time on mouse movement is minimal. A
for() loop is used to iterate over the images created in the first step and
preload each one.

The resetAll() function is a convenient way to reset all the
images to their normal state. This is necessary because, when an item of the
menu is clicked, all other items in the menu must revert to their normal state
before the clicked item can change to its click state.

The setNormal(), setHover() and setClick() functions take
care of changing the source of a particular image (image number passed as
function argument) to its normal, hover, or click state respectively. Since
images which are clicked must remain in that state until another image is
clicked (see rule #2), they are temporarily immune to mouse movements; thus,
the setNormal() and setHover() functions include code to only change a button’s
state if it is not already in its click state.

The above is just one of the many ways in which preloading
can help you speed up the response time of your JavaScript effects. Use the
techniques outlined above in your site, and alter them where needed to fit your
requirements. Good luck!

Subscribe to the Developer Insider Newsletter

From the hottest programming languages to commentary on the Linux OS, get the developer and open source news and tips you need to know. Delivered Tuesdays and Thursdays

Subscribe to the Developer Insider Newsletter

From the hottest programming languages to commentary on the Linux OS, get the developer and open source news and tips you need to know. Delivered Tuesdays and Thursdays