PART I JAVAWHAT? THE WHERE, WHY, AND HOW OF JAVASCRIPT
Chapter 19 Getting data into JavaScript 327
Working with images in JavaScript
After completing this chapter, you will be able to
■
■ Understand both new and old methods for creating rollover or hover images using JavaScript.
■
■ Preload images using JavaScript.
■
■ Create a slide show of images.
■
■ Enhance image maps using JavaScript.
Working with image hovers
The term image rollover refers to changing an image when a user moves the mouse over it, to provide visual feedback about the mouse location on the screen. The more common term for rollover is now hover. Although this technique has been largely supplanted by Cascading Style Sheets–based solu- tions, because this is a JavaScript book, I show you only the JavaScript methods for creating hovers.
You can still benefit from learning how JavaScript-based hovers work, even if you use Cascading Style Sheets to create them.
Hovers take advantage of certain events that relate to mouse movement on a computer, primarily mouseover and mouseout.
a simple hover
Placing mouseover and mouseout event handlers within the <IMG> tag creates the hover effect. The handlers display images that differ only slightly from each other. The following HTML creates a hover effect using the old DOM event handling model:
onmouseout="window.document.img_home.src='home_default.png'">
</body>
</html>
The important parts of this <IMG> tag are its name (img_home); the mouseover and mouseout events; and code that runs when those events fire. The tag’s name allows you to access the image easily through the window.document object call, and the mouseover and mouseout events make the action happen. When viewed in a web browser, the preceding code loads the image called home _ default.png, as shown in Figure 14-1.
FIGURE 14-1 The initial load of the default graphic through a webpage.
When you move the mouse over the graphic, the mouseover event fires, and the following code changes the source of the graphic to home_over.png:
window.document.img_home.src='home_over.png'
While the mouse is over the graphic, the image changes to the one shown in Figure 14-2, in which the direction of the gradient is reversed.
FIGURE 14-2 The graphic changes when the mouse moves over it.
When the mouse moves away from the graphic, the image changes back to home_default.png, thanks to the mouseout event, which calls this JavaScript:
window.document.img_home.src='home_default.png'
Modern hovers with jQuery
A newer method for creating hovers with JavaScript is to use the Document Object Model (DOM) and the load event of the window object. (The load event of the window object was covered in Chapter 13,
“JavaScript events and the browser.”) With the DOM in use, when the page calls the load event, the load handler calls a JavaScript function that populates the mouseover and mouseout events for all the images in the document.
Using Modern hovers
Although using the DOM with the load event is called “modern hovers,” and it does accomplish the goal of unobtrusive scripting, the technique can be somewhat cumbersome. Using the DOM with the load event can also be slightly less compatible when used across various brows- ers and platforms.
The pragmatist in me wants to say that using the example that was just shown is acceptable, especially if your webpage has just a few graphics, but I feel like I’m teaching a bad practice if I tell you to use it. Therefore, I leave it up to you to choose which approach works best for you. If you have a lot of graphics that require the hover effect, you’ll find that this second, more cur- rent approach, which uses a generic function to handle the hover events, is easier to maintain.
Example 14-1 works exactly the same as the example in the preceding section, but uses different code. (See listing14-1.html in the sample code in the companion content.)
EXAMPLE 14-1 A different approach to hover
<!doctype html>
<html>
<head>
<title>hover example</title>
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
});
});
</script>
</body>
</html>
The preceding code, coupled with a load event handler, creates a simple mouseover effect. The jQuery hover() function gets called during the load event to make sure that all of the images are ready. The hover() function takes two arguments, the function to handle the mouseover event and the function to handle the mouseout event. With that in mind, the code loads two anonymous functions, both named function(), which merely change the src attribute of the image.
Even though the functionality is the same as the preceding example, the code in Example 14-1 is not very portable. This is fine if all you have is one image and its accompanying hover state, as in this example. However, if you have a page full of images, as is more likely the case in the real world, this code breaks. Therefore, the script needs improving.
This example code does show the basic theory of how to implement hovers. Retrieve the image with its ID and set the hover() function to use specific functions, which in turn should set the src attri- bute to the name of the image to use for that event. Now it’s your turn to make the function more portable so that you can use it in the future.
This exercise uses six images (three graphics, each of which has a default and a hover image), but the code is written to support any number of images. I included the images used in this exercise with the downloadable code for this book, so you don’t have to reinvent the wheel just to make this exer- cise work.
Creating portable hovers
1. Using Microsoft Visual Studio, Eclipse, or another editor, edit the file hover.html in the
Chapter14\hover sample files folder in the companion content. This folder includes six images:
home_default.png, home_over.png, about_default.png, about_over.png, blog_default.png, and blog_over.png. The file names containing _default are the images to display initially; the file names containing _over are the hover images.
2. Within the webpage, add the boldface code shown here into hover.html (to replace the TODO comments):
<!doctype html>
<html>
<head>
<title>hover exercise</title>
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
</head>
<body>
<img id="home" name="img_home" src="home_default.png" alt="Home" /><br />
<img id="blog" name="img_blog" src="blog_default.png" alt="Blog" /><br />
<img id="about" name="img_about" src="about_default.png" alt="About" /><br />
<script type="text/javascript">
$(window).load(function () { $('img').hover(function() {
$(this).attr("src",$(this).attr("id") + "_over.png");
}, function() {
$(this).attr("src",$(this).attr("id") + "_default.png");
});
});
</script>
</body>
</html>
3. View the page in a browser. You should see a page similar to the following screen shot. If you run into problems, make sure that each of the images and jQuery are located in the current directory, because that’s where the <IMG> tag is looking for them.
4. Move the mouse over the buttons one at a time. Each image should change to its correspond- ing hover image. Here’s what the screen looks like when the mouse is over the Blog graphic:
a closer look at the exercise
The portable hover exercise you performed in the preceding section shows a better hover implemen- tation. Like the example that preceded it, the code used in the exercise creates a function and then calls it using the window.load event. Unlike the preceding example, the exercise’s code gathers all the images using the jQuery $(‘img’) selector and then adds a mouseover and a mouseout event handler to each through the hover() function. This code, as shown in the exercise, is as follows:
$('img').hover(function() {
$(this).attr("src",$(this).attr("id") + "_over.png");
}, function() {
$(this).attr("src",$(this).attr("id") + "_default.png");
});
});
This code still changes the src attribute of the image, now by using the $(this) selector. A notable change is that the id attribute is retrieved and used as the name of the src attribute.
Making sure that the file names and the <IMG> tags’ id attributes match is important. For exam- ple, here’s one of the <IMG> tags from the example:
<p><img id="about" name="img_about" src="about_default.png" alt="About"></p>
Because these file names are generated in the event handlers based on the element IDs, the file names for the About graphic must be about_default.png and about_over.png. Similarly, the image file names must be home_default.png and home_over.png for the Home graphic, and so on.
note Of course, you could use an entirely different naming convention—the important issue is that the naming convention you use for the hover graphics files must match what you coded in the JavaScript.
The hover() function shown in the exercise gathers all the images on the page. For real-world pages, that means there’s a good chance that the images collection list contains graphics and images that don’t have a hover action. Therefore, a further improvement on this script is to create a condi- tional to check whether the graphic should be a hover. One of the simplest solutions is to refine the naming convention for hover graphics to include the word hover in the <IMG> tag’s name attribute, like this:
<p><img id="about" name="hover_about" src="about_default.png" alt="About"></p>
The new code iteration uses a jQuery selector to examine whether the name attribute starts with the word hover. If it does, the code continues the hover action; otherwise, it simply returns.
Figure 14-3 shows an example page with four images, three of which have hover behavior.
FIGURE 14-3 An example with only certain images being hover capable.
When you move the mouse over any of the top three images on the page, the hover image loads. However, because the name of the last image doesn’t contain the word hover, it doesn’t get a mouseover or mouseout event handler. Here’s the full code (but note that the script still needs a little more improvement before it’s done). This code is included in the companion content sample files in as hover-jquery.html.
<!doctype html>
<html>
<head>
<title>hover regular expression</title>
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
</head>
<body>
<img id="home" name="hover_home" src="home_default.png" alt="Home" /><br />
<img id="blog" name="hover_blog" src="blog_default.png" alt="Blog" /><br />
<img id="about" name="hover_about" src="about_default.png" alt="About" /><br />
<img id="logo" name="logo" src="logo.png" alt="Logo" /><br />
<script type="text/javascript">
$(window).load(function () {
$('img[name^=hover]').hover(function() {
$(this).attr("src",$(this).attr("id") + "_over.png");
}, function() {
$(this).attr("src",$(this).attr("id") + "_default.png");
});
});
</script>
</body>
Preloading images
You might have noticed an issue when you first began working with the hover examples in the previ- ous section. When the hover image is first loaded, it can take a second to render. This delay occurs because the image has to be loaded through the web server and network before it is displayed in the browser.
This isn’t a huge issue; it’s more of an annoyance when using the application across a super-fast network connection. However, the lag is noticeable in real-world web applications, especially for users who might be running on slow dial-up connections or through a mobile device. Luckily, you can pre- load the images using a little JavaScript. Preloading stores the images in the browser’s cache so that they are available almost instantly when a visitor moves the mouse over an image.
The basic premise behind preloading an image is to create an image object and then set the src() property on that object, pointing to the image you’d like to preload. What you do with that object after you set the src() property isn’t important. JavaScript makes the call to load the image asynchro- nously, so the rest of the script continues to execute while the image loads in the background.
The asynchronous nature of preloading does have an important implication when you’re working with multiple images: you must create a new image object for each image that you need to preload.
If you have a batch of hover images, as is often the case, each image needs its own object and its own src() property set.
The final version of the hover code incorporates preloading. Example 14-2 shows the hover script and the HTML page for context; the preload elements of the code are shown in boldface. This code is included in the companion content sample files in the hover\preload folder.
EXAMPLE 14-2 Preloading images with jQuery
<!doctype html>
<html>
<head>
<title>hover regular expression</title>
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
</head>
<body>
<img id="home" name="hover_home" src="home_default.png" alt="Home" /><br />
<img id="blog" name="hover_blog" src="blog_default.png" alt="Blog" /><br />
<img id="about" name="hover_about" src="about_default.png" alt="About" /><br />
<img id="logo" name="logo" src="logo.png" alt="Logo" /><br />
<script type="text/javascript">
$(window).load(function () {
$('img[name^=hover]').each(function() {
var image = $('<img />').attr('src',$(this).attr("id") + "_over.png");
});
$('img[name^=hover]').hover(function() {
$(this).attr("src",$(this).attr("id") + "_over.png");
}, function() {
$(this).attr("src",$(this).attr("id") + "_default.png");
});
});
</script>
</body>
</html>
Example 14-3 shows the same preload script, written with the use of the ehandler.js script and JavaScript, for environments where jQuery is not available. This code is found in the preload-js folder in Chapter 14’s companion content.
EXAMPLE 14-3 Preloading and hover
<!doctype html>
<html>
<head>
<title>Rollover</title>
<script type="text/javascript" src="ehandler.js"></script>
<script type="text/javascript">
function rollover() {
var images = document.getElementsByTagName("img");
var imgLength = images.length;
var preLoad = [];
for (var i = 0; i < imgLength; i++) { if (images[i].id.match(/rollover/)) { preLoad[i] = new Image();
preLoad[i].src = images[i].id + "_over.png";
EHandler.add(images[i],"mouseover", function(i) { return function() {
images[i].src = images[i].id + "_over.png";
};
}(i));
</script>
</head>
<body>
<p><img id="rollover_home" name="img_home" src="rollover_home_default.png"
alt="Home"></p>
<p><img id="rollover_about" name="img_about" src="rollover_about_default.png"
alt="About"></p>
<p><img id="rollover_blog" name="img_blog" src="rollover_blog_default.png"
alt="Blog"></p>
<p><img id="logo" name="img_logo" src="logo.png" alt="Braingia Logo"></p>
<script type="text/javascript">
var bodyEl = document.getElementsByTagName("body")[0];
EHandler.add(bodyEl,"load", function() { rollover(); });
</script>
</body>
</html>
To review, the code from Example 14-3 uses the image tag naming convention to construct the image names, so all the same warnings about synchronizing the id attributes with your JavaScript code discussed earlier in this chapter apply.
Working with slide shows
You can use JavaScript to create a “slide show” effect in which one image is swapped for another in the browser window. For the purposes of this chapter, you build a visitor-controlled slide show—that is, one in which the visitor controls the image changes by clicking buttons to move forward and backward through them, as opposed to a timed slide show, in which the application swaps the images automatically after a certain interval.
Creating a slide show
You can implement slide show functionality through JavaScript in several ways. One approach might be to use a for loop to iterate through the images, but this section illustrates another, more straight- forward slide show variation.
Most slide shows are rather simple in design, although I’ve seen some overly complex ones.
Example 14-4, which I explain, shows the slide show in its first version, with just forward capability.
The first versions of the slide show use simple JavaScript along with the ehandler.js script. A later ver- sion in this chapter will utilize jQuery.
EXAMPLE 14-4 A basic (but slightly incomplete) slide show
<!doctype html>
<html>
<head>
<title>Slideshow</title>
<script type="text/javascript" src="ehandler.js"></script>
<script type="text/javascript">
var images = ['home_default.png','about_default.png','blog_default.png','logo.
png'];
function nextImage() {
var img = document.getElementById("slideimage");
var imgname = img.name.split("_");
var index = imgname[1];
if (index == images.length - 1) { index = 0;
} else { index++;
}
img.src = images[index];
img.name = "image_" + index;
}
</script>
</head>
<body>
<p><img id="slideimage" name="image_0" src="home_default.png" alt="Home"></p>
<form name="slideform">
<input type="button" id="nextbtn" value="Next">
</form>
<script type="text/javascript">
var nextBtn = document.getElementById("nextbtn");
EHandler.add(nextBtn,"click",function() { nextImage(); });
</script>
</body>
</html>
I might as well discuss the HTML portion of this code, because it’s short. Here it is:
<p><img id="slideimage" name="image_0" src="home_default.png" alt="Home"></p>
<form name="slideform">
<input type="button" id="nextbtn" value="Next">
</form>
This HTML code displays an image and sets its ID and name to specific values that will be used