Using JavaScript and graphics

The easy way to make your images dynamic

Internet purists consider the World Wide Web primarily a vehicle for disseminating information. Much of that information is in text form, which can be easily rendered by any Web browser. But even from the beginning days of the Web, graphics have played an important role in enhancing the basic text page. These days, it's not unusual to see Web sites that are ninety percent graphics. These sites may not conform to the strict concept of dissemination of information, but some of them certainly are attractive.

Most of us strive for a balance between text and graphics in our Web pages. The graphics serve to enhance the appearance and readability of the page. Typical uses for graphics include banners, ads from sponsoring companies, and colored bullets to highlight important pieces of text.

The JavaScript scripting language can be used to enhance the graphics you put on your Web pages. JavaScript can be used to dynamically control the graphic content of the page. For example, you can display one background for your page in the morning and another in the afternoon. And at night you can use a star field background. Or, you can use JavaScript to create the display for digital clocks, hit counters, bar graphs, and more.

This month's column details several ways you can use JavaScript and graphics. But one notable topic is missing from this discussion: using JavaScript for animation. That subject is deserving of its own column, coming soon.

Understanding the HTML image element

The <IMG> element is the most commonly used tag for representing graphical content in an HTML document (the latest HTML specifications add a <FIG> element, but it is not yet supported by Netscape and most other browsers). For the uninitiated, the syntax of the basic <IMG> tag is:

<IMG SRC="url">

where "url" is a properly constructed URL for the image file. The URL can be absolute or relative. Remember that not all browsers are equipped to display graphics. Therefore, it's advisable to include "alternate text" for the image for those who are image-challenged. Use the ALT attribute inside the <IMG> tag to specify alternate text. Here's an example:

<IMG SRC="../myimage.gif" ALT="This is the myimage.gif graphic">

Images created with the <IMG> tag are considered "inline" because they are treated just like text characters. That means you can intersperse images with text, and the browser will take care of making sure everything flows properly.

Most images are taller than the text that surrounds them, however. The normal behavior of most browsers is to place the bottom of the image flush with the bottom of the text that surrounds it. You can change this behavior if you want a different alignment. The most common alignment choices, understood by all browsers that display images, are:

  • bottom -- Aligns the text to the bottom of the image. This is the default.
  • middle -- Aligns the text to the middle of the image.
  • top -- Aligns the text to the top of the image.

You may use only one alignment at a time. The syntax is:

<IMG SRC="myimage.gif" ALIGN="alignment">

Browsers ordinarily display images in their "natural size." If an image is 100 pixels by 100 pixels, for example, that's how big it is when rendered on the browser's screen. But with Netscape you can change the size of the image if you want it smaller or larger by using the WIDTH and HEIGHT attributes. An advantage of these attributes is that, when used, the browser creates an empty box for the image, then fills the box with the image as the entire page loads. This cues users that a graphic is expected at that spot.

  • Specifying just the width or height changes the size of the image in proportion. For example, specifying WIDTH="100" sizes a square image to a height and width of 100 pixels. If the original image is not square, it is sized in relative proportion. For instance, if the original image is 400 pixels wide by 100 pixels high, changing the width to 100 pixels reduces the image to 25 pixels high.

  • Specifying both the width and height lets you change the proportion of the image in any way you like. For example, you can transform that 400-by-100-pixel image to 120 by 120, 75 by 90, or anything else.

For example:

<IMG SRC="myimage.gif" ALT="Alternate text1" HEIGHT="100" WIDTH="100">
Caution: When combined with JavaScript you should always provide the HEIGHT and WIDTH attributes for <IMG> tags. Otherwise, you may get inconsistent results and/or crashing! This caution applies to any <IMG> tag that appears in the same document that contains JavaScript code.

Combining images with JavaScript

JavaScript can be used to enhance images used in HTML documents. For instance, you can use JavaScript to dynamically create a page using images selected by a conditional test expression, such as the time of day.

In fact, the JavaScript digital clock application, which uses JavaScript and an assortment of GIF images, is one of the most popular on the Web. The clock.html example uses JavaScript to display the current time, using big green LED digits. Each digit is an individual GIF, strung together by JavaScript to form the face of a digital clock.

I used digit GIFs provided by Russ Walsh; Russ kindly allows his GIFs to be used freely on Web pages, as long as proper credit is given. You can use any digits you wish for your clock, but you must provide a separate GIF file for each numeral and separate files each for the colon and am/pm indicators. Change the clock.html code to reference the digit files you wish to use.

