[Chapter 16] 16.5 Image Replacement Example
Author: David Flanagan
Date: Fri Aug 29 11:02:20 1997

#

| Chapter 16 Special Effects with Images |

## 16.5 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

#### 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 ALIGN="absmiddle">');
        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"
           onClick="alert(tb1.checked + '\n' + tb2.checked + '\n' + tb3.checked)">
    <INPUT TYPE="button" VALUE="Reset Buttons"
           onClick="if (tb1.checked) tb1.click();
                    if (tb2.checked) tb2.click();
                    if (tb3.checked) tb3.click();">
    </FORM>

Other Image Properties |  | Other Image Techniques