reptile7's JavaScript blog
Tuesday, March 22, 2016
Your id, Señor Clock
Blog Entry #363

Our tour of the Java Goodies Calendars, Clocks, and Calculators sector next brings us to a "DHTML Clock" script, which we'll check over in today's entry. Authored by Paul Swonger in April 1998, the DHTML Clock script creates and displays a running digital clock. You can see the clock at the dhtmlclock.html page; the dhtmlclock.txt Grab the Script page is still available.

As regards running the script, Joe warns: MSIE 4.0 Required - I'll address this in due course, but for the time being, let's just get right to the code, shall we?

A home for our clock

The DHTML Clock clock is housed in a styled, id="Clock" <div>.

<div id="Clock" align="center"
style="font-family:Verdana;font-size:40;color:#0000ff;"> </div>

• The align attribute of the div element is obsoleted by HTML5: use a text-align:center; styling to horizontally center the clock in the div.
• CSS lengths lacking unit identifiers are illegal: specify the font-size:40; declaration as font-size:40px;.

Time starting materials

The clock is set in motion by a tick( ) function that fires when the script document has finished loading.

<script type="text/javascript">
function tick( ) { ... }
window.onload = tick;

The tick( ) function body begins by declaring eight variables.

var today, intHours, intMinutes, intSeconds, hours, minutes, seconds, ap;

Next, tick( ) creates a new Date( ) object, which is assigned to today; subsequent statements get the today hour, minute, and second, and assign them to intHours, intMinutes, and intSeconds, respectively.

today = new Date( );
intHours = today.getHours( );
intMinutes = today.getMinutes( );
intSeconds = today.getSeconds( );

Display components

The DHTML Clock clock is a 12-hour clock whose display includes an hours part, a minutes part, a seconds part, and an ap a.m./p.m.-type indicator.

hours and ap

With the intHours hour in hand, tick( ) determines the hours and ap parts of the clock via the following if...else if...else if...else series of statements:

if (intHours == 0) { hours = "12:"; ap = "Midnight"; } else if (intHours < 12) { hours = intHours + ":"; ap = "A.M."; } else if (intHours == 12) { hours = "12:"; ap = "Noon"; } else { intHours = intHours - 12; hours = intHours + ":"; ap = "P.M."; }

Somewhat strangely, the ap indicator will read Midnight for the entire 12 a.m. to 1 a.m. hour and Noon for the entire 12 p.m. to 1 p.m. hour - don't know 'bout you, but I don't like that* - here's how I'd handle all of this:

ap = intHours < 12 ? "a.m." : "p.m.";
if (intHours == 0) hours = "12:";
else if (intHours < 13) hours = intHours + ":";
else hours = (intHours - 12) + ":";

• Re the ap assignment, the < operator takes precedence over the conditional operator so there's no need to parenthesize the intHours < 12 condition.

*As it happens, there is in fact a "noonhour" word for the 12 p.m. to 1 p.m. hour, but I'm not gonna use that, either.

minutes and seconds

The minutes and seconds parts of the clock are set with:

if (intMinutes < 10) { minutes = "0" + intMinutes + ":"; }
else { minutes = intMinutes + ":"; }
if (intSeconds < 10) { seconds = "0" + intSeconds + " "; }
else { seconds = intSeconds + " "; }

I would compact these assignments with the conditional operator as well:

minutes = intMinutes < 10 ? "0" + intMinutes + ":" : intMinutes + ":";
seconds = intSeconds < 10 ? "0" + intSeconds + " " : intSeconds + " ";

Going live

The hours, minutes, seconds, and ap strings are concatenated

var timeString = hours + minutes + seconds + ap;

and the resulting timeString string is subsequently loaded into the Clock div.

Clock.innerHTML = timeString;

A setTimeout( ) command updates the clock every 100 milliseconds.

window.setTimeout("tick( );", 100);

The current versions of IE and Netscape in April 1998 were IE 4.x and Netscape 4.x, respectively. Unlike IE 4.x, Netscape 4.x does not support the use of standalone ids as object references - on my computer, Communicator 4.61 throws a Clock is not defined JavaScript Error when it hits the Clock.innerHTML = timeString; line - so that's what the MSIE 4.0 Required business is all about. Microsoft would today recommend that we use the getElementById( ) method to locate the Clock div - see the Note below this example.

document.getElementById("Clock").innerHTML = timeString;

One more point before moving on: Mozilla would today recommend that we use the

window.setTimeout(tick, 100);

setTimeout( ) syntax to update the clock.

A Netscape port

Netscape 4.x doesn't support the innerHTML property, either; indeed, classical JavaScript (JS 1.0-1.3, before the client-side stuff was shipped off to the DOM) doesn't have any properties for setting the text of a textual element - the closest we get is the text property of the anchor/link objects, which is read-only for Netscape 4.x (but is actually writable for some modern browsers, including Firefox). This doesn't mean that we can't adapt the DHTML Clock script for Netscape 4.x, however; here's how:

(1) Give the Clock div a relative positioning so as to layerize it.

body { background-color: white; }
#Clock, #Clock2 { text-align: center; font-family: Verdana; font-size: 40px; color: blue; position: relative; }

<div id="Clock"></div>

(2-4) Via the document property of the layer object and the write( ) method of the document object, write an id='Clock2' div containing the timeString string to the Clock layer. After that, close( )** the document.Clock.document. Wrap the document.Clock.document commands in an if (document.layers) { ... } conditional to keep non-Netscape 4.x browsers at bay.

if (document.layers) { document.Clock.document.write("<div id='Clock2'>" + timeString + "<\/div>"); document.Clock.document.close( ); } else Clock.innerHTML = timeString;

**It's not necessary to begin with a corresponding open( ) call, but the close( ) operation is definitely necessary to ensure that only one Clock2 div is written in the Clock layer.

Sensibly, Netscape abandoned the layer interface and brought innerHTML on board for Netscape 6.

Old-school dynamicity

The classical way of outputting a JavaScript digital clock is by loading it into an <input type="text">.

document.clockForm.clockInput.value = timeString;

<form name="clockForm" action="">
<input name="clockInput">

We previously worked with an input digital clock in HTML Goodies' JavaScript Script Tips #25-28, which we discussed in Blog Entry #61.

Does an input clock also count as a DHTML clock? I would certainly say so, given that we are dynamically (the "D" stands for "Dynamic", right?) changing the value attribute of an HTML input element, good enough. Relatedly, I find that Firefox, Google Chrome, and Opera all apply the #Clock styles (vide supra) to an input clock display. BTW, the image-based clock discussed in Blog Entry #359 is a DHTML clock too.


We may or may not get into some trigonometry in the following entry.

Comments: Post a Comment

<< Home

Powered by Blogger

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