Previous Page TOC Index Next Page Home


From the Web:

Dave Eisenberg's Calendar

Dave Eisenberg's calendar (http://www.best.com/~nessus/js-today.html) is a good example of the use of expressions and variables, as well as functions and objects. The program generates a dynamic Web page that includes a greeting suited to the time of day (such as "Good Evening!"), the time of day, and the current month's calendar with the current date highlighted.

In addition, the page includes an image suited to the current time of day.

In doing this, Eisenberg makes use of several techniques that we haven't seen yet. His script uses the Date object, as well as several new methods including Math.floor() from the Math object and others from the Date object.

The source code for the page is in Listing W1.1.

Input

<HTML>

<HEAD>

<TITLE>Greetings from Dave Eisenberg</TITLE>

</HEAD>

<BODY>

<SCRIPT LANGUAGE="JavaScript">

<!--  to hide script contents from old browsers

function greeting()

{

   var today = new Date();

   var hrs = today.getHours();

   document.writeln("<CENTER>");

   if ((hrs >=6) && (hrs <=18))

   {

      document.writeln("<IMG SRC=\"daypix/day");

      document.write(Math.floor(hrs / 10));

      document.write(Math.floor(hrs % 10));

      document.write("00.gif\">");

   }

   else

      document.write("<IMG SRC=\"daypix/night1.gif\">");

   document.writeln("<BR>");

   document.write("<H1>Good ");

   if (hrs < 6)

      document.write("(Early) Morning");

   else if (hrs < 12)

      document.write("Morning");

   else if (hrs <= 18)

      document.write("Afternoon");

   else

      document.write("Evening");

   document.writeln("!</H1>");

   document.write("You entered this page at ");

   dayStr = today.toLocaleString();

   i = dayStr.indexOf(' ');

   n = dayStr.length;

   document.write(dayStr.substring(i+1, n));

   document.writeln("</CENTER>");

}

function montharr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11)

{

   this[0] = m0;

   this[1] = m1;

   this[2] = m2;

   this[3] = m3;

   this[4] = m4;

   this[5] = m5;

   this[6] = m6;

   this[7] = m7;

   this[8] = m8;

   this[9] = m9;

   this[10] = m10;

   this[11] = m11;

}

function calendar()

{

   var monthNames = "JanFebMarAprMayJunJulAugSepOctNovDec";

   var today = new Date();

   var thisDay;

   var monthDays = new montharr(31, 28, 31, 30, 31, 30, 31, 31, 30,

      31, 30, 31);

   year = today.getYear() + 1900;

   thisDay = today.getDate();

   // do the classic leap year calculation

   if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))

      monthDays[1] = 29;

   // figure out how many days this month will have...

   nDays = monthDays[today.getMonth()];

   // and go back to the first day of the month...

   firstDay = today;

   firstDay.setDate(1);

   // and figure out which day of the week it hits...

   startDay = firstDay.getDay();

   document.writeln("<CENTER>");

   document.write("<TABLE BORDER>");

   document.write("<TR><TH COLSPAN=7>");

   document.write(monthNames.substring(today.getMonth() * 3,

      (today.getMonth() + 1) * 3));

   document.write(". ");

   document.write(year);

   document.write("<TR><TH>Sun<TH>Mon<TH>Tue<TH>Wed<TH>Thu<TH>Fri<TH>Sat");

   // now write the blanks at the beginning of the calendar

   document.write("<TR>");

   column = 0;

   for (i=0; i<startDay; i++)

   {

      document.write("<TD>");

      column++;

   }

   for (i=1; i<=nDays; i++)

   {

      document.write("<TD>");

      if (i == thisDay)

         document.write("<FONT COLOR=\"#FF0000\">")

      document.write(i);

      if (i == thisDay)

         document.write("</FONT>")

      column++;

      if (column == 7)

      {

         document.write("<TR>"); // start a new row

         column = 0;

      }

   }

   document.write("</TABLE>");

   document.writeln("</CENTER>");

}

document.write(greeting());

document.write("<HR>");

document.write(calendar());

document.write("<HR>");

document.write("<A HREF=\"http://www.best.com/~nessus\">");

document.write("Back to Dave Eisenberg's resume<\A>");

