reptile7's JavaScript blog
Monday, March 23, 2009
A Style Sheet
Blog Entry #140

With the aid of CSS and a bit of JavaScript, we can code the display in a much cleaner manner. In particular, CSS positioning will enable us to cash in the tables - all four of them - for a single div element and allow us to replace the presentational attributes that position the images - align, hspace, valign, vspace, and also tables[3]'s cellpadding="2" attribute - with a set of style rules, which can be unobtrusively placed in the document head or in an external file.

So, let's start with our new div element container, to which we will give the identifier div0:

<div id="div0"> images... </div>

Here's the style rule set we'll use for this guy:

#div0 {
width: 481px; height: 416px;
margin-left: auto; margin-right: auto;
border: 1px solid #ffcd38;
background-color: #00695e;
position: relative; }

• Excluding the spacer element borders, the foreground measures exactly 481px by 416px.
• The div element has a default width of "100%", i.e., it spans the entire width of the viewport. Giving div0 a specific width and setting its margin-left and margin-right properties to auto horizontally centers div0 within the viewport. (The div element is like the form element in this respect - see the "Centering a form" section of Blog Entry #93.)
• The original border code can be replaced by a single style declaration, border:1px solid #ffcd38;.
div0 is given tables[2]'s #00695e background color.
div0 is relatively positioned so that it serves as the containing block for positioning its img element children.

To the best of my knowledge, CSS alone cannot be used to vertically center a div or other block-level element within the viewport; however, if we give the body element a body0 identifier, then we can vertically center div0 in the viewport via the cross-browser script below:

<body id="body0">
<!-- The original body element attributes - bgcolor, link, alink, and vlink - are all deprecated; we'll deal with them later. -->
<div id="div0"> images... </div>
<script type="text/javascript">
var outerdiv, vtotal, topoffset;
outerdiv = document.getElementById("div0"); = "416px";
vtotal = document.getElementById("body0").clientHeight;
topoffset = (vtotal - parseInt( / 2; = topoffset;

As shown, this script should be placed (or referenced, for an external script) in the document body and after div0. The script requires support for the DOM getElementById( ) method and clientHeight property, but if you're using a relatively modern browser, then you should be OK. Alternatively, I would certainly understand if you simply gave div0 a margin-top:150px; style and said, "Close enough for government work."

We turn now to's images. (In most cases - excepting starstripe.jpg and map2.gif - the images could be replaced with #PCDATA text, but because the coder(s) went to the trouble of creating these images, why not make use of them?) As detailed in the previous entry, ten img placeholders are spread across tables[2] and tables[3]; per their source order, we will give these placeholders the identifiers img0, img1, ... img9.

Upon stripping out the various presentational attributes - including width and height, which are valid for the img element - and also the name attributes for the img4, img5, and img9 placeholders - the name attribute of the img element is legit in HTML but is deprecated by XHTML 1.0 - the img code can be simplified to:

<img id="img0" src="/images/starstripe.jpg" alt="Welcome to" />
<img id="img1" src="/images/head.gif" alt="The Official US Time" />
<img id="img2" src="/images/pleaseclick.gif" alt="Please Click" />
<img id="img3" src="/images/map2.gif" usemap="#usatimezonemap" alt="Select a time zone" />
<img id="img4" src="/images/labels/zone-00.gif" alt="Zone-00" />
<img id="img5" src="/images/zonenames.gif" usemap="#zonenamesb3c96c19" alt="Time Zone Names" />
<a href="exhibits.html"><img id="img6" src="/images/timeex.gif" alt="Time exhibits" /></a>
<a href="about.html"><img id="img7" src="/images/aboutthisservice.gif" alt="About this service" /></a>
<a href=""><img id="img8" src="/images/privacy.gif" alt="Privacy Statement" /></a>
<span id="span0" onclick="ToggleJava( );"><img id="img9" src="/images/javaoff.gif" alt="Disable/Enable Java" /></span>

The original img9 placeholder is written by a script element and as the child of an anchor element:

<script language="JavaScript1.2"><!--
if(JavaOK){document.write('<a href="#" onclick="ToggleJava(this);"><img src="/images/javaoff.gif" width="186" height="11" align="right" name="IsJava" alt="Disable/Enable Java" border="0" /></a>');}//--></script>

Contra Blog Entry #138, a closer look at the document head's first script element reveals that it contains no commands that set JavaOK, which is initialized with a value of 1, to 0 if the user's browser is not Java-enabled, and thus the "Disable Java Animation" javaoff.gif image is initially loaded into the img9 placeholder regardless of whether the user's browser is Java-enabled or not.

The preceding anchor element is not really a hyperlink, in the sense that its href="#" attribute does not point to a target anchor, but merely serves as a container for a call to the ToggleJava( ) function in the document head's first script element, which, per its identifier, toggles the javaoff.gif and javaon.gif images in the foreground's lower-right-hand corner. I confess that the use of anchor elements as user interface elements gets my goat, so I've replaced img9's anchor element parent with a span0 span element, which can be given a cursor:pointer; style so that it appears to be a link. For its part, the script element is clearly not necessary if its document.write( ) command is triggered by an if statement whose condition is necessarily true. On the other hand, if in the document head JavaOK were toggled to 0 by a not-Java-enabled browser, then a post-img9

document.getElementById("img9").src = JavaOK ? "javaoff.gif" : "javaon.gif";
// The ?: conditional operator is detailed here.

script command would load img9 with either javaoff.gif or javaon.gif as appropriate. Moreover, the ToggleJava( ) function should now be rewritten as:

function ToggleJava( ) {
if (JavaOK) { document.getElementById("img9").src = "javaon.gif"; JavaOK = 0; }
else { document.getElementById("img9").src = "javaoff.gif"; JavaOK = 1; } }
// ToggleJava( ) does not need to be passed this or anything else.

(The setzone( ) function in the document head's second script element should be rewritten analogously - I trust you can do that.)

We're finally ready for some img style rules:

img { border: 0px; }
#img0 { width: 21px; height: 416px; float: left; }
#img1 { width: 438px; height: 30px; position: relative; left: 11px; top: 13px; }
#img2 { width: 181px; height: 10px; position: relative; left: 23px; top: 29px; }
#img3 { width: 413px; height: 204px; position: relative; left: 23px; top: 33px; }
#img4 { width: 404px; height: 18px; position: relative; left: 21px; top: 33px; }
#img5 { width: 413px; height: 20px; position: relative; left: 23px; top: 40px; }
#img6 { width: 112px; height: 13px; position: relative; left: 88px; top: 58px; }
#img7 { width: 147px; height: 13px; position: relative; left: 108px; top: 58px; }
#img8 { width: 208px; height: 11px; position: relative; top: 78px; }
#img9 { width: 186px; height: 11px; position: relative; left: 62px; top: 78px; }
#span0 { cursor: pointer; }

starstripe.jpg must be floated left if the other images are to 'flow' down its right side.
• Unsurprisingly, these rules do not give identical displays with different browsers. The above left declarations are rendered by the browsers on my computer in an impressively consistent manner - this is not true for the top declarations, however. Using the presentational values in the source and with the aid of DigitalColor Meter's "aperture" feature, I initially worked out a set of left and top values that precisely reproduced the display when using Firefox; my original Firefox top values gave a slightly-different-but-acceptable rendering when using Opera but, alas, pushed the img8 and img9 images below div0's bottom edge when using Safari, so I reduced some of them a bit (rather than increasing div0's height) in order to get everything inside div0.
• It is left to you to add declarations for the tables[2] bgndteal.gif and starstripe-bg.jpg background images if you feel they are necessary.

What's left? Oh yeah - the body element's attributes

<body bgcolor="black" link="#cedbd2" alink="#0000aa" vlink="#cedbd2">

can be replaced by the following style rules:

body { background-color: black; }
a:link, a:visited { color: #cedbd2; }
a:active { color: #0000aa; }

However, the source's anchor elements have no textual content - they surround images in all cases - so unless we convert the timeex.gif, aboutthisservice.gif, and privacy.gif images to text, the above a:link, a:visited, and a:active rules serve no purpose and can be thrown out.

We'll take up the merging of the usatimezonemap and zonenamesb3c96c19 map elements in the following entry.


Wednesday, March 18, 2009
Table Dump
Blog Entry #139

We continue today with our analysis of the Web page. As promised at the end of the previous post, we will next
(1) overhaul the presentation and also
(2) merge's usatimezonemap and zonenamesb3c96c19 image maps.

The tables

Last time we noted that the source contains no CSS at all and employs a set of four nested tables to lay out its display. Section 11.1 ("Introduction to tables") of the HTML 4.01 Specification declares, Tables should not be used purely as a means to lay out document content as this may present problems when rendering to non-visual media. Additionally, when used with graphics, these tables may force users to scroll horizontally to view a table designed on a system with a larger display. To minimize these problems, authors should use style sheets to control layout rather than tables. Got it, folks?

Let's first take stock of's tables and what they do before we get rid of them - in the discussion below I will reference these tables per their source order as tables[0], tables[1], tables[2], and tables[3], as would be returned by a var tables = document.getElementsByTagName("table") command.

My 'attribute x is valid/deprecated' statements below can be confirmed by checking the W3C's HTML 4 Index of Attributes.

One more point before we get started: when I refer to, say, the "first cell" of tables[i]'s "first row", I am referring to the first-in-source-order cell of tables[i]'s first-in-source-order row, granted that we could legitimately reference that row and cell with tables[i].rows[0].cells[0] per the DOM rows property/collection of the table object and cells property/collection of the tr object.


<table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%">
<tr align="center" valign="middle"> ... </tr></table>

The width="100%" and height="100%" attributes of the outermost table and the align="center" and valign="middle" attributes of its single tr element child serve to center the display within the viewport (the viewing area of the browser window). These attributes are all W3C-valid except for the table's height attribute; however, the MSDN Library's and Netscape's reference materials both specify that a table element can have a height attribute, so it's safe to assume that this attribute is widely supported.

tables[0]'s only row contains one cell, which holds tables[1].


<table border="0" cellpadding="0" cellspacing="0"> ... </table>

This table uses Netscape's proprietary spacer element to surround the display with a custom 1px solid #ffcd38 border. For example, tables[1]'s first row

<tr><td colspan="3" bgcolor="#ffcd38"><spacer type="block" width="1" height="1"></td></tr>

sets the top border; the left, right, and bottom borders are set in the same way by the first cell of tables[1]'s second row, the third cell of tables[1]'s second row, and tables[1]'s third row, respectively. The tables[1] border code would not be worth discussing in detail even if the spacer element were widely supported, which it is not.

The bgcolor attribute was formerly legit for the table, tr, td/th, and body elements, but is now deprecated for all of these elements.

The second cell of tables[1]'s second row holds tables[2].


<table border="0" cellpadding="0" cellspacing="0" bgcolor="#00695e" background="/images/bgndteal.gif"> ... </table>

The background attribute is not valid for the table element or for the td element (see the next code snippet); it was previously valid for the body element, and only for the body element, but has now been deprecated. However, the MSDN Library (but not Netscape) says that background is OK for the table and td elements, and in practice I find that Firefox, Opera, and Safari all support background for these elements.

In any case, tables[2]'s background attribute is unnecessary given that the bgndteal.gif image is nothing more than a 32px-by-32px #00695e color block; its effect is identical to that of tables[2]'s bgcolor attribute, which at least was valid once upon a time.

Left-side decorationThe first cell of tables[2]'s first row holds the starstripe.jpg image that runs down the left side of the display:

<td width="21" rowspan="3" valign="top" background="/images/starstripe-bg.jpg">
<img height="416" width="21" src="/images/starstripe.jpg" alt="Welcome to" />

There are no transparent regions in the starstripe.jpg image, and thus it might seem pointless to equip starstripe.jpg's td container with a background image. If starstripe.jpg were for some reason not available, however, we would see the stretched-to-fit starstripe-bg.jpg image in its place (at least that's what happens with the browsers on my computer).

The width attribute of the td element has been deprecated.

The second cell of tables[2]'s first row holds the The Official US Time head.gif image:

<img height="30" width="438" src="/images/head.gif" hspace="4" vspace="13" alt="The Official US Time" />

We discussed the hspace and vspace attributes of the img element in the "Image Position" section of Blog Entry #15; both of these attributes are now deprecated.

tables[2]'s second row contains one cell, which holds tables[3].

The one cell of tables[2]'s third and last row holds the Privacy Statement privacy.gif and Disable/Enable Java javaoff.gif or Disable/Enable Java javaon.gif linking images at the bottom of the display (the preceding images and the tables[3] images shown below actually have transparent backgrounds - I've given them tables[2]'s background color to make them easier to see):

<td width="460" align="left" valign="top">
<a href="">
<img src="images/privacy.gif" width="208" height="11" border="0" align="left" alt="Privacy Statement" /></a>
<script language="JavaScript1.2"><!--
if(JavaOK){document.write('<a href="#" onclick="ToggleJava(this);"><img src="/images/javaoff.gif" width="186" height="11" align="right" name="IsJava" alt="Disable/Enable Java" border="0" /></a>');}//--></script></td>

The align and border attributes of the img element are now deprecated, as is the script element's language attribute - we will disentangle the IsJava img placeholder from its surrounding script later.


<table border="0" cellpadding="2" cellspacing="0"> ... </table>

The one cell of tables[3]'s first row holds the Please Click pleaseclick.gif image that appears directly above the mapped map2.gif image.

The map2.gif image (more precisely, its img placeholder) and its associated usatimezonemap map element are both contained by the single td element of tables[3]'s second tr element. Strangely, the map2.gif image and the usatimezonemap map are also marked up with font and b elements:

<font face="Arial,Helvetica,Geneva,Swiss,SunSans-Regular" color="#3c3c98"><b> ...image plus map... </b></font>

Interestingly, there are no content model violations here: the font element, although deprecated, can have a b element child according to the X/HTML Transitional DTDs, whereas the b element can have img and map element children according to the X/HTML Strict DTDs. Having said this, the above font and b elements have absolutely no effect on the map2.gif image* and usatimezonemap map and should be removed.

*I have subsequently discovered that Firefox and Safari do apply the font and/or b formatting to the img alt="Select a time zone" text when the map2.gif image is not available, but this is non-standard behavior that should not be counted on. We could reliably format the Select a time zone string if we were to recast the img element as an object element, but this is a can of worms that we're not going to open - not now, anyway.

The one cell of tables[3]'s third row holds the zonename img placeholder under the map2.gif image.

The zonenames.gif image and its associated zonenamesb3c96c19 map are both contained by the single td element of tables[3]'s fourth tr element.

The one cell of tables[3]'s fifth and last row holds the Time exhibits timeex.gif and About this service aboutthisservice.gif linking images:

<td align="center">
<a href="exhibits.html"><img border="0" height="13" width="112" src="/images/timeex.gif" hspace="10" vspace="20" alt="Time exhibits" /></a>
<a href="about.html"><img border="0" height="13" width="147" src="/images/aboutthisservice.gif" hspace="10" vspace="20" alt="About this service" /></a>

Whew - what a mess, huh? It's time to clean this baby up, and we'll do that in the next post.


Friday, March 06, 2009
This Time Is Your Time
Blog Entry #138

(August 2016 Update: The usatimezonemap and zonenamesb3c96c19 <map>s at the site were discarded in the course of a redesign in February or March 2014.)

To wrap up our discussion of image maps spanning Blog Entries #121, #122, #123, and #124, we will in this post deconstruct a real-world example, specifically, the image maps appearing at, the home page of the U.S. Government's "Official U.S. Time" Web site. Here's a screen shot of the foreground:

The (non-background) display, when using Firefox

Depending on your browser's support for Netscape's proprietary spacer element, you may or may not see the display's marigold-ish (#ffcd38) border, e.g., Firefox (which I was using when I captured the display) shows it but Opera does not.

Notwithstanding its appearance, the display contains no #PCDATA text but is composed entirely of images. Two of these images are mapped:

(1) The map2.gif image

U.S. time zone regions

is associated with a usatimezonemap map comprising sixteen area elements.

(2) The zonenames.gif image

U.S. time zone regions

is associated with a zonenamesb3c96c19 map comprising nine area elements.

Before we get started, I should mention that the source is 'distinguished' by a total absence of CSS and the use of four nested tables for layout purposes - one suspects Sir Tim would 'have an aneurysm' upon looking at this code - we'll sort out this situation after we go through the usatimezonemap and zonenamesb3c96c19 maps.

<map name="usatimezonemap"> ... </map>

In this section, I will reference the usatimezonemap map area elements per their source order as areas[0], areas[1], areas[2], etc. (As the area object is a type of link object, their actual object references would be document.links[0], document.links[1], document.links[2], ...)

Subchapter IX of Chapter 6 of Title 15 of the United States Code defines nine U.S. standard time zones, which are duly delineated in the map2.gif image by the usatimezonemap map; from east to west:
(1) areas[13] encompasses Puerto Rico and also Saint Thomas in the U.S. Virgin Islands, which observe Atlantic standard time (UTC-4) throughout the year;
(2) areas[15] traces the Eastern Time Zone (UTC-5 during standard time);
(3) areas[12] traces the Central Time Zone (UTC-6 during standard time);
(4) areas[11] traces the Mountain Time Zone (UTC-7 during standard time), excepting Arizona - vide infra;
(5) areas[10] traces the Pacific Time Zone (UTC-8 during standard time);
(6) areas[9] frames the Alaska Time Zone (UTC-9 during standard time);
(7) areas[14] encompasses Hawaii, which observes Hawaii-Aleutian standard time (UTC-10) throughout the year;
(8) areas[8] encompasses American Samoa, which observes Samoa standard time (UTC-11) throughout the year; and
(9) areas[3] encompasses Guam and the Northern Mariana Islands, which observe Chamorro standard time (UTC+10) throughout the year.

Here's what's going on with the other seven usatimezonemap area elements:
areas[5] traces the Arizonan sector of the Navajo Nation, which observes mountain standard time or mountain daylight time à la the rest of the Mountain Time Zone mapped by areas[11].
areas[6] encompasses the rest of Arizona, including the Hopi Nation enclave, which observes mountain standard time throughout the year.
areas[7] encompasses the western part of the Aleutian Islands that lies in the Hawaii-Aleutian Time Zone; unlike Hawaii, this region observes DST.
areas[2], areas[1], and areas[4] respectively encompass the Republic of the Marshall Islands, the Federated States of Micronesia, and the Republic of Palau, independent nations that nevertheless have entered into "Compacts of Free Association" with the U.S.; these regions respectively observe UTC+12, UTC+11, and UTC+9 throughout the year.
• Curiously, the Kwajalein atoll, which is part of the Republic of the Marshall Islands and accordingly observes UTC+12 throughout the year, is given its own area, areas[0].

Shape-wise, the non-contiguous U.S. time zone regions are all circumscribed by shape="rect" (rectangular) area elements. Let's take a look at the Alaska Time Zone area, areas[9]:

<area shape="rect" coords="47,-2,101,72" onmouseover="setzone('08');" onmouseout="setzone('00');" onclick="TimeHREF(this);" href="/timezone.cgi?Alaska/d/-9" alt="Alaska Time Zone" />

Let's first get a minor issue out of the way. With a top-y coords value of -2, the areas[9] area actually extends beyond the top edge of the map2.gif image, and thus the top 54px-by-2px part of the area is 'inactive', i.e., does not respond to mouseover, mouseout, and click events. But in practical terms, does it matter whether the top-y value is set to -2 or 0? No.

The onmouseover and onmouseout event handlers both call the setzone( ) function in the document head's second script element:

<script name="function def" language=JavaScript1.1><!--
function setzone(zonenum) {
document.images['zonename'].src = '/images/labels/zone-' + zonenum + '.gif'; }

<!-- In case you were wondering, name is not a valid (nor even a deprecated) attribute for the script element. -->

Directly below the map2.gif image is a zonename img placeholder for holding images specifying labels and other information for the various time zones - "Atlantic time zone - Puerto Rico & Virgin Islands, no Daylight Saving", "Eastern time zone", etc.; the zonename replacement images are themselves preloaded by the document head's third (name="preload labels") script element. The zonename placeholder is initially loaded with a transparent zone-00.gif image:

<img name="zonename" width="404" height="18" src="/images/labels/zone-00.gif" alt="Zone-00" />

Mousing over a usatimezonemap area passes to the setzone( ) function a corresponding image label number (01, 02, ... 16) that is given the identifier zonenum and then concatenated with /images/labels/zone- and .gif to give the image label URL, whose assignment to the zonename src property loads the image label into the zonename placeholder. In short for our Alaska example, mousing over the Alaskan mainland sends '08'* to setzone( ), which consequently displays /images/labels/zone-08.gif

Alaska time zone

below the map2.gif image. Conversely, mousing away from a usatimezonemap area returns the zone-00.gif image to the zonename placeholder by sending '00'* to setzone( ).

*Image label numbers with a leading 0 must be stringified before they are passed to setzone( ); otherwise, JavaScript will cast off the 0 and the image label (whose src value includes the 0) will not load. Image label numbers beginning with a 1 need not be stringified.

The onclick event handler calls the TimeHREF( ) function in the document head's first (name="TimeHREF function def.") script element:
function TimeHREF(oldlink) {
if (JavaOK) { oldlink.href = oldlink.href + '/java'; }
else { oldlink.href = oldlink.href; } }
The script code that precedes TimeHREF( ), which I am not going to go through, sets a JavaOK variable to 1 or 0 depending on whether the user's browser is Java-enabled or not, respectively. Clicking a usatimezonemap area passes to TimeHREF( ) this, a self-reference to the area, which is given the identifier oldlink. If JavaOK is 1 and thus evaluates to true as an if condition, then /java is appended to the area's href value and the user is taken to a 'Java' page with a dynamic time display and a map that shows where in the world it is day or night. If JavaOK is 0, then the user is taken to a 'non-Java' page with a static time display and without the world map. The TimeHREF( ) else oldlink.href self-assignment statement is in fact unnecessary, because the usatimezonemap areas are already source anchors by virtue of being part of an image map.

The contiguous U.S. time zone regions are of course all mapped by shape="poly" (polygonal, incorrectly specified in the source as shape="polygon") area elements, e.g.,

<area shape="poly" coords="132,12, 130,29, 116,55, 114,74, 124,111, 140,127, 152,127, 155,116, 155,104, 161,104, 167,68, 153,64, 153,59, 148,58, 151,45, 157,46, 162,40, 169,42, 172,37, 166,28, 170,19, 142,11, 140,16" onmouseover="setzone('07');" onmouseout="setzone('00');" onclick="TimeHREF(this);" href="/timezone.cgi?Pacific/d/-8" alt="Pacific Time Zone" />

maps the Pacific Time Zone.

Finally, I have sent the following email message to the email contact address on the "About this Service" page:
Hello, NIST -

I have an HTML/image map question for you regarding the "usatimezonemap" map element that appears in the source. How did you determine the coordinates (coords values) of the area elements of this map? I would guess that you used a specialized image map-creating program to do this - if so, which one?
There's been no response as of this writing. The movable crosshairs method of Blog Entry #124 could certainly be used to delimit usatimezonemap's rectangular regions, and maybe even its polygonal regions in a crude way but not with precision.

<map name="zonenamesb3c96c19"> ... </map>

The zonenamesb3c96c19 map (how's that for a descriptive name?) divides the zonenames.gif image into nine rectangular areas that respectively encompass the time zones listed in the image, e.g.,

<area shape="rect" coords="292,0,335,19" onclick="TimeHREF(this);" href="/timezone.cgi?Eastern/d/-5" alt="Eastern Time" />

surrounds the image's "Eastern" text. Clicking a time zone takes the user to the corresponding 'Java' or 'non-Java' time page described above. Mousing over a time zone does not display a corresponding label in the zonename placeholder, however.

Vis-à-vis the usatimezonemap map, the zonenamesb3c96c19 map leaves out everything to the 'west' of (across the Date Line from) Samoa, has single areas for the Hawaii-Aleutian and Mountain Time Zones, and strangely concludes with a "UTC" area (well, "strangely" in the sense that there are no U.S. commonwealths/territories/associated states in the UTC±0 time zone region).

But you may be thinking, "Why use an image map here at all, as opposed to, more conventionally, a series of anchor elements? Better yet, why not combine the usatimezonemap and zonenamesb3c96c19 maps via reformulating the usatimezonemap map in terms of anchor elements?" OK, OK, we'll get to that, plus a trade-in of those layout tables for a style sheet, in the following entry.


Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)