|
Calendars
You are here: irt.org | Articles | JavaScript | Date and Time | Calendars
Published on: Sunday 1st December 1996 By: Martin Webb
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">' +
'<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:
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 ><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 Netscape Navigator 4 - 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 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">' +
'<tr ' + thcol + '>' +
'<th colspan="7">' + names[Month] + ' ' + Year +
'<tr ' + trcol + '>' +
'<th>S</th>' +
'<th>M</th>' +
'<th>T</th>' +
'<th>W</th>' +
'<th>T</th>' +
'<th>F</th>' +
'<th>S</th>' +
'</tr>' +
'<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>' +
Calendar(1-1,thisYear) +
'</td><td>' +
Calendar(2-1,thisYear) +
'</td><td>' +
Calendar(3-1,thisYear) +
'</td><td>' +
Calendar(4-1,thisYear) +
'</td></tr><tr valign="top"><td>' +
Calendar(5-1,thisYear) +
'</td><td>' +
Calendar(6-1,thisYear) +
'</td><td>' +
Calendar(7-1,thisYear) +
'</td><td>' +
Calendar(8-1,thisYear) +
'</td></tr><tr valign="top"><td>' +
Calendar(9-1,thisYear) +
'</td><td>' +
Calendar(10-1,thisYear) +
'</td><td>' +
Calendar(11-1,thisYear) +
'</td><td>' +
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.
View the complete calendar.htm
and cal.htm source code.
Feedback on 'Calendars'
View the profile on Martin Webb and the list of other Articles by Martin Webb.
|
|