reptile7's JavaScript blog
Thursday, November 30, 2017
A JavaScript 1.2 Calendar and Clock, Part 2
Blog Entry #384

Welcome back to our ongoing analysis of the Calendars, Clocks, and Calculators Multiple Java Calendar script. At present we are working our way through the js-caltop1.html document that fills the upper frame1 frame of the javacalendar.html frameset.

As noted in the previous post, the js-caltop1.html body contains three script elements, which I will call scripts[0], scripts[1], and scripts[2], as though we had gotten them with a var scripts = document.getElementsByTagName("script"); command. (FYI: Use of the id attribute with the script element wasn't OK in HTML 4 but is green-lighted by HTML5.)

The left cell of the js-caltop1.html layout table is coded completely by the scripts[0] script, whereas the center cell of the table is coded partly by the scripts[1] script and partly by the scripts[2] script. The right cell of the table is written as normal HTML.

The month and year controls

The document.write( ) command that writes out the

"<font face='Arial'><b>" + day + months + dates + "/" + years + "</b></font>"

date string in the layout table's left cell also writes out nine img placeholders for the image-based digital clock above the date string; the clock itself is filled in by a date( ) function that fires when the js-caltop1.html page has finished loading. Before we get to the clock, however, we've got some more top-level rendering to do.

The scripts[0] script ends with the document.write("</td>"); closure of the left cell. The scripts[0] script's nextElementSibling is the scripts[1] script, which writes out some of the layout table's center cell.

The center cell content comprises a form that holds four controls, in source order:
elements[0] is a selection list of month options.

elements[1] is a push button.
elements[2] is a text field that displays a getYear( ) year number.

elements[3] is a push button.

The scripts[1] part of the center cell is:

document.write("<center><td><form name='isnform'>");
document.write("<select name='isnlist' onchange='navigator(this.form);'>");
document.write("<option value='1'>January");
document.write("<option value='2'>February");
document.write("<option value='12'>December");

• The starting center element cannot validly be a child of the layout table's rows[0] row (the tr element has a (th|td)+ content model) and does not horizontally center the rows[0].cells[1] content. Throw it out.
• À la the date string's months = today.getMonth( ) + 1; index, each month option value is one higher than the corresponding getMonth( ) return.

The isnlist list's options can alternatively and preferably be created via the selectObject.options-writing methodology detailed in Blog Entry #380:

var monthArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var optionvaluesArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; /* As per getMonth( ) */
for (var i = 0; i < monthArray.length; i++)
    document.isnform.isnlist.options[i] = new Option(monthArray[i], optionvaluesArray[i]);

The scripts[1] script ends with the document.write("</select>"); closure of the isnlist list. The scripts[1] script's nextElementSibling is the scripts[2] script, which writes out the rest of the center cell.

t = new Date( );
y = t.getYear( );
document.write("<input name='raise' type='button' value='<<' onclick='down( );'>");
document.write("<input name='showyear' type='text' value='19" + y + "' size='4'>");
document.write("<input name='raise' type='button' value='>>' onclick='up( );'>");

In the js-caltop1.html source, the <input ... value='<<' ...></td> run of tags is actually written out by a single document.write( ) command, which I have broken up for the sake of clarity.

The value attribute of the input element has a CDATA data type designation and therefore there shouldn't be a problem with specifying literal < and > characters in the value values for the and buttons but you might want to err on the side of caution and use character references to code those characters, e.g., value='&lt;&lt;' and value='&gt;&gt;'.

The t = new Date( ); and y = t.getYear( ); statements actually appear near the beginning of the scripts[1] script, although they could have been placed at the beginning of the scripts[2] script. The y year number is effectively appended to a 19 substring and the resulting numeric string is assigned to the value of the showyear text field. For all but a small set of very early browsers, the 2017 y return is 117 and the initial showyear value is therefore 19117.

The today = new Date( ); and years = today.getYear( ); statements in the date string part of the code have a global scope and could have been used to set the showyear value. That said, if we were to separate the code's calendar, clock, and date string parts from one another, then each part would of course need its own Date functionality.

The navigator( ), up( ), and down( ) functions are coded in the scripts[1] script; we'll go through these functions after we display the calendar in the frame2 frame.

Before we move on to the layout table's right cell, I should note that the isnlist selection is set to the current month by:

v = t.getMonth( ) + 1;
document.isnform.isnlist.selectedIndex = v - 1;

The v getMonth( ) determination follows the t construction in the scripts[1] script, whereas the selectedIndex assignment occurs at the very end of the scripts[2] script. A document.isnform.isnlist.selectedIndex = t.getMonth( ); command at the end of the scripts[1] script would have been simpler, yes?

The calendar trigger

The right cell's only content is a push button.

<input name="butt" type="button" value=" Show Calendar " onclick="compute(this.form);'js-calbot2.html', target='frame2');">

The button is the last control of a line form whose start tag and first five controls are written JavaScriptically in the scripts[2] script

document.write("<form name='line'>");
document.write(...5 type='hidden' <input>s...);

even as the button and the following </form> tag are written as normal HTML as shown above - not a valid situation* whether the script element has a CDATA or #PCDATA content model.

*We could say the same thing about the layout table itself, most of which is created JavaScriptically but whose last cell and concluding markup are written as normal HTML. We will get rid of the document.write( ) commands, the layout table, and the isnform and line forms when it comes time to roll out a demo.

The compute( ) function is coded in the scripts[2] script; we'll discuss compute( ) and that somewhat unusual ) command when we're ready to display the calendar.

Clock intro

The layout table is followed by three <p>s of text that take us to the end of the js-caltop1.html source and that I trust you are able to modify (or delete) as you see fit. When the top-level rendering is finished, the browser gets to work on the clock in the table's left cell. As noted earlier, the clock's img placeholders are written out by the same scripts[0] document.write( ) command that writes out the date string.

var a = 12;
var b = 15;
/* As before, the original code has been broken up below to make it more readable. */
document.write("<img name='hour1' src='dgbl.gif' width='" + a + "' height='" + b + "'>");
document.write("<img name='hour2' src='dgbl.gif' width='" + a + "' height='" + b + "'>");
document.write("<img src='dgcol.gif' height='" + b + "'>");
document.write("<img name='min1' src='dgbl.gif' width='" + a + "' height='" + b + "'>");
document.write("<img name='min2' src='dgbl.gif' width='" + a + "' height='" + b + "'> ");
document.write("<img name='sec1' src='dgbl.gif' width='" + a + "' height='" + b + "'>");
document.write("<img name='sec2' src='dgbl.gif' width='" + a + "' height='" + b + "'> ");
document.write("<img name='noon1' src='dgbl.gif' width='" + a + "' height='" + b + "'>");
document.write("<img src='dgm.gif' width='" + a + "' height='" + b + "'>");

Seven of the nine placeholders are initially filled with a 'blank' dgbl.gif image. A dgcol.gif image of a colon fills the third placeholder and a dgm.gif image of an uppercase M fills the ninth placeholder. Note that a space separates (v-vi) the fifth and sixth placeholders and (vii-viii) the seventh and eighth placeholders.

(Yes, the dgcol.gif image really is that faint. Also, the original bgcolor="black" rubs me the wrong way and we'll definitely change that when it comes time to roll out a demo.)
We'll check over the date( ) function that sets the hour, minute, second, and a.m./p.m. parts of the clock in the following entry.

Tuesday, November 14, 2017
A JavaScript 1.2 Calendar and Clock, Part 1
Blog Entry #383

We introduced the Multiple Java Calendar script in the previous entry and are now ready to deconstruct the script's frame documents; we'll go through js-calbot1.html and the date string part of js-caltop1.html in today's post.

The font-size follies

The js-calbot1.html source is much simpler than that for js-caltop1.html or js-calbot2.html, and contains no JavaScript, so that's where we'll start.

<!-- This script was made by Ryan Haugh. -->
<body bgcolor="black" text="white">
<font size="+4,+5" face="Arial">This Is A Simple Calendar That You Can Change To Any Month Or Year You Want.</font>

• An authorship comment containing the author's full name appears in all three frame documents but not in the corresponding JavaScript Goodies documents.
• Yep, the </center> tag is missing - we'd need it if we were keeping the center element but we won't be doing that.

We've got a white, horizontally centered, gigantic Arial text string on a black background - that's it. HTML5 declares that the bgcolor and text attributes of the body element, the center element, and the font element are obsolete ... and must not be used by authors, but let's leave this aside for a moment. The one odd thing here is that size="+4,+5" attribute - what does it mean, what exactly does it give us?

The +4,+5 value is not invalid in that the font element's size attribute has a CDATA data type designation but it's not really valid, either: unlike the face="Arial" attribute, whose value could be a comma-separated list of font names in order of preference, the size attribute should have only one setting.

A size="+4" setting would mean "four sizes larger" and take us from a size="3" default to a size="7" maximum vis-à-vis an integer size scale that ranges from 1 to 7 and to which all sizes belong, quoting the W3C; it follows that a size="+5" setting would also take us to the size="7" maximum, i.e., +5 wouldn't go off-scale and give us an even bigger size.

To see how a +4,+5-type value plays out in an on-scale case, I applied size="+2", size="+2,+3", and size="+3" settings to some normal (size="3") text: I found that the size="+2" and size="+2,+3" renderings were identical and were smaller than the size="+3" rendering, as though the browser parseInt( )ed the +2,+3 value.

If in the js-calbot1.html case the size="+4", size="+4,+5", size="+5", and size="7" settings give identical renderings, then in the name of simplicity we might as well size="7" the This Is A Simple Calendar ... string if we're going to hold onto the font element. But of course, we shouldn't hold onto the font element, or the center element or the body element's bgcolor and text attributes for that matter; as the center element is a type of div element, we should code the js-calbot1.html body with:

body { background-color: black; color: white; }
#aboutDiv { text-align: center; font-size: 48px; font-family: Arial; }
<div id="aboutDiv">This Is A Simple Calendar That You Can Change To Any Month Or Year You Want.</div>

This Is A Simple Calendar ...

At least on my computer, a size="7" setting is effectively duplicated by a font-size:48px; style declaration; CSS's largest <absolute-size> font-size value, xx-large, maps onto size="6" and therefore doesn't quite cut it.

What day is today?

The first-completed part of the js-caltop1.html display is the date string in the layout table's left cell. Most of the js-caltop1.html display is created JavaScriptically, and the date string is created completely by top-level code in the first of three script elements in the js-caltop1.html body.

We begin by creating a today Date object and then getting day of the week, month, date number, and year information for that object.

<body onload="date( );" bgcolor="black" onunload="reseter( );" text="white">
today = new Date( );
day = today.getDay( ) + 1;
months = today.getMonth( ) + 1;
dates = today.getDate( );
years = today.getYear( );

The author increments the getDay( ) and getMonth( ) returns to numbers that a non-programmer would associate with a given day of the week and month respectively, e.g., day is 1 for a Sunday, months is 11 for November. This is a bad call in my book: when writing JavaScript code it is best to stick with JavaScript's starts-with-0 indexing system.

The Multiple Java Calendar script went live at Java Goodies in November 1997 and predates the implementation of the getFullYear( ) method in JavaScript 1.3; the years getYear( ) return would have been 97 in 1997.

Moving on, the day and months indexes are respectively converted into corresponding day of the week and month strings by two series of if statements.

if (day == 1) { day = "Sunday, "; }
else if (day == 2) { day = "Monday, "; }
else if (day == 7) { day = "Saturday, "; }

if (months == 1) { months = "January "; }
else if (months == 2) { months = "February "; }
else if (months == 12) { months = "December "; }

Finally, day, months, dates, and years are plugged into the b element child of a font element that concludes (is the lastChild of) the layout table's left (rows[0].cells[0]) cell.

document.write("<table border='0' width='100%'>");
document.write("<td align='middle'>");
document.write(...img placeholders for the image-based digital clock...);
document.write("<font face='Arial'><b>" + day + months + dates + "/" + years + "</b></font>");

• In the js-caltop1.html source, the <center></td> run of tags is actually written out by a single document.write( ) command, which I have broken up for the sake of clarity.
• The beginning center element horizontally centers the text that follows the layout table but has no effect on the layout table itself, which spans the width of the viewport as per its width='100%' attribute.
• The td content is in practice horizontally centered by the align='middle' attribute even though align should have been set to center for this purpose. FYI: The align attribute was valid for the various internal table elements in HTML 4 but has now been obsoleted by HTML5 for all of the elements that could formerly take it.

So, if we retro-set today to 1 November 1997 (new Date(1997, 10, 1)), then our output is:

Saturday, November 1/97

How I'd code the date string

body { background-color: black; color: white; }
#datestringDiv { font-weight: bold; font-family: Arial; }
<div id="datestringDiv"></div>
var today = new Date( );
var dayArray = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var day = dayArray[today.getDay( )];
var monthArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var months = monthArray[today.getMonth( )];
var dates = today.getDate( );
var years = today.getFullYear( );
document.getElementById("datestringDiv").textContent = day + ", " + months + " " + dates + ", " + years;

I like working with arrays and I use a getDay( )-synced dayArray and a getMonth( )-synced monthArray to set day and months, respectively. I of course replace the getYear( ) call with a getFullYear( ) call. I house the date string in a div, which can be created JavaScriptically although I prefer to write it as normal HTML. Re the date string format, I separate dates and years with a comma-space versus a slash.

Powered by Blogger

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