reptile7's JavaScript blog
Thursday, March 12, 2015
Let's Make an Appointment
Blog Entry #345

I've been slogging through the Calendars, Clocks, and Calculators sector of the Java Goodies JavaScript Repository over the past few days, cataloguing what's there, and I'm sorry to report that its pickings are a lot slimmer than I originally thought they would be. We won't be spending nearly as much time in this sector as we did in the Scripts that Display Text sector.

The Quadratic Equation script is followed by a Timezone Buttons script that codes a World Clock. The Timezone Buttons demo works just fine although its color="#FFFFFF" text input labels are invisible due to the white background; the Grab the Script page is gone but you can still get the script at the JavaScript Goodies site. The Timezone Buttons script is evidently a slightly earlier version of the JavaScript Script Tips #87-90 script that we dissected in January-March 2008. (At least now I know who wrote the script. Cheers, Randy.)

The Timezone Buttons script is followed by a Calendar and Datebook script for which Joe does not provide a demo but whose package is still available. The Calendar and Datebook script codes a calendar for a month of your choosing - either the current month or a past or future month - and places custom memos - e.g., "Dentist Appointment", "Take puppies to the vet" - on specific dates of the calendar.

We will discuss the Calendar and Datebook script for at least the next two entries.

The ampcal/ package

Authored by Andrew Pierce in 1998, the Calendar and Datebook code comprises an ampcal/ package of three files:
(1) ampcal.js
(2) example.html
(3) readme.txt

The ampcal.js script builds the calendar/datebook ("calendar" hereafter) from scratch, and is imported into the example.html display document via:

<!-- Include the calendar source file -->
<script language="JavaScript" src="ampcal.js"></script>
<script language="JavaScript"> /* ...The internal example.html script... */ </script>

The example.html document sets the calendar's month and year, date memos, heading, and font sizes, and writes the calendar to the page.

The example.html document concludes with the following notice:

<p>Email the author: <a href="">Andrew Pierce</a><br>
<a href="">Visit the ampCal web page.</a></p>

The page is no longer extant: a search for it at the Internet Archive led me to a functioning demo.

The readme.txt file is, well, a readme-type file.

Calendar overview