<!-- end hiding contents from old browsers  -->

</SCRIPT>

</BODY>

</HTML>

Output

The code produces results like those in Figures W1.1 and W1.2.


Figure W1.1. During the day time, the user gets one of several images depicting the time of day.


Figure W1.2. Using the Date object, the program builds a calendar for the current month.

End of Output

Analysis

The first thing you notice about this script is that it is not placed inside the header of the HTML file. The author does this because there is no chance of events triggering calls to functions which have not yet been defined.

In addition, all HTML code is dynamically generated by the script.

The calendar program uses three functions. The calls are made in sequence by the main body of the script:

document.write(greeting());

document.write("<HR>");

document.write(calendar());

document.write("<HR>");

document.write("<A HREF=\"http://www.best.com/~nessus\">");

document.write("Back to Dave Eisenberg's resume<\A>");

At the top of the script, two global declarations (today and hrs) occur. The command var today = new Date(); creates an instance of the system's Date object in much the same way you could create an instance of any object you defined yourself.

The Date object enables programmers to create an object that contains information about a particular date and provides a set of methods to work with that information.

In order to create an instance of the Date object, you use the variable = new Date(parameters) form where the parameters can be any of the following:


In JavaScript, it is not possible to create dates before 1 January 1970. 1 January 1970 at 00:00:00 is known as the epoch.

The Date object provides the methods outlined in Table 4.1.

Name


Description


getDate

Returns the day of the month as an integer from 1 to 31

getDay

Returns the day of the week as an integer where zero is Sunday and one is Monday

getHours

Returns the hour as an integer between 0 and 23

getMinutes

Returns the minutes as an integer from 0 to 59

getMonth

Returns the month as an integer from 0 to 11 where zero is January and 11 is December

getSeconds

Returns the seconds as an integer between 0 and 59

getTime

Returns the number of milliseconds since 1 January 1970 at 00:00:00

getTimezoneOffset

Returns the difference between the local time and Greenwich Mean Time in minutes

getYear

Returns the year as a two-digit integer

parse

Returns the number of milliseconds since 1 January 1970 at 00:00:00 for the date string passed to it

setDate

Sets the day of the month based on an integer argument from 1 to 31

setHours

Sets the hour based on an argument from 0 to 23

setMinutes

Sets the minutes based on an argument from 0 to 59

setMonth

Sets the month based on an argument from 0 to 11

setSeconds

Sets the seconds based on an argument between 0 and 59

setTime

Sets the time based on an argument representing the number of milliseconds since 1 January 1970 at 00:00:00

setYear

Sets the year based on a four-digit integer greater than 1900

toString

Returns the current date as a string

toGMTString

Returns the current date and time using the Internet GMT conventions (i.e. in the form "Mon, 18 Dec 1995 17:28:35 GMT")

toLocaleString

Returns the date as a string in the form "MM/DD/YY HH:MM:SS"

UTC

Takes a comma delimited date and returns the number of milliseconds since 1 January 1970 at 00:00:00 GMT time

Based on this information, the variable declaration var hrs = today=getHours() will contain the current hour when the user loads the page.

The first function the script calls is greeting(), which displays the appropriate image and welcome message along with the current time:

function greeting()

{

   var today = new Date();

   var hrs = today.getHours();

   document.writeln("<CENTER>");

   if ((hrs >=6) && (hrs <=18))

   {

      document.writeln("<IMG SRC=\"daypix/day");

      document.write(Math.floor(hrs / 10));

      document.write(Math.floor(hrs % 10));

      document.write("00.gif\">");

   }

   else

      document.write("<IMG SRC=\"daypix/night1.gif\">");

   document.writeln("<BR>");

   document.write("<H1>Good ");

   if (hrs < 6)

      document.write("(Early) Morning");

   else if (hrs < 12)

      document.write("Morning");

   else if (hrs <= 18)

      document.write("Afternoon");

   else

      document.write("Evening");

   document.writeln("!</H1>");

   document.write("You entered this page at ");

   dayStr = today.toLocaleString();

   i = dayStr.indexOf(' ');

   n = dayStr.length;

   document.write(dayStr.substring(i+1, n));

   document.writeln("</CENTER>");

}

