Write the Document Object Methods
You may have noticed that each table cell possesses an
onClick event handler that points to a function called
changeDate() and that the four navigation strings call a function called
changeMonth(). You must declare these functions outside of the calendar object even though doing that breaks the object-oriented principle of encapsulation, because the
document object raises the events they handle, not the calendar object.
The project uses some JavaScript trickery to get a reference to the current calendar object. Basically, it converts a string parameter into the current calendar object by passing the argument through the
eval() function. The caveat is that when you create the calendar object, the
id parameter you pass in must be the same as the variable name you declare. This is a small price to pay to keep a reference to the current calendar. Here's the
changeDate() function"
function changeDate(td,cal){
// Some JavaScript trickery
// Change the cal argument to the existing
// calendar object
// This is why the first argument in the
// constructor must match the variable name
// The cal reference also allows for
// multiple calendars on a page
cal = eval(cal);
document.getElementById(cal.id +
"selected").className = "days";
document.getElementById(cal.id +
"selected").id = "";
td.className = "date";
td.id = cal.id + "selected";
// set the calendar object to the new date
cal.dateObject.setDate(td.firstChild.nodeValue);
cal = new calendar(cal.id,cal.dateObject,cal.pix);
// here is where you could react to a date change—
// I'll just display the formatted date
alert(cal.getFormattedDate());
}
In essence, after converting the cal argument into the calendar object, the
changeDate() function uses the
td reference to exchange the current date's CSS class with the newly clicked-on date. It then sets the date of the internal Date object to the value stored in the cell. Finally, for testing purposes, it displays the formatted date in an alert boxbut you can choose to handle the date swap any way you choose.
The
changeMonth() function moves the calendar to the next or previous month. It uses the
eval() trickery you've already employed in this function to retain a reference to the current calendar object. The good news is that the Date object and, indirectly, the calendar object is smart enough to roll the year forward and backward when necessary. Here's the
changeMonth() method:
function changeMonth(mo,cal){
// more trickery!
cal = eval(cal);
// The Date object is smart enough to
// know that it should roll over in December
// when going forward and in January
// when going back
cal.dateObject.setMonth(cal.dateObject.getMonth() + mo);
cal = new calendar(cal.id,cal.dateObject,cal.pix);
cal.formattedDate = cal.getFormattedDate();
document.getElementById('calContainer').innerHTML = cal.write();
}
Save the file as
calendar.js in the same folder as the CSS file.
Create the HTML File
At this point, creating an HTML file to display the calendar is pretty simplethe calendar object itself does most of the work. Open a new file in your text editor and create the following HTML file:
<html>
<head>
<title>Calendar Demo</title>
<script src="calendar.js"
type="text/javascript"></script>
<link rel="stylesheet" type="text/css"
href="calendar.css"/>
</head>
<body>
<script language="JavaScript">
// create the pix array
var pix = new Array();
for(i=0; i<12; i++){
pix[i] = new Image();
pix[i].src = 'images/fractal' + i + '.jpg';
}
// Place this script wherever you want your calendar
// The first argument must match the var name
var thisMonth = new calendar('thisMonth',new
Date(),pix);
document.write(thisMonth.write());
</script>
</body>
</html>
Note that you need to create the
pix array on the HTML page, rather than in the JavaScript file. This makes sense from an object-oriented standpointthe pictures for any given calendar are page specific. The
sample code uses a naming convention and a
for loop to create the image array. Save the file in the same directory as the CSS and JavaScript file.
The Façade design pattern works well in this application. It exposes the data available in the JavaScript Date object, removing the necessity for working directly with the Date object itself, and customizing its functionality specifically for the calendar application. Because the calendar uses some W3C DOM methods in the
changeDate() method, you'll need to deploy the calendar component in a browser that adheres to the W3C DOM specification. I tested the calendar application in Mozilla Firebird 0.7, Opera 7.1, and Internet Explorer 6 and it worked beautifully in all three browsers.