Image Replacement Example

Because image replacement is such a versatile technique we will end our discussion of the Image object with an extended example. Example 16-3 defines a ToggleButton class that uses image replacement to simulate a graphical checkbox. Because this class uses images that we provide, we can use bolder graphics than those plain-old graphics used by the standard HTML Checkbox object. Figure 16-1 shows how these toggle button graphics could appear on a web page. This is a complex, real-world example, and is worth studying carefully.

Figure 16-1: ToggleButtons implemented with image replacement

[Graphic: Figure 16-1]

Example 16-3: Implementing a ToggleButton with Image Replacement

<SCRIPT LANGUAGE="JavaScript1.1"> // This is the constructor function for our new ToggleButton class. // Calling it creates a ToggleButton object and outputs the required // <A> and <IMG> tags into the specified document at the current location.  // Therefore, don't call it for the current document from an event handler. // Arguments: // document: the Document object the buttons will be created in. // checked: a Boolean that says whether the button is initially checked. // label: an optional string that specifies text to appear after the button. // onclick: an optional function to be called when the toggle button is // clicked. It will be passed a Boolean indicating the new // state of the button. You can also pass a string, which will // be converted to a function which is passed a Boolean argument // named "state". function ToggleButton(document, checked, label, onclick) {
 // first time called, document will be false. Ignore this call. if (document == null) return; // The first time we are called (and only the first time) we have // to do some special stuff. First, now that the prototype object // is created, we can set up our methods.  // Second, we've got to load the images that we'll be using. // Doing this will get the images in the cache for when we need them. if (!ToggleButton.prototype.over) {
 // Initialize the prototype object to create our methods. ToggleButton.prototype.over = _ToggleButton_over; ToggleButton.prototype.out = _ToggleButton_out; ToggleButton.prototype.click = _ToggleButton_click; // Now create an array of image objects, and assign URLs to them. // The URLs of the images are configurable, and are stored in an // array property of this constructor function itself. They will be // initialized below. Because of a bug in Navigator, we've got // to maintain references to these images, so we store the array // in a property of the constructor rather than using a local variable. ToggleButton.images = new Array(4); for(var i = 0; i < 4; i++) {
 ToggleButton.images[i] = new Image(ToggleButton.width, ToggleButton.height); ToggleButton.images[i].src = ToggleButton.imagenames[i];
}
} // Save some of the arguments we were passed. this.document = document; this.checked = checked; // Remember that the mouse is not currently on top of us. this.highlighted = false; // Save the onclick argument to be called when the button is clicked. // If it is not already a function, attempt to convert it // to a function that is passed a single argument, named state. this.onclick = onclick; if (typeof this.onclick == "string") this.onclick = new Function("state", this.onclick); // Figure out what entry in the document.images[] array the images // for this checkbox will be stored at. var index = document.images.length; // Now output the HTML code for this checkbox. Use <A> and <IMG> tags. // The event handlers we output here are confusing, but crucial to the // operation of this class. The "_tb" property is defined below, as // are the over(), out(), and click() methods. document.write('&nbsp;<A HREF ="" ' + 'onMouseOver="document.images[' + index + ']._tb.over();return true;" '+ 'onMouseOut="document.images[' + index + ']._tb.out()" '+ 'onClick="document.images[' + index + ']._tb.click();
return false;">'); document.write('<IMG src="' + togglebutton.imagenames[this.checked+0] +'"'+ ' WIDTH=" + togglebutton.width + " HEIGHT=" + togglebutton.height + " BORDER=0 HSPACE=0 VSPACE=0 >'); if (label) document.write(label); document.write('</A>'); // Now that we've output the <IMG> tag, save a reference to the // Image object that it created in the ToggleButton object. this.image = document.images[index]; // And also make a link in the other direction: from the Image object // to this ToggleButton object. Do this by defining a "_tb" property // in the Image object. this.image._tb = this;
}
// This becomes the over() method. function _ToggleButton_over() {
 // Change the image, and remember that we're highlighted. this.image.src = ToggleButton.imagenames[this.checked + 2]; this.highlighted = true;
}
// This becomes the out() method. function _ToggleButton_out() {
 // Change the image, and remember that we're not highlighted. this.image.src = ToggleButton.imagenames[this.checked + 0]; this.highlighted = false;
}
// This becomes the click() method. function _ToggleButton_click() {
 // Toggle the state of the button, change the image, and call the // onclick method, if it was specified for this ToggleButton. this.checked = !this.checked; this.image.src = ToggleButton.imagenames[this.checked+this.highlighted*2]; if (this.onclick) this.onclick(this.checked);
}
// Initialize static class properties that describe the checkbox images. These // are just defaults. Programs can override them by assigning new values. // But the should only be overridden *before* any ToggleButtons are created. ToggleButton.imagenames = new Array(4); // create an array ToggleButton.imagenames[0] = "togglebutton0.gif"; // the unchecked box ToggleButton.imagenames[1] = "togglebutton1.gif"; // the box with a check mark ToggleButton.imagenames[2] = "togglebutton2.gif"; // unchecked but highlighted ToggleButton.imagenames[3] = "togglebutton3.gif"; // checked and highlighted ToggleButton.width = ToggleButton.height = 25; // size of all images </SCRIPT>
<!-- Here's how we might use the ToggleButton class. --> Optional extras:<BR>
<SCRIPT LANGUAGE="JavaScript1.1"> // Create the buttons var tb1 = new ToggleButton(document, true, "28.8K Modem<BR>"); var tb2 = new ToggleButton(document, false, "Laser Printer<BR>"); var tb3 = new ToggleButton(document, false, "Tape Backup Unit<BR>"); </SCRIPT>
<!-- Here's how we can use the ToggleButton objects from event handlers. -->
<FORM>
<INPUT TYPE="button" VALUE="Report Button States" >
<INPUT TYPE="button" VALUE="Reset Buttons" >
</FORM>