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 element is the most commonly used tag for representing graphical content in an HTML document (the latest HTML specifications add a
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 tag to specify alternate text. Hereโs an example:
<IMG SRC="../myimage.gif" ALT="This is the myimage.gif graphic">
Images created with the 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 fortags. Otherwise, you may get inconsistent results and/or crashing! This caution applies to any
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 thetag 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 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 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 tag, use the 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 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 tag references the map name, which is #control (note the hash before the name). Other attributes provided with the
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 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 8n#define count_height 16nstatic 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 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.