The calendar is housed in a 6-row*, 7-cells-per-row table, which doesn't have an identifier so let's give it an id="calTable". Could we put the calendar in a div of 42 spans? Sure. But a calendar counts as a grid of data in my book, and therefore I would say that the table structure is appropriate.
(*We'll see later that some months require a 7th row.)

The calTable table's first (rows[0]) row is filled with a Sunday-to-Saturday set of headers. The remaining rows are populated with date numbers and memos as appropriate for the display month. The rows[1]-rows[5] cells are color-coded per criteria we will discuss in due course.

The calendar is completely coded by two scripts: the external ampcal.js script and an internal example.html script. There is no separation at all between structure, presentation, and behavior. The calendar structure can be written out as normal HTML if desired, although doing this will greatly increase the calendar 'footprint' in the example.html document. The calendar stylings are easily moved to an external or internal style sheet.

Initiation I

An ampCal Object object bundles
(a) various data for the calendar and
(b) functionality for storing/retrieving the date memos and for displaying the calendar.

• I'm tempted to say that the ampCal object 'represents' the calendar, but that would not really be true, as the ampCal data doesn't intersect with the calendar structure in any way.
• As the Mozilla JavaScript Guide's discussion of constructor functions does not specify that a constructor function (vide infra) creates an Object object, you'll just have to take my word for it that window.alert(ampCal); displays an [object Object] message.

The ampcal.js script contains 5 functions and no top-level commands. The Calendar and Datebook action effectively begins with the internal example.html script, whose first operation creates the ampCal object by instantiating an ampCalendar object type.

ampCal = new ampCalendar(9, 1998);

The ampCalendar( ) constructor function

function ampCalendar(m, y) { ... }

is the last function in the ampcal.js source; it defines a total of 21 properties for the calendar, 4 of which are methods; its two arguments are stored in m and y variables.

The ampCalendar( ) function first creates empty arrays for storing the date memo data, and assigns them to m_rgDay and m_rgTxt properties.

this.m_rgDay = new Array( );
this.m_rgTxt = new Array( );

Next, m_strDead, m_strFutr, m_strPast, and m_strNow properties are set to #-less RRGGBB colors

this.m_strDead = "C0C0C0";
this.m_strFutr = "F5DEB3";
this.m_strPast = "E1E1D1";
this.m_strNow = "F08080";

with which we'll paint the rows[1]-rows[5] cell backgrounds. FYI: The #C0C0C0 color has a "silver" name, the #F5DEB3 color is "wheat", and the #F08080 color is "lightcoral" - see the Extended color keywords section of the CSS Color Module Level 3 specification. The #E1E1D1 color doesn't have a name as far as I know.

An array of the numbers of days/month for a non-leap year is assigned to an m_rgDays property; an array of month names is assigned to an m_rgMths property.

this.m_rgDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
this.m_rgMths = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

Font family data are loaded into a font property; font size data are loaded into fontSize and headSize properties.

this.font = "Verdana, Arial, Helvetica";
this.fontSize = "2";
this.headSize = "2";

The m parameter value, 9, is assigned to a month property; the y parameter value, 1998, is assigned to a year property.

this.month = m;
this.year = y;

Subsequently, m_now and m_myDate properties are set to Date objects for the current date and for the first date of the display month, respectively.

this.m_now = new Date( );
this.m_myDate = new Date(y, m - 1, 1);

After that, this.m_myDate.getMonth( ), 8, is plugged into the this.m_rgMths[ ] array to give September, which is assigned to a monthName property. The this.monthName value, a space character, and the this.year value are concatenated to give a September 1998 string, which is assigned to a title property.

this.monthName = this.m_rgMths[this.m_myDate.getMonth( )];
this.title = this.monthName + " " + this.year;

We're getting there. References for ampCalendar_setFebDays( ), ampCalendar_Display( ), ampCalendar_setItem( ), and ampCalendar_getText( ) functions are then assigned respectively to setFebDays, display, setItem, and getText properties: we'll discuss these functions when we get to them.

this.setFebDays = ampCalendar_setFebDays;
this.display = ampCalendar_Display;
this.setItem = ampCalendar_setItem;
this.getText = ampCalendar_getText;

The ampCalendar( ) function concludes with a call to the ampCalendar_setFebDays( ) function.

this.setFebDays( ); } // That's it for ampCalendar( ).

Look before you leap

If this.month is 1 and this.year is a leap year, then the ampCalendar_setFebDays( ) function, which is the first function in the ampcal.js source, adjusts this.m_rgDays[1] to 29.

function ampCalendar_setFebDays( ) { if (this.month == 1) { if (this.year % 4 == 0) { if (this.year % 100 == 0) { if (this.year % 400 == 0) this.m_rgDays[1] = 29; } else this.m_rgDays[1] = 29; } } }

• The this.month == 1 test actually flags January and not February: recall that this.month is one greater than this.m_myDate.getMonth( ).

• As I trust you know, there is a bit more to the leap year thing than just divisibility by 4, namely, years that are divisible by 100 but not by 400 (e.g., 1900, 2100) are not leap years.

• The this.year conditional code is more verbose than it needs to be, and can be recast as:

if (!(this.year % 4) && (this.year % 100) || !(this.year % 400)) this.m_rgDays[1] = 29;

Having said all this, the ampCalendar_setFebDays( ) functionality and the m_rgDays[ ] array are actually excess baggage, and can be thrown out: as we'll see in the next post, the ampCalendar_Display( ) function calls on several Date object methods to build the calendar and doesn't make use of the m_rgDays[ ] array at all.

We'll continue our Calendar and Datebook deconstruction in the following entry.

Comments: Post a Comment

<< Home

Powered by Blogger

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