Events and Rollovers

Reading: Thau Chapter 4 to page 61.

Rollovers Overview

We've all seen the rollover mania that grips cyberspace. It's manifested in simple, “click here” rollovers such as the ones at the Music Department. Notice that as you roll over the menu on the left, the links get highlighted. There are also more elaborate double rollovers such as the ones at the Quantitative Reasoning Program. Not only are the links changing color, but some explanatory text appears on the right. (The rollovers on the Wellesley College home page are different and much more complex. We will not discuss them in this course.)

Rollovers may seem complicated but they are actually rather simple. Typically, you have two images, such as the following (for a web site booking tickets to the north pole):

You display the default image as usual and the browser watches the mouse's position. You ask the browser to execute some JavaScript (JS) when the mouse rolls over the image. When that happens, your JS code swaps images (in this case from the image with the green background to the one with the red background).

To understand this in more detail, we have to distinguish among:

In a sense, the IMG tag creates an image object which functions like a picture frame. A rollover replaces the contents of the picture frame with another picture.

Events

An event is some action that takes place. A browser can detect some events that might be of interest to the author of a web page. For example, the browser can determine when a user:

There are common JavaScript events defined on most HTML tags. We will see and use some of those events later in this course. When these events take place, they trigger a JavaScript event. The programmer (that would be you) has the option of telling Javascript what to do when an event arises by writing event handlers using attributes such as:

An event handler is some JavaScript code that is the value of one of several special tag attributes, like the ones named above. As you can see, the name of the attribute corresponds to the event that is being handled. When that event occurs, the JavaScript code in the event handler is executed. Here's an example that just does a simple alert:

take the polar express

<IMG SRC="polar-green.png"
     ALT="take the polar express"
     onClick="alert('thanks for clicking!');"> 

Implementing Simple Rollovers

In order to implement a rollover, the event handler needs to refer to the tag that will have its image data modified. Usually, of course, that image is the same one that has the event-handler attribute, but not always (as we will see). In that special case, we can use a special JavaScript variable named this.

take the polar express

<IMG SRC         = "polar-green.png"
     ALT         = "house icon"
     onMouseOver = "this.src = 'polar-red.png';"
     onMouseOut  = "this.src = 'polar-green.png';">

Let's talk about the code in the onMouseOver event handler. It's traditional to use the up-and-down capitalization for that and similar event handlers, since it's easier to see the words it comprises. However, as you know, HTML is not case-sensitive, so you can specify the name of the attribute in all-lower or all-upper case.

The value of the attribute is all the stuff enclosed by double quotes, and the value of the attribute is automatically treated as JavaScript code, without having to specify SCRIPT tags.

In this case, the JavaScript code is an assignment statement that changes the value of this.src. The this variable may seem magical: its value automatically changes from place to place and it always means “the current object.” In this instance, it means the image object created by the IMG tag that contains the event handler code; it's as if the SRC attribute of the tag is changing. As you know, the SRC attribute determines which image file is displayed, so changing the SRC attribute causes a new image to be downloaded and shown.

The other event handler is almost identical. It re-loads the original image data when the mouse is no longer over the image.

In JavaScript, as in English, the word “this” depends on context. In the example above, this means the JavaScript image object created by the IMG tag. To do more complex rollovers, we'll have to be able to refer to them. However, we can't just say “that” because the browser should respond “which?”

Implementing More Complex Rollovers

To refer to any image other than this one, we have to give it a name or an identifier. To do that, we can use the id attribute. (Some old code still uses the name attribute, but name has been deprecated and id is preferred. You can use id to label pretty much any HTML tag.)

Let's start with using id for just a simple rollover. The following code is equivalent to the rollover in the previous section:

take the polar express

<IMG SRC         = "polar-green.png"
     ID          = "pic1"
     ALT         = "house icon"
     onMouseOver = "document.getElementById('pic1').src='polar-red.png';"
     onMouseOut  = "document.getElementById('pic1').src='polar-green.png';">

Notice that the id is just pic1, which is fine for this example, but in general it's better to label the image in a way that is meaningful to you as the web author, so that you can remember what role the image plays. For example, label it infobox or caption or whatever.

Now, if we want some other image to change when we roll over this one, all we need to do is use id to label the one we want and use the label in our JavaScript code. Here's an example:

take the polar express take the polar express

<IMG SRC         = "polar-green.png"
     ID          = "picleft"
     ALT         = "take the polar express"
     onMouseOver = "document.getElementById('picright').src = 'polar-red.png';"
     onMouseOut  = "document.getElementById('picright').src = 'polar-green.png';">