Note: It is important that you provide the absolute URL to the images you use. Otherwise Netscape will not display the graphics. The clock.html example uses a function (pathOnly) to extract the current path of the document. The script therefore expects to find the images in the same path as the document. Alternatively, you can hard-code the absolute URL if you place the images elsewhere, or you may use the <BASE HREF> tag at the start of the document to explicitly tell Netscape the base URL you want to use.

JavaScript digital clock

<HTML> <HEAD> <TITLE>JavaScript Digital Clock</TITLE> <SCRIPT LANGUAGE="JavaScript"> var Temp; setClock(); function setClock() { var OpenImg = '<IMG SRC="'+pathOnly(location.href)+'dg' var CloseImg='.gif" HEIGHT=21 WIDTH=16>' Temp = "" now = new Date(); var CurHour = now.getHours(); var CurMinute = now.getMinutes(); now = null; if (CurHour >= 12) { CurHour = CurHour - 12; Ampm = "pm"; } else Ampm = "am"; if (CurHour == 0) CurHour = "12" if (CurMinute < 10) CurMinute = "0" + CurMinute else CurMinute = "" + CurMinute

CurHour = "" + CurHour; for (Count = 0; Count < CurHour.length; Count++) { Temp += OpenImg + CurHour.substring (Count, Count+1) + CloseImg } Temp += OpenImg + "c" + '.gif" HEIGHT=21 WIDTH=9>' for (Count = 0; Count < CurMinute.length; Count++) { Temp += OpenImg + CurMinute.substring (Count, Count+1) + CloseImg } Temp += OpenImg + Ampm + CloseImg }

function pathOnly (InString) { LastSlash=InString.lastIndexOf ('/', InString.length-1) OutString=InString.substring (0, LastSlash+1) return (OutString); } </SCRIPT> <BODY> <H1 ALIGN=CENTER>The JavaScript Clock</H1> The current time is: <SCRIPT>document.write(Temp); </SCRIPT> </BODY> </HTML>

Using JavaScript with client-side image maps

If you're lucky enough to have control over the server that contains your published Web pages, you've probably dabbled with server-side image maps. These are images that have been "dissected" into smaller chunks; as the user clicks on each chunk, the server responds to a different action.

The downside to server-side image maps is that you need a CGI program running on the server to handle the click requests. Not everyone has CGI access. Client-side image maps change that: The "intelligence" for dissecting the image and directing the user to the proper link -- based on the area of the image that was clicked -- is built into the browser. Netscape Navigator (version 2.0 and later) is one of many browsers that now support this standard.

Netscape takes the process a step further, however, letting you integrate client-side image maps with JavaScript. In an ordinary client-side image map, you are limited merely to linking to another page. If you wish, you can "link" to a JavaScript function and give your image maps even more intelligence. For instance, you might create a control panel that only lets users successfully click on an image button if some piece of information -- say a user name -- has been provided.

The anatomy of a client-side image map

Two new HTML tags are used to create client-side image maps. They are the <MAP> tag, which defines the map structure, and one or more <AREA> tags, which define the clickable areas within the image. To create the image map, define a <MAP> tag and give the mapping a name. The syntax is:

<MAP NAME="mapname>

You can use most any name for the map, but it should contain only alphabetical and numeric characters. The exception is the underscore, but avoid using an underscore for the first character. Next, define one or more <AREA> tags that define the areas of your image. The tag takes the syntax:

<AREA SHAPE="rect" COORDS="x1,y1,x2,yx" HREF="url">

After the last <AREA> tag, use the </MAP> tag to denote the end of the mapping.

The last item is the image you want to use, with a reference to the area map you've previously defined. Use the standard <IMG> tag, with a new USEMAP attribute. For the USEMAP attribute, provide the name of the map. Here's an example:

<MAP NAME="control">
<AREA SHAPE=RECT COORDS="0,0,57,31" HREF="/index.html">
<AREA SHAPE=RECT COORDS="58,0,255,31" HREF="toc.html">
<AREA SHAPE=RECT COORDS="256,0,313,31" HREF="backpage.html">
</MAP>
<IMG SRC="control.gif" USEMAP="#control" BORDER=0 HEIGHT=34 WIDTH=314>

