reptile7's JavaScript blog
Wednesday, January 31, 2018
 
A JavaScript 1.2 Calendar and Clock, Part 6
Blog Entry #388

The right year

One last point regarding the compute( ) day-of-the-week algorithm discussed in the previous post:
Obviously, the algorithm will not give us what we want if the val3 year input is off in some way. The year field's "19" + t.getYear( ) value was 1997 back in 1997 but is 19118 in 2018, which for January leads to a week = Tuesday versus the Monday that 1 January 2018 actually fell on, not good: this problem can be quickly fixed by setting the value to t.getFullYear( ).

A new charge

After the compute( ) function has finished executing, a

window.open('js-calbot2.html', target='frame2');

command replaces the js-calbot1.html document in the frame2 frame with the js-calbot2.html document. Per Mozilla, the window.open( ) method's windowName parameter specifies the name of the browsing context, a <frame> in this case, into which to load the specified resource; the target= part is unnecessary and in fact shouldn't be there.

js-calbot2.html intro

The js-calbot2.html body comprises a single script element that single-handedly (without the aid of any non-script HTML) creates a tabular calendar for a given month.

<html>
<body bgcolor="black" text="red" link="white" vlink="white">
<script>
...calendar code...
</script>
</html>


Body style

As shown above, the body element start tag provides color settings for the page background, the foreground text, unvisited links, and visited links.
(t) The text="red" attribute reddens the calendar's Sunday to Saturday day headers, and that's it.
(l,v) There are no links on the js-calbot2.html page.

Interframe data transfer

The js-calbot2.html script calls on the values stored in the line form's result, month, and year fields to create the calendar.

window.onerror = null;
first = parent.frame1.document.line.result.value;
months = parent.frame1.document.line.month.value;
yr = parent.frame1.document.line.year.value;


The line form's raison d'être is to facilitate this transfer of data. However, we could alternatively store the line form's hidden control values in global variables

var val1, val2x, val3, week;
val1 = 1;
val2x = t.getMonth( ) + 1; // Or just: val2x = t.getMonth( );
val3 = t.getFullYear( );


in which case there would be no need for the line form at all.

var first = parent.frame1.week;
var months = parent.frame1.val2x;
var yr = parent.frame1.val3;


The window.onerror = null; statement means your users won't see JavaScript errors caused by your own code, quoting Netscape, or at least that's what it meant for users who were using Netscape 3.x-4.x back in the day. I suspect the statement's purpose is to suppress the "parent.frame1 is undefined" or equivalent error that would otherwise be promptly thrown by the above parent.frame1 expression(s) if we were to land on the isolated js-calbot2.html page outside of the javacalendar.html frameset; a much better approach to preempting that error is to route the user to javacalendar.html via an if (! parent.frame1) window.location = "javacalendar.html"; conditional.

What month is it?

To build the calendar we'll need to know how many days the months month has.

var a = "";
if (months == 1 || months == 3 || months == 5 || months == 7 || months == 8 || months == 10 || months == 12) { a = 31; }
else if (months == 4 || months == 6 || months == 9 || months == 11) { a = 30; }
else { a = 28; }


Minor bullet point:
• The number-storing a can be declared with a var a; statement; its initialization to an empty string is pointless.
Major bullet point:
No allowance is made for leap years, whose Februaries will have only a = 28 days per the concluding else clause. Here's what we want for February:

else {
    if ((! (yr % 4) && (yr % 100)) || ! (yr % 400)) a = 29;
    else a = 28; }


We will later put the name of the months month in the calendar table caption. Accordingly, the months month number is mapped onto a corresponding month string via:

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


We saw the same set of months mappings in the js-caltop1.html date string code: as in that case, I would alternatively use an Array to get the months string:

var t = new Date( );
var monthArray = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var months = monthArray[t.getMonth( )];


Re the pre-months display

The first day string is mapped onto a getDay( )-synced d index via:

if (first == "Sunday") { d = 0; }
else if (first == "Monday") { d = 1; }
...
else if (first == "Saturday") { d = 6; }


We could have gotten d back in the compute( ) function with:

var t = new Date(val3, val2x, val1);
var d = t.getDay( );


We will later use d to create calendar table cells that lead up to the start of the months month for months months that do not begin on a Sunday.

Calendar intro

We're ready to start writing out the calendar table.

document.write("<center><table border='1'>");

• The center element's closing </center> tag is missing in the source; of course, we should actually use a table { margin-left: auto; margin-right: auto; } styling to horizontally center the table.

The calendar's rows[0] row holds one cell that contains a months yr caption.

document.write("<tr>");
document.write("<th colspan='7'><center><font size='+3' color='#449977' face='Arial'><b>" + months + " " + yr + "</b></font></center></th>");
document.write("</tr>");


• Th cell content is bolded and horizontally centered by default with Firefox, Google Chrome, Opera, and Safari on my computer.
• A +3 font element size can be effected by a font-size: xx-large; styling.
• A caption is a heading but not really a header, and the th element is not quite right for it; it would be better to put our caption in a bona fide caption element:

caption { color: #449977; font: bold xx-large Arial; }

var calendarCaption = document.createElement("caption");
calendarCaption.textContent = months + " " + yr;
document.getElementsByTagName("table")[0].appendChild(calendarCaption);


Caption content is placed at the top of the table and is horizontally centered but not bolded by default; it is not surrounded by the table border, which doesn't bother me, although you could give it, say, a border: double #888; styling if you like.

The calendar's rows[1] row holds seven cells that respectively contain Sunday to Saturday day headers.

document.write("<tr>");
document.write("<td width='75'><center><font size='-1' face='Arial'><b>Sunday</b></font></center></td>");
document.write("<td width='75'><center><font size='-1' face='Arial'><b>Monday</b></font></center></td>");
...
document.write("<td width='75'><center><font size='-1' face='Arial'><b>Saturday</b></font></center></td>");
document.write("</tr>");


• Changing the td elements to th elements would allow us to get rid of the center and b element formatting.
• A -1 font element size can be effected by a font-size: small; styling; that said, I myself would size-wise leave the day headers alone and not small-en them.

Here's what we've got so far:


The day header row is coded with:

var dayArray = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var dayTr = document.createElement("tr");
document.getElementsByTagName("table")[0].appendChild(dayTr);
for (var i = 0; i < dayArray.length; i++) {
    var dayTh = document.createElement("th");
    dayTh.style.width = "75px";
    dayTh.textContent = dayArray[i];
    dayTh.style.color = "red";
    dayTh.style.fontFamily = "Arial";
    dayTr.appendChild(dayTh); }

We'll go through the date part of the calendar in the following entry.

Comments: Post a Comment

<< Home

Powered by Blogger

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