reptile7's JavaScript blog
Tuesday, August 01, 2017
 
Tic Tic Tic It Holds On
Blog Entry #377

Today's post marks our return to the Calendars, Clocks, and Calculators (CCC) sector of the Java Goodies JavaScript Repository. Continuing in reverse chronological order, the Another Great Science Calculator script is preceded by a Digital Clock script that was authored by "BurnBlade" at some point in 1997. I've lost track of how many clock scripts we've heretofore covered - "Too many," you are perhaps thinking - but because I hold that every script deserves its fifteen minutes of fame, we will give BurnBlade's script a look-over in the discussion below.

Overview/layout

The Digital Clock script's code can be viewed here and its effect is displayed at the aforelinked digitalclock.html page. The display comprises three parts:
(1) an hour:minute:second time part and
(2) an a.m. or p.m. part
that compose a 12-hour clock, and
(3) a month/date/year date part.
The script's claim to distinction is its layout, which positions the display parts in separate cells of a two-row <table>.

<form name="timedate" onsubmit="0">
<table cellspacing="0" cellpadding="0">
<tr align="center">
<td><input type="text" name="time" size="7" value="..Starti"></td>
<td><input type="text" name="parts" size="2" value="ng.."></td></tr>
<tr align="center">
<td colspan="2"><input type="text" name="date" size="8" value="........"></td></tr>
</table></form>


The use of form <input> parking spaces for the parts reflects (vide infra) the JavaScript state of the art in 1997. There are no real red flags here* but we will use a simpler structure in the demo at the end of the post.

*Admittedly, the onsubmit="0" event handler is kind of weird and doesn't serve any useful purpose, but it's not invalid, either. BTW, HTML 3.2, the current version of HTML when the script was written, qualifiedly green-lights the use of tables for layout purposes.

The display is horizontally centered by a <center> element, which is strangely (and invalidly, note the <body> markup) wrapped around all of the rest of the code:

<center><script language="javascript">
...JavaScript statements, functions, and commands...
</script>
<body onload="startwatch( );">
<form name="timedate" onsubmit="0">
...
</form></center>


Putting the center element just around the table element and its descendants is what we would have wanted to do:

<form name="timedate" onsubmit="0"><center><table cellspacing="0" cellpadding="0">...Rows and cells...</table></center></form>

Part production

The time and a.m. or p.m. parts of the display are produced by the following JavaScript:

day = new Date( );
hour = day.getHours( );
minute = day.getMinutes( );
second = day.getSeconds( );
if (hour > 12) {
    hours = hour - 12;
    part = "PM"; }
else {
    part = "AM";
    if (hour == 0) {
        hours = 12; }
    else {
        hours = hour; } }
if (minute < 10) { minutes = 0; }
else { minutes = ""; }
if (second < 10) { seconds = 0; }
else { seconds = ""; }
time = ("" + hours + ":" + minutes + "" + minute + ":" + seconds + "" + second + "");
parts = ("" + part + "");
document.timedate.time.value = time;
document.timedate.parts.value = parts;


0s are prepended to minute and second values in the 0-9 range.
• Note that the 12 noon → 1 in the afternoon hour gets an AM designation.

Can we tighten up the above code? Yes indeed:

var day = new Date( ); var hour = day.getHours( ); var minute = day.getMinutes( ); var second = day.getSeconds( );
var part = hour > 11 ? "PM" : "AM"; /* The ?: conditional operator is detailed here. */
if (hour == 0) hour = 12;
if (hour > 12) hour -= 12;
if (minute < 10) minute = "0" + minute;
if (second < 10) second = "0" + second;
var time = hour + ":" + minute + ":" + second;
document.timedate.time.value = time;
document.timedate.parts.value = part;


The date part of the display is produced by:

date = ("" + (day.getMonth( ) + 1) + "/" + day.getDate( ) + "/" + day.getYear( ) + "");
document.timedate.date.value = date;


At the demo page, the year value is 117 - a smoking gun that the script uses day's getYear( ) return versus its getFullYear( ) return therefor. Given that + operations have a left-to-right associativity, the date calculation can be recast as:

var date = day.getMonth( ) + 1 + "/" + day.getDate( ) + "/" + day.getFullYear( );

Setting the clock in motion

Loading the parent document calls a startwatch( ) function that itself calls
(a) a stopwatch( ) function, which could be used to stop the clock once it's running but doesn't do anything at this juncture (OK, it resets the watchRun flag to false), and then
(b) a dayTime( ) function that produces an initial clock reading;
dayTime( ) is re-called every 1000 milliseconds so as to update the clock.

var watchID = null;
var watchRun = false;
function stopwatch( ) {
    if (watchRun) window.clearTimeout(watchID);
    watchRun = false; }
function startwatch( ) {
    stopwatch( );
    dayTime( ); }
function dayTime( ) {
    ...Determination and display of the time, parts, and date values as detailed above...
    watchID = window.setTimeout("dayTime( );", 1000);
    watchRun = true; }
...
<body onload="startwatch( );">


If you don't care about stopping the clock (the code contains no mechanism to do so, although it is simple enough to append an onclick="stopwatch( );"-triggering button to the timedate form), then you can ditch the startwatch( ) and stopwatch( ) functions and just use a window.onload = dayTime; statement to get things under way.

Don't render me, Bro

Like many old scripts, the Digital Clock JavaScript begins and ends with some "Hiding Scripts Within Comment Tags" HTML markup:

<script language="javascript">
<!-- Begin Digital Watch
...
// End Digital Watch-->
</script>


Such hiding code has been anachronistic for quite some time although it made sense for BurnBlade to have included it back in the day. However, the <!-- Begin Digital Watch line is followed by a
document.write("<!-- Begin Hiding Script -->"); command
and the // End Digital Watch--> line is preceded by a
document.write("<!-- End Hiding Script -->"); command.

I don't quite know what to make of those document.write( ) commands. Each write( ) command writes out an intact HTML comment; the text of those comments - Begin Hiding Script and End Hiding Script - implies that the commands are also meant to serve a hiding purpose even though the commands would not effect-wise duplicate the HTML hiding code for a non-JavaScript-capable browser. Moreover, the commands strike me as somewhat nonsensical in that the write( ) method is for writing something renderable to the page whereas comments are not meant to be rendered - I'd say we should throw them out, wouldn't you?

Demo + changes

We conclude with an updated demo.



I've traded in the form and table for a <div id="clockDiv" style="text-align:center;"> and a trio of <span>s.

var clockSpans = document.getElementById("clockDiv").getElementsByTagName("span");
clockSpans[0].textContent = time;
clockSpans[1].textContent = part;
clockSpans[2].textContent = date;


Check the source of the current page for the full coding.
We'll do some letter counting in the next post via the CCC Number of Letters script.


Powered by Blogger

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