This map uses an image named control.gif. The <IMG> tag references the map name, which is #control (note the hash before the name). Other attributes provided with the <IMG> tag are no border (BORDER=0), and the width and height of the image. When your users click on the back arrow (which is the first area defined), they are sent to the index.html page. Conversely, if they click on the contents "button" (the second area defined), they are taken to a page called toc.html. And if they click on the forward arrow, they are taken to a page called backpage.html.

Adding JavaScript to image map control

JavaScript can be used to extend the functionality of client-side image maps. For added flexibility provide the name of a JavaScript function for the HREF in the <AREA> tag. Instead of jumping to some page, your JavaScript code is executed in which you can do anything you want. The trick: Use the JavaScript: protocol for the URL, and follow it with the name of the function you wish to use.

For example, suppose you want users to go back only one page in the history list when they click on the back arrow. You can use the window.history.go(-1) method to jump back one page in the user's history list. You can either provide this entire function after the JavaScript: protocol, or call a user-defined function that contains this instruction. Here are both methods:

<AREA SHAPE=RECT COORDS="0,0,57,31" HREF="JavaScript:window.history.go(-1)">

or ...

<AREA SHAPE=RECT COORDS="0,0,57,31" HREF="goBack()">

... and elsewhere in the document:

<SCRIPT>
function goBack() {
    window.history.go (-1);
}
</SCRIPT>

Personally, I prefer the latter method, because I often need to provide a number of JavaScript functions that I want performed. But, you can use whatever method you like best and which best fits the situation.

Following is a working example of using client-side image maps with JavaScript. The buttons display an alert box to show you that the JavaScript: URL is indeed working. The forward and back buttons also work -- assuming you have pages forward and backward in your history list. If the history list is empty (you have loaded the document into a new window, for example) then the current page remains.

Client-side image map example

<HTML> <HEAD> <TITLE>Client Side Image Map Example</TITLE> <SCRIPT LANGUAGE="JavaScript"> function goBack() { alert ("Back"); window.history.go (-1); }

function goForward() { alert ("Forward"); window.history.go (1); }

function toc() { alert ("Table of contents"); } </SCRIPT> </HEAD> <BODY> <CENTER> <MAP NAME="control"> <AREA SHAPE=RECT COORDS="0,0,57,31" HREF="JavaScript:goBack()"> <AREA SHAPE=RECT COORDS="58,0,255,31" HREF="JavaScript:toc()"> <AREA SHAPE=RECT COORDS="256,0,313,31" HREF="JavaScript:goForward()"> </MAP> <IMG SRC="control.gif" USEMAP="#control" BORDER=0 HEIGHT=34 WIDTH=314> </BODY> </HTML>

Creating graphics on-the-fly with JavaScript

If you're not an X Window user, you probably haven't heard of the XBM graphics format. This format is supported by Netscape and many other browsers. It's a simple format that offers only black-and-white rendition and is intended to be used in X Window applications for basic icons. It's occasionally used in Web pages to produce icons and hit counter digits, and for various other graphic images.

What makes the XBM format particularly interesting to us "JavaScripters" is that you can create the XBM image in JavaScript and display it in Netscape. This allows you to create and manipulate simple images in real time, using nothing more than JavaScript. The images are limited to black-and-white only.

Understanding the XBM format

The XBM format is really a C-language variable assignment. The XBM file format begins with two define statements that indicate the width and height, in pixels, of the image. The width is usually, but not always, stated in multiples of eight. The height can be any value.

Next comes the bit representation of the image. This consists of one or more values, specified in hexadecimal format. Each value defines an area of up to eight pixels wide by one pixel in height. For instance, the following XBM file produces a small 8-by-1-pixel line:

#define text_width 8
#define text_height 1
static unsigned char text_bits[] = {0xff};

Note that you can make the line shorter by specifying a smaller width. But you cannot make a line longer without adding more hex values. You can do this by separating each value with a comma, like this:

#define text_width 16
#define text_height 1
static unsigned char text_bits[] = {0xff,0xff};

This defines a 16-by-1-pixel line. Each 0xff value is used for eight pixels of the line. Of course, an XBM graphic of just a very short line isn't too useful. Most of the time you will want to add height to the image. This is done by increasing the height value, and by adding more hex values in the list. Netscape will read the image going from left to right, top to bottom. You can better visualize the arrangement of the values if you put them in "spreadsheet" column/row format. Each column represents eight bits of width; each row represents one bit of height.

The following produces a 16 by 8 bar. Notice the formatting of the 0xff values. This is purely for easy readability. It helps you visualize that there are two 8-pixel columns (for a total of 16 pixels), and eight rows.