<IMG SRC         = "polar-green.png"
     ID          = "picright"
     ALT         = "take the polar express"
     onMouseOver = "document.getElementById('picleft').src = 'polar-red.png';"
     onMouseOut  = "document.getElementById('picleft').src = 'polar-green.png';">

To do a double rollover, you just have to change the SRC of more than one IMG. For example:

take the polar express take the polar express

<IMG SRC         = "polar-green.png"
     ID          = "left2"
     ALT         = "take the polar express"
     onMouseOver = "document.getElementById('left2').src = 'polar-red.png';
                    document.getElementById('right2').src = 'polar-red.png';"
     onMouseOut  = "document.getElementById('left2').src = 'polar-green.png';
                    document.getElementById('right2').src = 'polar-green.png';">
<IMG SRC         = "polar-green.png"
     ID          = "right2"
     ALT         = "take the polar express"
     onMouseOver = "document.getElementById('left2').src = 'polar-red.png';
                    document.getElementById('right2').src = 'polar-red.png';"
     onMouseOut  = "document.getElementById('left2').src = 'polar-green.png';
                    document.getElementById('right2').src = 'polar-green.png';">

Notice that the code in the event handler can get rather long. There are many ways to abbreviate the code, which we will learn when we get to functions, but even without that, length is not a problem. The browser doesn't care how long a line is, so you could just let it stretch, even to a hundred characters or so. Long lines, however, are difficult for people to read, so putting in line breaks is a good idea. The browser doesn't object to line breaks within an event handler (as illustrated above). Typically, you would break the line at a logical location within the JavaScript code, such as after the semi-colon. The only restriction is you must not break the line within a JavaScript string literal, such as within either of the filenames (eg, at the hyphen or the .png above).

You may sometimes see JavaScript code in which

document.getElementById('identifier').src

is written more succinctly as

identifier.src

Unfortunately, while this works in many browsers, it does not work in all browsers. For this reason, we recommend that you do not use this abbreviation. For example, in Spring, 2008, the following works in Firefox and IE, but not in Safari:

take the polar express take the polar express

<IMG SRC         = "polar-green.png"
     ID          = "left3"
     ALT         = "take the polar express"
     onMouseOver = "left3.src = 'polar-red.png';
                    right3.src = 'polar-red.png';"
     onMouseOut  = "left3.src = 'polar-green.png';
                    right3.src = 'polar-green.png';">
<IMG SRC         = "polar-green.png"
     ID          = "right3"
     ALT         = "take the polar express"
     onMouseOver = "left3.src = 'polar-red.png';
                    right3.src = 'polar-red.png';"
     onMouseOut  = "left3.src = 'polar-green.png';
                    right3.src = 'polar-green.png';">
Exercise 1

This link has a nice example of image swap behavior. Try to figure out how it was done, then check the code.

Rollover Links

The rollovers above swap images very nicely, but they're not active links, which is the most common use of a rollover. A rollover link is nice because the user gets visual feedback that the mouse is positioned correctly before they click.

To make an image into a hyperlink, all you need to do is wrap it with the anchor (A) tag:

take the polar express

<A HREF = "http://www.imdb.com/title/tt0338348/"><IMG
     SRC         = "polar-green.png"
     ALT         ="take the polar express"
     onMouseOver = "this.src='polar-red.png';"
     onMouseOut  = "this.src='polar-green.png';"></A>

Notice that the code is not indented as nicely as we've argued that it should be: in particular, the IMG tag is at the end of a line, instead of being neatly indented under the A tag. In this case, aesthetics has to give way to function, because if we indent the IMG tag below the A tag, the line break will end up causing blue-underlined whitespace in the browser, which will look ugly. Whenever you are using the A tag, remember that everything between the start tag and the end tag will end up with blue underlining (or whatever your style sheet specifies), and so you have to be careful, even with “invisible” stuff like spaces and line breaks. It is always safe, however, to break lines between attributes of a tag, as we did between IMG tag and its SRC attribute.

Exercise 2

This link extends the previous exercise to do hyperlinks. Try to figure out how it was done, then check the code.

Why use the A tag at all? Why not have a JavaScript event handler that responds to a mouse click by changing the browser's location to the desired page? The code would look like the following:

take the polar express

<IMG SRC         = "polar-green.png"
     ALT         = "take the polar express"
     onClick     = "window.location = 'http://www.imdb.com/title/tt0338348/';"
     onMouseOver = "this.src = 'polar-red.png';"
     onMouseOut  = "this.src = 'polar-green.png';">

There is a certain aesthetic beauty to code like this, at least to computer scientists, because of its simplicity. However, we should eschew this simplicity and prefer the more complex code that uses the A tag. The reason is that some older browsers don't support event handlers or JavaScript, and some users disable JavaScript in their preferences, or are using screen-reading software that doesn't handle these events in the same way. In short, if the JavaScript doesn't work, for any reason, you still want your web page to work. This is what is known as graceful degradation.