The function determines that it is daytime if hrs is between 6 and 18 and then builds an image tag. The filename includes a number built up out of the hrs variable using Math.floor(). This method returns the closest integer less than the argument. In that way, if hrs is 12, the image's filename would be day1200.gif.


Math.ceil() is similar to Math.floor() except it returns the nearest integer greater than the value of the argument.

The current time, which is output at the end of the function, is obtained from the string returned by the Date.toLocaleString() method. This string contains the date and time separate by a single space. The function uses the indexOf() method of the string object. to locate the index of the space in the string. The length property of the string object is used to determine the index of the last character in the string.

The substring() method then returns the portion of the string after the index up to the end of the string. The string object, and in particular the substring() method, are discussed in more detail in later chapters. The string object is covered in depth in Chapter 10, "Strings, Math, and the History List."

The next function to be called is the calendar() function which does the more complex job of building the calendar. The calendar is designed using HTML tables, which are discussed further in Chapter 7, "Loops."

function calendar()

{

   var monthNames = "JanFebMarAprMayJunJulAugSepOctNovDec";

   var today = new Date();

   var thisDay;

   var monthDays = new montharr(31, 28, 31, 30, 31, 30, 31, 31, 30,

      31, 30, 31);

   year = today.getYear() + 1900;

   thisDay = today.getDate();

   // do the classic leap year calculation

   if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))

      monthDays[1] = 29;

   // figure out how many days this month will have...

   nDays = monthDays[today.getMonth()];

   // and go back to the first day of the month...

   firstDay = today;

   firstDay.setDate(1);

   // and figure out which day of the week it hits...

   startDay = firstDay.getDay();

   document.writeln("<CENTER>");

   document.write("<TABLE BORDER>");

   document.write("<TR><TH COLSPAN=7>");

   document.write(monthNames.substring(today.getMonth() * 3,

      (today.getMonth() + 1) * 3));

   document.write(". ");

   document.write(year);

   document.write("<TR><TH>Sun<TH>Mon<TH>Tue<TH>Wed<TH>Thu<TH>Fri<TH>Sat");

   // now write the blanks at the beginning of the calendar

   document.write("<TR>");

   column = 0;

   for (i=0; i<startDay; i++)

   {

      document.write("<TD>");

      column++;

   }

   for (i=1; i<=nDays; i++)

   {

      document.write("<TD>");

      if (i == thisDay)

         document.write("<FONT COLOR=\"#FF0000\">")

      document.write(i);

      if (i == thisDay)

         document.write("</FONT>")

      column++;

      if (column == 7)

      {

         document.write("<TR>"); // start a new row

         column = 0;

      }

   }

   document.write("</TABLE>");

   document.writeln("</CENTER>");

}

The function starts by defining variables which will be used later in the function, as well as defining an instance of the Date object called today and an instance of the montharr object (defined by the montharr() function) which contains 12 properties with the number of days in each month of the year.

The first step is to determine if it is a leap year so that the value of monthDays[1] (for February) can be adjusted. This is done by using today.getYear() to get the current year and then using the following if statement to check if the year is a leap year:

if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))

      monthDays[1] = 29;

Next, the variable nDays is assigned the number of days in the current month, The index used in monthDays is the value returned by today.getMonth() because it returns an integer which corresponds to the indexes of the monthDays object.

A copy of today called firstDay is created and the date set to the first of the month using firstDay.setDate(1) in order to figure out the day of the week using startDay = firstDay.getDay(). You could have used today.setDate(1) and today.getDay(), but that would have made the script harder to read and understand.

The function then outputs the opening tags of the table and writes the current month out by using the substring() method on the variable monthNames. This is followed by writing the number of blank calendar spaces needed in the first row using a for loop, which is covered in Chapter 7.

Next, another for loop is used to write out the dates of the month in sequence. The if statements with the condition (i== thisDay) are used to determine if the text color should be changed for the current table cell.

The variable column is incremented throughout both for loops to keep track of which column of our seven-column table the current date is written into. If the date has been written into the seventh column, then the last if statement in the second loop starts a table row with the TR tag and resets column to zero.

Finally, the function writes out all the closing HTML for the table.

Previous Page TOC Index Next Page Home