|
Articles | Calendars |
back
With the end of the Millennium approaching, many
programmers around the world are focused on dates. So to wet your appetites here
are a few calendar routines written in JavaScript.
What we want to be able to show is a 12 month calendar
from January to December in a grid 4 by 3, with the current day highlighted.
We will achieve this requirement in stages. Each month
will be output by a JavaScript function called Calendar by passing the
month and year e.g.:
Where m is the month from 0 to 11, and y
is the year. JavaScript dates store January as '0' and December as '11'. The Calendar
function will handle all the required processing, i.e. to calculate the day the
first of the required month falls on, and whether the year is a leap year or
not.
To calculate the day the first of a month falls on,
first set the date to the 1st of the month and then use the getDay()
function to return the day:
var firstDay = new Date(Year,Month,1);
var startDay = firstDay.getDay();
|
When creating a date object the new keyword is
used, if no parameters are passed to the Date() function then the new
date object will be set to the current date.
Year is a leap year if it is divisible by 4,
and not by 100, unless it is divisible by 400:
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0))
days[1] = 29;
else
days[1] = 28;
|
The days[] variable is an array that holds the
number of days of each month. This can be easily created with the following
function definition and function call which creates a new array object.
The use of this allows reference to the variable days:
function array(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;
}
var days = new array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
|
The array() function can be reused to create
the names[] array to hold the names of each month:
var names = new array("Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec");
|
All that remains is to output the calendar within an
HTML table:
document.write("<table callspacing=0 cellpadding=0 border=1>");
document.write("<tr align=right>");
var column = 0;
for (i=0; i<startDay; i++)
{
document.write("<td> <\/td>");
column++;
}
|
This creates a table, starts the first row, and creates
empty cells until the startDay, i.e. first day of the month. The column
variable controls the number of days displayed across the table.
for (i=1; i<=days[Month]; i++)
{
document.write("<td>",i,"<\/td>");
column++;
if (column == 7)
{
document.write("<\/tr><tr align=right>");
column = 0;
}
}
document.write("<\/tr><\/table>");
|
This outputs all the days in the Month
in individual cells. When a whole week is output, the current table row is ended
and a new table row is started. Finally the last table row and the table are
ended.
The first draft of the Calender JavaScript
function is now complete:
<script language="JavaScript"><!--
function Calendar(Month,Year)
{
firstDay = new Date(Year,Month,1);
startDay = firstDay.getDay();
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0))
days[1] = 29;
else
days[1] = 28;
document.write("<table callspacing=0 cellpadding=0 border=1>");
document.write("<tr align=right>");
var column = 0;
for (i=0; i<startDay; i++)
{
document.write("<td> <\/td>");
column++;
}
for (i=1; i<=days[Month]; i++)
{
document.write("<td>",i,"<\/td>");
column++;
if (column == 7)
{
document.write("<\/tr><tr align=right>");
column = 0;
}
}
document.write("<\/tr><\/table>");
}
function array(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;
}
var names = new array("Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec");
var days = new array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
Calendar(1-1,1997);
//-->
</script>
|
This then displays the following:
This basic Calendar function can then be
enhanced to show the month, year and days of the week with the addition of the
following two lines:
document.write("<tr><th colspan=7>",names[Month]," ",Year);
document.write("<tr><th>S<\/th><th>M<\/th><th>T<\/th><th>W<\/th>
<th>T<\/th><th>F<\/th><th>S<\/th><\/tr>");
|
Color can be added for those browsers that support
table cell colors. First we need to define some colors to be used before calling
the Calendar function:
var thcol = "BGCOLOR='#AAACBF'";
var trcol = "BGCOLOR='#CCECFF'";
var tdcol = "BGCOLOR='#FF8888'";
|
Then whenever we use <tr> or <td>
to start a new table row or cell add the additional Bgcolor attribute, e.g.:
document.write("<tr><th colspan=7>",names[Month]," ",Year);
|
replace with:
document.write("<tr ",thcol,"><th colspan=7>",names[Month]," ",Year);
|
which when written to the document will appear as:
<tr bgcolor='#AAACBF'><th colspan=7>Jan 1997);
|
To highlight the current day we need to define another color
and show the calendar for the current month and year:
var hlcol = "bgcolor='#8888ff'";
function y2k(number) { return (number < 1000) ? number +
1900 : number; }
var today = new Date();
var thisDay = today.getDate();
var thisMonth = today.getMonth();
var thisYear = y2k(today.getYear());
Calendar(thisMonth,thisYear);
|
The JavaScript function getYear() returns the
number of years since 1900, or the year if greater than 2000, therefore we use
the y2k() function to force the year into CCYY format. As thisMonth is
a value calculated by the getMonth() function, we no longer have to
subtract 1 from the year.
When writing each day to the table cell if it is equal
to today's date use the new color instead:
if ((i == thisDay) && (Month == thisMonth) && (Year == thisYear))
document.write("<td ",hlcol,">",i,"<\/td>";
else
document.write("<td ",tdcol,">",i,"<\/td>");
|
The calendar for the current month and year now looks
like this:
To display the current years calendar the following
JavaScript can be used to call the Calendar function twelve times:
document.write("<table border><tr valign=top><td>");
Calendar(1-1,thisYear);document.write("<\/td><td>");
Calendar(2-1,thisYear);document.write("<\/td><td>");
Calendar(3-1,thisYear);document.write("<\/td><td>");
Calendar(4-1,thisYear);document.write("<\/td><\/tr>
<tr valign=top><td>");
Calendar(5-1,thisYear);document.write("<\/td><td>");
Calendar(6-1,thisYear);document.write("<\/td><td>");
Calendar(7-1,thisYear);document.write("<\/td><td>");
Calendar(8-1,thisYear);document.write("<\/td><\/tr>
<tr valign=top><td>");
Calendar(9-1,thisYear);document.write("<\/td><td>");
Calendar(10-1,thisYear);document.write("<\/td><td>");
Calendar(11-1,thisYear);document.write("<\/td><td>");
Calendar(12-1,thisYear);document.write("<\/td><\/tr>
<\/table>");
|
Since the introduction of NN4 - using multiple
document.write's in a script slows down the rendering of the page, so much so,
that the above example can take almost 30 seconds to display. There is a simple
answer to this - use fewer document writes. The following is a rewritten version
of the calendar script:
<script type="text/javascript" language="JavaScript"><!--
function Calendar(Month,Year)
{
var output = '';
firstDay = new Date(Year,Month,1);
startDay = firstDay.getDay();
if (((Year % 4 == 0) && (Year % 100 != 0)) ||
(Year % 400 == 0))
days[1] = 29;
else
days[1] = 28;
output += "<table callspacing=0 cellpadding=0>";
output += "<tr " + thcol + "><th colspan=7>" + names
[Month] + " " + Year;
output += "<tr " + trcol + "><th>S<\/th><th>M<\/th>
<th>T<\/th><th>W<\/th><th>T<\/th><th>F<\/th><th>S<\/th><\/tr>";
output += "<tr align=right>";
var column = 0;
for (i=0; i<startDay; i++)
{
output += "<td> <\/td>";
column++;
}
for (i=1; i<=days[Month]; i++)
{
if ((i == thisDay) && (Month == thisMonth) &&
(Year == thisYear))
output += "<td " + hlcol + ">" + i + "<\/td>";
else
output += "<td " + tdcol + ">" + i + "<\/td>";
column++;
if (column == 7)
{
output += "<\/tr><tr align=right>";
column = 0;
}
}
output += "<\/tr><\/table>";
return output;
}
function array(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;
}
var names = new array("Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec");
var days = new array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
var thcol = "bgcolor='#AAACBF'";
var trcol = "bgcolor='#CCECFF'";
var tdcol = "bgcolor='#FF8888'";
var hlcol = "bgcolor='#8888ff'";
function y2k(number) { return (number < 1000) ? number + 1900 : number; }
var today = new Date();
var thisDay = today.getDate();
var thisMonth = today.getMonth();
var thisYear = y2k(today.getYear());
var output = "<table border><tr valign=top><td>";
output += Calendar(1-1,thisYear) + "<\/td><td>";
output += Calendar(2-1,thisYear) + "<\/td><td>";
output += Calendar(3-1,thisYear) + "<\/td><td>";
output += Calendar(4-1,thisYear) + "<\/td><\/tr><tr valign=top><td>";
output += Calendar(5-1,thisYear) + "<\/td><td>";
output += Calendar(6-1,thisYear) + "<\/td><td>";
output += Calendar(7-1,thisYear) + "<\/td><td>";
output += Calendar(8-1,thisYear) + "<\/td><\/tr><tr valign=top><td>";
output += Calendar(9-1,thisYear) + "<\/td><td>";
output += Calendar(10-1,thisYear) + "<\/td><td>";
output += Calendar(11-1,thisYear) + "<\/td><td>";
output += Calendar(12-1,thisYear) + "<\/td><\/tr><\/table>";
document.write(output);
//--></script>
|
It uses a local output variable within the Calender()
function to hold the contents of the HTML built up, which it then returns to the
functions caller, which maintains a global output variable which is
then written to the document with just one document.write.
Which produces the following:
The final example uses a combination of JavaScript and
Forms to create a more sophisticated calendar interface. If your browser does
not support floating frames, then view the calendar
in a popup window.
It is created using two html files, one called calendar.htm,
which contains some JavaScript to set the initial month and year variables and a
Frameset with one frame containing the source file cal.htm, which
controls the calendar display.
The following diagram illustrates the relationship
between the two files:
calendar.htm (parent document)
|
|
cal.htm (child document)
The child document uses the variables established in
the parent document using the following syntax:
Calendar(parent.month,parent.year);
|
When the child document detects changes in either the
Month or Year selections, using the following Select attributes:
<select name='Month' onChange='changeMonth();'>
<select name='Year' onChange='changeYear();'>
|
the JavaScript variables within the parent document are
updated and the child document is redisplayed, e.g.:
function changeMonth () {
if (document.Cal.Month.options
[document.Cal.Month.selectedIndex].value != "")
{
parent.month1 = document.Cal.Month.options
[document.Cal.Month.selectedIndex].value;
location.href = 'cal1.htm';
}
}
function changeYear () {
if (document.Cal.Year.options
[document.Cal.Year.selectedIndex].value != "")
{
parent.year1 = document.Cal.Year.options
[document.Cal.Year.selectedIndex].value;
location.href = 'cal1.htm';
}
}
|
Where document.Cal.Year represents the document
followed by the name of the form followed by the name of the selection.
Feel free to use or adapt any of the following source
code. All I ask is that you drop me a note to say where you've used it, or what
enhancements you have made.
Complete calendar.htm source code:
<html><head><title>'No Content' - JavaScript Page</title></head>
<script language="JavaScript"><!--
function y2k(number) { return (number < 1000) ? number + 1900 : number; }
var today = new Date();
var year = y2k(today.getYear());
var month = today.getMonth();
//-->
</script>
<frameset frameborder='0' framespacing='0' ROWS='100%,*'>
<frame scrolling='no' frameborder='0' marginheight='0'
marginwidth='0' name='cal' noresize src='cal.htm'>
</frameset>
</html>
|
Complete cal.htm source code:
<HTML>
<head>
<title>'No Content' - JavaScript Page</title>
</head>
<body bgcolor="#C0C0C0" topmargin=2 leftmargin=5>
<p><center>
<script type="text/javascript" language="JavaScript"><!--
function Calendar(Month,Year)
{
var output = '';
output += "<form name='Cal'><table bgcolor='#C0C0C0'>
<tr><td align=left>";
output += "<font color='#0000BB' face='Arial' size=+1>
" + names[parent.month] + " " + parent.year + "<\/font><\/td>
<td width=50% align=right>";
output += "<select name='Month' onChange='changeMonth();'>";
for (month=0; month<12; month++)
{
if (month == parent.month)
output += "<option value='" + month + "' selected>
" + names[month] + "<\/option>";
else
output += "<option value='" + month + "'>" +
names[month] + "<\/option>";
}
output += "<\/select>";
output += "<select name='Year' onChange='changeYear();'>";
for (year=1900; year<2101; year++)
{
if (year == parent.year)
output += "<option value='" + year + "' selected>
" + year + "<\/option>";
else
output += "<option value='" + year + "'>" + year +
"<\/option>";
}
output += "<\/select><\/td><\/tr><tr><td align=center colspan=2>";
firstDay = new Date(Year,Month,1);
startDay = firstDay.getDay();
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0))
days[1] = 29;
else
days[1] = 28;
output += "<table callspacing=0 cellpadding=0 border=
1 bordercolordark='#FFFFFF' bordercolorlight='#C0C0C0'><tr>";
for (i=0; i<7; i++)
{
output += "<td width=50 align=center valign=middle>
<font size=-1 color='#000000' face='Arial'><b>" + dow[i] + "<\/b>
<\/font><\/td>";
}
output += "<\/tr><tr align=center valign=middle>";
var column = 0;
var lastMonth = Month - 1;
if (lastMonth == -1)
lastMonth = 11;
for (i=0; i<startDay; i++)
{
output += "<td width=50 height=30><font size=-1 color=
'#c0c0c0' face='Arial'>" + (days[lastMonth]-startDay+i+1) +
"<\/font><\/td>";
column++;
}
for (i=1; i<=days[Month]; i++)
{
if ((i == thisDay) && (Month == thisMonth) &&
(Year == thisYear))
output += "<td width=50 height=30 bgcolor=
'#FFFFFF' bordercolordark='#000000' bordercolorlight='#C0C0C0'>
<font size=-1 color='#FF0000' face='Arial'>" + i + "<\/font><\/td>";
else
output += "<td width=50 height=30><font size=
-1 color='#0000BB' face='Arial'>" + i + "<\/font><\/td>";
column++;
if (column == 7)
{
output += "<\/tr><tr align=center valign=middle>";
column = 0;
}
}
if (column > 0)
{
for (i=1; column<7; i++)
{
output += "<td width=50 height=30><font size=-1 color=
'#c0c0c0' face='Arial'>" + i + "<\/font><\/td>";
column++;
}
}
output += "<\/tr><\/table>";
output += "<\/form><\/td><\/tr><\/table>";
return output;
}
function array(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 changeMonth () {
if (document.Cal.Month.options
[document.Cal.Month.selectedIndex].value != "")
{
parent.month = document.Cal.Month.options
[document.Cal.Month.selectedIndex].value;
location.href = 'cal.htm';
}
}
function changeYear () {
if (document.Cal.Year.options
[document.Cal.Year.selectedIndex].value != "")
{
parent.year = document.Cal.Year.options
[document.Cal.Year.selectedIndex].value;
location.href = 'cal.htm';
}
}
function y2k(number) { return (number < 1000) ? number + 1900 : number; }
//-->
</script>
<p>
<center>
<script type="text/javascript" language="JavaScript"><!--
var names = new array("January","February","March","April","May","June",
"July","August","September","October","November","December");
var days = new array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
var dow = new array("Sun","Mon","Tue","Wed","Thu","Fri",
"Sat","","","","","");
var today = new Date();
var thisDay = today.getDate();
var thisMonth = today.getMonth();
var thisYear = y2k(today.getYear());
document.write(Calendar(parent.month,parent.year));
//-->
</script>
</center>
</body>
</html>
|
Articles | Calendars |
back
|