#define text_width 16
#define text_height 8
static unsigned char text_bits[] = {
    0xff,0xff,
    0xff,0xff,
    0xff,0xff,
    0xff,0xff,
    0xff,0xff,
    0xff,0xff,
    0xff,0xff,
    0xff,0xff};

In all of the above examples the graphic is composed of all-black line segments. You can use other hex values to produce line segments with black and white bits. White (actually, the absence of black) is represented by a 0 bit; black is represented by a 1 bit. Put eight bits together and you get a value from 0 to 255. The hex value 0xff is decimal 255, or binary 11111111. All those ones create the all-black line. Conversely, 0x00 will make an all-white line, as it's decimal 0, or binary 00000000.

To make an image different, number values are used to represent the bit pattern desired. The pattern 1000001, which is decimal 128 (or hex 0x81), produces a line with only one bit turned on at each end. The middle is white. The bits of the digit are organized right to left with respect to how the bits appear on the screen. Remember this when calculating the bits to make a picture.

A practical XBM example

One practical use for XBM graphics is a hit counter. JavaScript provides all the images for each number. By itself, JavaScript is not capable of storing the number of times someone visits your Web site; this requires a CGI program. For the following example, though, we'll create a "fake" hit counter that can be used instead. This hit counter makes up an absurdly large number and displays that as the number of people who have visited the page. It's intended to serve as comic relief; of course you should not actually represent the number as valid, because some people take "hit counters" pretty seriously.

The random hit-counter script shown below uses a randomizing function based on the Park-Miller random number generator algorithm. A specific random number routine is used instead of JavaScript's Math.random property because in Netscape 2.0 the random property only functions when using the Unix platform. Here is the complete random_hit.html example.

Random hit count

<HTML> <HEAD> <TITLE>Random Hit Count</TITLE> <SCRIPT> function setHits() { RandNum = new randomNumberGenerator(); val = RandNum.next() + "" val = val.substring (2, 12) PicSize = "HEIGHT=16 WIDTH=8 ALIGN='absmiddle'>"; Digit = new Array(); Head = "#define count_width 8\n#define count_height 16\nstatic char count_bits[] = {" Digit[0]=Head+"0xff,0xff,0xff,0xc3,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0xc3,0xff,0xff,0xff};" Digit[1]=Head+"0xff,0xff,0xff,0xcf,0xc7,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xc7,0xff,0xff,0xff};" Digit[2]=Head+"0xff,0xff,0xff,0xc3,0x99,0x9f,0x9f,0xcf,0xe7,0xf3,0xf9,0xf9,0x81,0xff,0xff,0xff};" Digit[3]=Head+"0xff,0xff,0xff,0xc3,0x99,0x9f,0x9f,0xc7,0x9f,0x9f,0x9f,0x99,0xc3,0xff,0xff,0xff};" Digit[4]=Head+"0xff,0xff,0xff,0xcf,0xcf,0xc7,0xc7,0xcb,0xcb,0xcd,0x81,0xcf,0x87,0xff,0xff,0xff};" Digit[5]=Head+"0xff,0xff,0xff,0x81,0xf9,0xf9,0xf9,0xc1,0x9f,0x9f,0x9f,0x99,0xc3,0xff,0xff,0xff};" Digit[6]=Head+"0xff,0xff,0xff,0xc7,0xf3,0xf9,0xf9,0xc1,0x99,0x99,0x99,0x99,0xc3,0xff,0xff,0xff};" Digit[7]=Head+"0xff,0xff,0xff,0x81,0x99,0x9f,0x9f,0xcf,0xcf,0xe7,0xe7,0xf3,0xf3,0xff,0xff,0xff};" Digit[8]=Head+"0xff,0xff,0xff,0xc3,0x99,0x99,0x99,0xc3,0x99,0x99,0x99,0x99,0xc3,0xff,0xff,0xff};" Digit[9]=Head+"0xff,0xff,0xff,0xc3,0x99,0x99,0x99,0x99,0x83,0x9f,0x9f,0xcf,0xe3,0xff,0xff,0xff};" for (Count = 0; Count < val.length; Count++) { dig= val.substring (Count, Count+1) setDigit (dig, PicSize) } }