Borderless Image Links

One aesthetic disadvantage of the image link that we recommend (the one using the A tag) is the blue border that some browsers will display. The blue used in links is a strong hint to the user that something is a link, so the blue border is generally a good thing unless you're quite certain that your user understands that this image is a link. But, in many cases, you are certain that is so (for example, navigation bars make the intention clear), and you want to get rid of the blue border.

To eliminate the the border, you use CSS:

take the polar express

<A HREF = "http://www.imdb.com/title/tt0338348/"><IMG
     STYLE       = "border: none"
     SRC         = "polar-green.png"
     ALT         = "take the polar express"
     onMouseOver = "this.src = 'polar-red.png';"
     onMouseOut  = "this.src = 'polar-green.png';"></A>
Exercise 3

This link extends the previous exercise to do borderless rollovers . Try to figure out how it was done, then check the code.

Preloading

One problem that can arise with rollovers is that when the mouse rolls over the image for the first time, the second image has to be downloaded across the network, and that can cause a noticeable delay. When that happens, the users don't get the visual feedback they expect, and confusion can ensue, or at least annoyance.

Browsers automatically cache anything they download. “To cache” (pronounced “cash”) means to keep a copy in memory or on the local disk. The browser cache makes references to previously loaded images pretty fast. Thus, the solution is to make sure that the second image is downloaded before it is needed. This is called preloading.

We do this by downloading rollover images when the page loads, but we keep them in “offstage” (undisplayed) objects, rather than in IMG tags — they won't be visible until they are needed. The preloading code would be put in the HEAD of the document, to make sure it has occurred before any possible rollover. If we wanted to preload the red Polar Express image, we could do the following:

<script type="text/JavaScript">
    var polar_red = new Image();
    polar_red.src = "polar-red.png";
</script>

Here's what's going on. The first line of code creates an object to hold image data. This is an Image object, not surprisingly. The object is placed in a variable called polar_red. It's not important what we name the variable; we could have called it picture or just p. The second line of code assigns a URL to the SRC attribute of the object, thereby loading the image data across the network and into the object. At this point, the image data is cached and any uses of the polar-red.png file will load very quickly.

If we had several images to preload, we would use a different variable for each one. For example:

<script type="text/JavaScript">
    var nav1 = new Image();
    nav1.src = "home-button-over.png";
    var nav2 = new Image();
    nav2.src = "history-over.png";
    var nav3 = new Image();
    nav3.src = "eboard-over.png";
    ...
</script>

Slide Shows

You could use extend the rollover idea to a slide show. Each time you click on the following image, the image changes. It cycles through six possibilities.

one face of a six-sided die

Almost all the work is done in the event handler, which increments the slide number, using the remainder operator (the percent sign) to start over again when we reach 6. The code is as follows:

  <IMG ID      = "the_slide"
       SRC     = "../../Images/die1.gif"
       HEIGHT  = "70"
       WIDTH   = "70"
       onClick = "slideNumber = (slideNumber%6) + 1;
                  document.getElementById('the_slide').src 
                    = '../../Images/die' + slideNumber + '.gif';">

The only piece that is missing is some code to initialize the value of slideNumber. That is done by the following simple SCRIPT:

<script type="text/JavaScript">
var slideNumber = 1;
</script>

The slide-show code is organized into two pieces: there's the initialization script that goes in the BODY of the page, and the event handler that advances the slide. Note that we don't put the line of code that initializes the slideNumber variable in the event handler. Why not? Because if we did so, the slide number would start over at one every time we clicked on the image, and so we would only see the first slide.

Note that it's not important that you click on the image to advance the slide show. You could also have a button to do that.

Numbering and Naming Image Files

One trick that helped the dice slide show was that the names of the image files had a number in them, so we could mathematically generate a number and thereby generate a filename. What can you do if your image files don't have that convenient pattern?

Caveat

We've used the alert() function in some of our examples because it's obvious when it runs. You can use alert() anywhere in your JavaScript code. However, you can't use document.write() in an event handler. Why? Not because of any rule in JavaScript, but because it doesn't make sense.

You use document.write() within the SCRIPT tag as part of creating the BODY of a web page, but an event handler executes after the web has been written. There's no more left to write, so the document.write() either has no effect or causes the browser to hang, thinking that you're writing a new web page. So, remember,

Only use document.write() within the SCRIPT tag, not as part of an event handler.

Summary

Optional reading: Thau Chapter 4.

© Computer Science 110 Staff
This work is licensed under a Creative Commons License
Date Modified: Sunday, 16-Mar-2008 17:50:17 EDT