function Calendar(calName, passedDate, fullDisplay)
{
	// make sure the passed date is valid, and set it to the current and selected date
	this.m_curDate = new Date(passedDate);
	if (!this.m_curDate.getTime()) this.m_curDate = new Date();
	this.m_selDate = new Date(this.m_curDate);

	// setup the member variables
	this.m_name = calName;
	this.m_fullDisplay = fullDisplay;

	// define the number of days in each month, the short day names
	this.m_daysInMonths = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	this.m_shortDayNames = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');

	// handle if the passed date is a leap year
	var year = this.m_selDate.getYear();
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) this.m_daysInMonths[1] = 29;

	// allow for wrapping the current data in brackets
	this.m_wrapInBrackets = false;

	// define the class functions
	this.init = function()
	{
		// update the date field with the currently selected date
		document.getElementById(this.m_name).value = this.m_selDate.getFullYear() + '-' + (this.m_selDate.getMonth() + 1) + '-' + this.m_selDate.getDate();
	};

	this.update = function(varChange, value)
	{
		// update the date based on what we want changed
		switch (varChange) {
		case 'month':
			// handle if the date selected is larger than the number of days in the selected month
			if (this.m_selDate.getDate() > this.m_daysInMonths[value]) this.m_selDate.setDate(this.m_daysInMonths[value]);

			// update the month of the current date
			this.m_selDate.setMonth(value - 1);

			break;
		case 'year':
			// update the year of the current date
			this.m_selDate.setYear(value);

			// handle the leap years
			if ((this.m_selDate.getFullYear() % 4 == 0 && this.m_selDate.getFullYear() % 100 != 0) || this.m_selDate.getFullYear() % 400 == 0) this.m_daysInMonths[1] = 29;
			else this.m_daysInMonths[1] = 28;

			break;
		case 'day':
			// update the day of the current date
			this.m_selDate.setDate(value);

			break;
		case 'date':
			// update the date of the current date
			this.m_selDate = new Date((this.m_selDate.getMonth() + 1) + '/' + value + '/' + this.m_selDate.getFullYear());
			this.m_curDate = new Date(this.m_selDate);

			// update the hidden field
			document.getElementById(this.m_name).value = this.m_selDate.getFullYear() + '-' + (this.m_selDate.getMonth() + 1) + '-' + this.m_selDate.getDate();

			break;
		case 'time':
			this.m_selDate.setTime(value);
		}

		if (this.m_fullDisplay) {
			// display the calendar if we should
			document.getElementById(this.m_name + '_display').innerHTML = this.display();
		} else {
			// update the month select so we know we're displaying the correct date
			var m = document.getElementById(this.m_name + '_month');
			if (m) m.selectedIndex = this.m_selDate.getMonth();

			// update the day select, so we can't choose anything wrong
			var s = document.getElementById(this.m_name + '_day');
			if (s) {
				// clear the select box, and refill it
				while (s.length) s.options[0] = null;
				for (var i = 0; i < this.m_daysInMonths[this.m_selDate.getMonth()]; ++i) s.options[i] = new Option(i + 1, i + 1);

				// select the item that should be selected
				s.selectedIndex = this.m_selDate.getDate() - 1;
			}

			// update the year if we should
			if (varChange == 'time') {
				var y = document.getElementById(this.m_name + '_year');
				if (y) y.value = this.m_selDate.getFullYear();
			}

			// update the hidden field
			document.getElementById(this.m_name).value =  this.m_selDate.getFullYear() + '-' + (this.m_selDate.getMonth() + 1) + '-' + this.m_selDate.getDate();
		}
	};

	this.display = function(wrapInBrackets)
	{
		if (typeof(wrapInBrackets) != 'undefined') this.m_wrapInBrackets = wrapInBrackets;
		var ret = '';

		// make the table, and weekday head display
		ret += '<table border="0" cellspacing="1" cellpadding="0" width="100%">';
		ret += '<tr align="center">';
		for (var i = 0; i < this.m_shortDayNames.length; ++i) {
			ret += '<th width="13%">' + this.m_shortDayNames[i] + '</th>';
		}
		ret += '</tr>';
		ret += '<tr>';

		// copy the current date, so we can work with it
		var tempDate = new Date(this.m_selDate);

		// get the first day of the currently displayed month
		tempDate.setDate(1);

		// make the previous months days that should be visible
		var j = 0;
		var beginDate = new Date(tempDate.getTime() - 1000 * 60 * 60 * 24 * tempDate.getDay());
		if (beginDate.getTime() != this.m_selDate.getTime()) {
			while (beginDate.getDate() != 1) {
				j++;
				if (j == 1 || j == 7) ret += '<td align="center" class="othermonth_weekend">' + beginDate.getDate() + '</td>';
				else ret += '<td align="center" class="othermonth_weekday">' + beginDate.getDate() + '</td>';
				beginDate.setTime(beginDate.getTime() + 1000 * 60 * 60 * 24);
			}
		}

		// handle the leap year
		if ((this.m_selDate.getFullYear() % 4 == 0 && this.m_selDate.getFullYear() % 100 != 0) || this.m_selDate.getFullYear() % 400 == 0) this.m_daysInMonths[1] = 29;
		else this.m_daysInMonths[1] = 28;

		// display the days of the current month
		for (i = 1; i <= this.m_daysInMonths[this.m_selDate.getMonth()]; i++) {
			j++;
			ret += '<td align="center" ';

			if (i == this.m_curDate.getDate() && this.m_curDate.getMonth() == this.m_selDate.getMonth() && this.m_curDate.getFullYear() == this.m_selDate.getFullYear()) {
				// display the selected date
				var selected_day = i;
				if (this.m_wrapInBrackets) selected_day = '[' + i + ']';
				ret += 'class="selected_day">' + selected_day + '</td>';
			} else {
				// display every other day of the month
				ret += ((j == 1 || j == 7) ? 'class="thismonth_weekend" ' : 'class="thismonth_weekday" ') + 'style="cursor:pointer" onclick="' + this.m_name + '_cal.update(\'date\', ' + i + ')">' + i + '</td>';
			}

			if (j > 6) {
				ret += '</tr><tr>';
				j = 0;
			}
		}

		// display the next months days that should be visible
		if (j != 0)
		{
			z = j;
			for (i = 1; i <= (7 - z); i++) {
				j++;
				ret += '<td align="center" ';
				if (j == 1 || j == 7) ret += 'class="othermonth_weekend"';
				else ret += 'class="othermonth_weekday"';
				ret += '>' + i + '</td>';
			}
		}

		ret += '</tr></table>';

		return ret;
	};

	// init the calendar
	this.init();
}