function setDigit (Dig, PicSize) { // this function to overcome a bug if (Dig=="0") { document.write ("<IMG SRC='JavaScript:Digit[0]'" + PicSize) } else if (Dig=="1") { document.write ("<IMG SRC='JavaScript:Digit[1]'" + PicSize) } else if (Dig=="2") { document.write ("<IMG SRC='JavaScript:Digit[2]'" + PicSize) } else if (Dig=="3") { document.write ("<IMG SRC='JavaScript:Digit[3]'" + PicSize) } else if (Dig=="4") { document.write ("<IMG SRC='JavaScript:Digit[4]'" + PicSize) } else if (Dig=="5") { document.write ("<IMG SRC='JavaScript:Digit[5]'" + PicSize) } else if (Dig=="6") { document.write ("<IMG SRC='JavaScript:Digit[6]'" + PicSize) } else if (Dig=="7") { document.write ("<IMG SRC='JavaScript:Digit[7]'" + PicSize) } else if (Dig=="8") { document.write ("<IMG SRC='JavaScript:Digit[8]'" + PicSize) } else if (Dig=="9") { document.write ("<IMG SRC='JavaScript:Digit[9]'" + PicSize) } }

function nextRandomNumber () { var Hi = this.seed / this.Q; var Lo = this.seed % this.Q; var Test = this.A * Lo - this.R * Hi; if (Test > 0) this.seed = Test else this.seed = Test + this.M; return (this.seed * this.oneOverM); }

function randomNumberGenerator() { var D = new Date(); this.seed = 2345678901 + (D.getSeconds() * 0xFFFFFF) + (D.getMinutes() * 0xFFFF); this.A = 48271; this.M = 2147483647; this.Q = this.M / this.A; this.R = this.M % this.A; this.oneOverM = 1.0 / this.M; this.next = nextRandomNumber; } </SCRIPT> </HEAD> <BODY> A whopping <SCRIPT>setHits();</SCRIPT> people have visited this page since tea-time yesterday. Click Reload to see the number magically change. </BODY> </HTML>

Using JavaScript for on-the-fly image sizing

As mentioned earlier in this column, Netscape will scale images to fit the HEIGHT and WIDTH attributes you have defined for them. One common application of this resizing capability is using a small GIF image to create any length of bar you want. Suppose the original GIF file is 16 by 16 pixels. An <IMG> tag like the following will "stretch" it to 16 by 200 pixels:

<IMG SRC="small_box.gif" HEIGHT=16 WIDTH=200>

As long as the image is a solid color, it will not degrade when you resize it. The image can even contain stripes of other colors, but the colors must be horizontal. The stripes stretch with the rest of the image, and it looks like one long bar.

Now here's where JavaScript comes in. Instead of hard coding the width and/or height of the image, have JavaScript do it for you. You can use this technique to create horizontal bar charts or to design special effects for your page. Here's an example of using JavaScript to make a bar chart. The function stretches a small solid GIF image (the actual size is unimportant; the smaller the better for transmission speed) to the width specified.

JavaScript graphic sizing example

<HTML> <HEAD> <TITLE>JavaScript Graphic Sizing Example</TITLE> <SCRIPT> makeBar ("250", "Cat"); makeBar ("175", "Dog"); makeBar ("80", "Rat");

function makeBar (Width, Text) { var GifName = pathOnly (location.href) + "blu.gif"; var Height = 12; var Temp = "<IMG SRC='" + GifName + "' HEIGHT='" + Height + "' WIDTH=" + Width + "' ALIGN=baseline> " + Text + "<P>"; document.write (Temp); }

function pathOnly (InString) { LastSlash=InString.lastIndexOf ('/', InString.length-1); OutString=InString.substring (0, LastSlash+1); return (OutString); } </SCRIPT> </HEAD> <BODYv This is body text. </BODY> </HTML>

You can readily modify the script to use a different GIF image and to increase or decrease the height of the bars. I have the bars set at 12 pixels high.

Conclusion

Graphics can enhance any Web page, no matter what its content. Combining JavaScript with graphics is a quick and simple way to give your Web page a dynamic element and will help set it apart from the rest. You can use JavaScript to select the graphic to use, to size a graphic, and even to create the graphic, using the convenient XBM graphic format.

Gordon McComb is an author, consultant, and lecturer. He has written 50 books and over a thousand magazine articles during his 20 years as a professional writer. More than a million copies of his books are in print. Gordon also writes a weekly syndicated newspaper column on computers, reaching several million readers worldwide. Gordon's latest book is The JavaScript Sourcebook>, out this month from Wiley Computer Publishing.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more