/*
Purpose: Generic calendar code

Original author: Robert Seber
Author's version: 26
Passed testing on: IE5 PC, IE5 Mac, NS4 PC, NS6 PC, NS4 Mac

Modifications made by: 
Reasons for modification: 
Modifier's version: 
Passed testing on: 
*/

// Extend date functions

Date.prototype.getDayNum   = function(){      return this.getDate()    }
Date.prototype.setDayNum   = function(day){   this.setDate(day)        }
Date.prototype.getMonthNum = function(){      return this.getMonth()+1 }
Date.prototype.setMonthNum = function(month){ this.setMonth(month-1)   }
Date.prototype.getYearNum  = function(){      return this.getFullYear()}
Date.prototype.setYearNum  = function(year){  this.setYear(year)       }

Date.prototype.getDayOfWeekNum = function(firstDay){
	var day = this.getDay()-firstDay;
	if (day < 0) return day + 7;
	else return day;
}

Date.prototype.setDayMonthYear = function(day,month,year){
	this.setFullYear(year);
	this.setMonth(month-1);
	this.setDate(day);
	this.setHours(12);
}

Date.prototype.addDay = function(){
	this.setDate(this.getDate()+1);
}

Date.prototype.addMonth = function(){
	this.setMonth(this.getMonth()+1);
}

Date.prototype.addYears = function(numberOfYears){
	this.setYear(this.getFullYear()+numberOfYears);
}

Date.prototype.copyTo = function(date2){
	date2.setTime(this.getTime());
}

Date.prototype.getMonthComparator = function(){//Returns int to allow comparison
	return this.getYearNum()*100 + this.getMonthNum();
}

Date.prototype.getDayComparator = function(){//Returns int to allow comparison
	return this.getYearNum()*10000 + this.getMonthNum()*100 + this.getDayNum();
}

Date.isDate = function(day,month,year){//Checks if a date is valid
	if (year>999 && year<10000){
		var dt = new Date(year,month-1,day);
		return dt.getDate()==day && dt.getMonth()==month-1 && dt.getFullYear()==year;
	}
	return false;
}

//Calendar initialisation functions

function Calendar(){
	this.width = 190;
	this.height = 275;
	this.firstDayOfWeek = 1;
	this.todaysDate = new Date();
	this.selectedDate = new Date();
	this.earliestDate = new Date();
	this.earliestDate.setDayMonthYear(1,1,1000);
	this.latestDate = new Date();
	this.latestDate.setDayMonthYear(1,1,3000);
	this.viewDate = new Date();
	this.counterDate = new Date();
	this.outputWindow = new Object();
	this.getFormDay = new Function();
	this.getFormMonth = new Function();
	this.getFormYear = new Function();
	this.setFormDate = new Function();
	this.clearFormDate = new Function();
	this.id = Math.ceil(Math.random()*99999);
	this.outputHtml = "";
	this.styleSheetPath = "";
	this.showTodayControl = true;
	this.showClearControl = true;
	this.showYearControls = true;
	this.showDecadeControls = true;
	this.monthsText = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
	this.dayText = new Array("M","T","W","T","F","S","S");
	this.nextYearText = "Next";
	this.previousYearText = "Prev";
	this.nextDecadeText = " Next 10";
	this.previousDecadeText = "Prev 10";
	this.todayText = "Today";
	this.clearText = "Clear Form";
	this.closeText = "Close";
	this.validSelectedDate = false;
}

Calendar.prototype.setTodaysDate = function(day,month,year){
	this.todaysDate.setDayMonthYear(day,month,year);
}

Calendar.prototype.setSelectedDate = function(day,month,year){
	this.selectedDate.setDayMonthYear(day,month,year);
	this.setViewDate(day,month,year);
}

Calendar.prototype.setEarliestDate = function(day,month,year){
	this.earliestDate.setDayMonthYear(day,month,year);
}

Calendar.prototype.setLatestDate = function(day,month,year){
	this.latestDate.setDayMonthYear(day,month,year);
}

Calendar.prototype.setViewDate = function(day,month,year){
	this.viewDate.setDayMonthYear(day,month,year);
}

//Output functions

Calendar.prototype.writeLn = function(text){
	this.outputHtml += text + "\n";
}

Calendar.prototype.writeTableStart = function(){
	this.writeLn('<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td class="tableborder">');
	this.writeLn('<table width="100%" border="0" cellspacing="1" cellpadding="2">');
}

Calendar.prototype.writeTableDivider = function(){
	this.writeLn('</td></tr><tr><td>');
}

Calendar.prototype.writeTableEnd = function(){
	this.writeLn('</table>');
	this.writeLn('</td></tr></table>');
}

Calendar.prototype.writeCalendar = function(){
	this.outputHtml = "";
	this.outputWindow.document.open();
	this.writeLn('<html><head>');
	if (!isIEPC()) this.writeLn('<base href="' + window.location.href + '">');
	this.writeLn('<title>Calendar</title>');
	this.writeLn('<link rel="StyleSheet" href="'+this.stylesheetPath+'" type="text/css">');
	this.writeLn('</head>');
	this.writeLn('<body marginheight="0" marginwidth="0" topmargin="0" leftmargin="0"><center>');
	this.writeLn('<table border="0" width="100%" cellspacing="0" cellpadding="2"><tr><td class="background">');
	this.writeYearControls();
	this.writeTableDivider();
	this.writeMonthControls();
	this.writeTableDivider();
	this.writeMonth();
	this.writeBottomControl(this.showTodayControl,"calendar.selectToday()",this.todayText);
//	this.writeBottomControl(this.showClearControl,"calendar.clear()",this.clearText);
	this.writeBottomControl(true,"window.close()",this.closeText);
	this.writeLn('</td></tr></table>');
	this.writeLn('</center></body></html>');
	this.outputWindow.document.write(this.outputHtml);
	this.outputWindow.document.close();
	this.outputHtml = "";
	this.outputWindow.calendar = this;
}

Calendar.prototype.writeYearControls = function(){
	this.writeTableStart();
	var earliestYear = this.earliestDate.getYearNum();
	var viewYear = this.viewDate.getYearNum();
	var latestYear = this.latestDate.getYearNum();
	this.writeLn('<tr>');
	if (this.showYearControls) this.writeYearControl(viewYear>earliestYear,'changeViewYear(-1)',this.previousYearText);
	if (this.showDecadeControls) var params = ' rowspan="2"';
	else var params = "";
	this.writeLn('<td class="year" width="40%"'+params+'">&nbsp;' + this.viewDate.getYearNum() + '&nbsp;</td>');
	if (this.showYearControls) this.writeYearControl(viewYear<latestYear,'changeViewYear(1)',this.nextYearText);
	this.writeLn('</tr>');
	if (this.showDecadeControls) {
		this.writeLn('<tr>');
		this.writeYearControl(viewYear-10>=earliestYear,'changeViewYear(-10)',this.previousDecadeText);
		this.writeYearControl(viewYear+10<=latestYear,'changeViewYear(10)',this.nextDecadeText);
		this.writeLn('</tr>');
	}
	this.writeTableEnd();
}

Calendar.prototype.writeYearControl = function(isEnabled,methodText,displayText){
	if (isEnabled){
		this.writeLn('<td class="control" width="30%" nowrap><a href="javascript:calendar.'+methodText+'">&nbsp;'+displayText+'&nbsp;</a></td>');
	} else {
		this.writeLn('<td class="disabledcontrol" width="30%" nowrap>&nbsp;'+displayText+'&nbsp;</td>');
	}
}

Calendar.prototype.writeMonthControls = function(){
	this.viewDate.copyTo(this.counterDate);
	this.counterDate.setMonthNum(1);
	this.writeTableStart();
	this.writeLn('<tr>');
	for (var i=1;i<=12;i++){
		if (this.counterDate.getMonthComparator()<this.earliestDate.getMonthComparator() || this.counterDate.getMonthComparator()>this.latestDate.getMonthComparator()){
			this.writeLn('<td class="disabledmonth" width="17%">'+this.monthsText[i-1]+'</td>');
		} else if (this.counterDate.getMonthComparator()==this.viewDate.getMonthComparator()){
			this.writeLn('<td class="viewmonth" width="17%">'+this.monthsText[i-1]+'</td>');
		} else {
			this.writeLn('<td class="month" width="17%"><a href="javascript:calendar.viewMonth('+i+')">'+this.monthsText[i-1]+'</a></td>');
		}
		if (i==6) this.writeLn('</tr><tr>');
		this.counterDate.addMonth();
	}
	this.writeLn('</tr>');
	this.writeTableEnd();
}

Calendar.prototype.writeMonth = function(){
	this.viewDate.copyTo(this.counterDate);
	this.writeTableStart();
	this.writeLn('<tr>');
	for (var i=0;i<7;i++){
		this.writeLn('<td class="dayofweek" width="14%">'+this.dayText[i]+'</td>');
	}
	this.writeLn('</tr>');
	var i=0;
	while (this.counterDate.getMonthNum()==this.viewDate.getMonthNum()){
		this.writeWeek();
		i++;
	}
	if (i<6){
		this.writeLn('<tr>');
		this.writeBlankDays(7);
		this.writeLn('</tr>');
	}
	this.writeTableEnd();
}

Calendar.prototype.writeWeek = function(){
	this.writeLn('<tr>');
	var dayOfWeek = this.counterDate.getDayOfWeekNum(this.firstDayOfWeek);
	this.writeBlankDays(dayOfWeek);
	var i;
	for (i=dayOfWeek;i<7;i++){
		if (this.counterDate.getMonthNum()==this.viewDate.getMonthNum()){
			this.writeDay();
		} else break;
	}
	this.writeBlankDays(7-i);
	this.writeLn('</tr>');
}

Calendar.prototype.writeDay = function(){
	var day = this.counterDate.getDayNum();
	var month = this.counterDate.getMonthNum();
	var year = this.counterDate.getYearNum();
	if (this.counterDate.getDayComparator()>=this.earliestDate.getDayComparator() && this.counterDate.getDayComparator()<=this.latestDate.getDayComparator()) {
		if (this.validSelectedDate && this.counterDate.getDayComparator()==this.selectedDate.getDayComparator()){
			this.writeLn('<td class="selectedday" width="14%"><a href="javascript:calendar.selectDay('+day+','+month+','+year+')">'+this.counterDate.getDayNum()+'</a></td>');
		} else {
			this.writeLn('<td class="day" width="14%"><a href="javascript:calendar.selectDay('+day+','+month+','+year+')">'+this.counterDate.getDayNum()+'</a></td>');
		}
	} else {
		this.writeLn('<td class="disabledday" width="14%">'+this.counterDate.getDayNum()+'</td>');
	}
	this.counterDate.addDay();
}

Calendar.prototype.writeBlankDays = function(colspan){
	if (colspan>0) this.writeLn('<td colspan="'+colspan+'" class="blankday">&nbsp;</td>');
}

Calendar.prototype.writeBottomControl = function(isEnabled,methodText,displayText){
	if (isEnabled){
		this.writeTableDivider();
		this.writeTableStart();
		this.writeLn('<tr><td class="control"><a href="javascript:'+methodText+'">&nbsp; &nbsp; &nbsp; &nbsp; '+displayText+' &nbsp; &nbsp; &nbsp; &nbsp;</a></td></tr>');
		this.writeTableEnd();
	}
}

//User actions

function isIEPC(){
	return navigator.platform.indexOf("Win")!=-1 && navigator.appVersion.indexOf("MSIE")!=-1;
}

Calendar.prototype.open = function(){
	var yearSpan = this.latestDate.getYearNum()-this.earliestDate.getYearNum();
	if (yearSpan == 0){
		this.showYearControls = false;
		this.showDecadeControls = false;
	} else {
		this.showYearControls = true;
		if (yearSpan >= 10) this.showDecadeControls = true;
		else this.showDecadeControls = false;
	}
	if (this.todaysDate.getDayComparator()>this.earliestDate.getDayComparator() && this.todaysDate.getDayComparator()<this.latestDate.getDayComparator()){
		this.showTodayControl = true;
	} else {
		this.showTodayControl = false;
	}
	var formDay = this.getFormDay();
	var formMonth = this.getFormMonth();
	var formYear = this.getFormYear();
	this.validSelectedDate = Date.isDate(formDay,formMonth,formYear);
	if (this.validSelectedDate){
		this.setSelectedDate(formDay,formMonth,formYear);
		if (this.selectedDate.getMonthComparator()<this.earliestDate.getMonthComparator()){
			this.earliestDate.copyTo(this.viewDate);
		} else if (this.selectedDate.getMonthComparator()>this.latestDate.getMonthComparator()){
			this.latestDate.copyTo(this.viewDate);
		}
	}
	if (isIEPC()){
		this.close();
		//Fixes access / callee bug in IE PC
	}
	this.outputWindow = window.open("javascript:''","calendar" + this.id,"width="+this.width+",height="+this.height+",noresize");
	this.viewDate.setDayNum(1);
	this.writeCalendar();
	this.outputWindow.focus();
}

Calendar.prototype.close = function(){
	if (this.outputWindow && this.outputWindow.close) this.outputWindow.close();
}

Calendar.prototype.clear = function(){
	this.clearFormDate();
	this.validSelectedDate = false;
	this.close();
}

Calendar.prototype.selectDay = function(day,month,year){
	this.setSelectedDate(day,month,year);
	this.setFormDate(day,month,year);
	this.close();
}

Calendar.prototype.viewMonth = function(month){
	this.viewDate.setMonthNum(month);
	this.writeCalendar();
}

Calendar.prototype.selectToday = function(){
	this.todaysDate.copyTo(this.viewDate);
	this.todaysDate.copyTo(this.selectedDate);
	this.setFormDate(this.selectedDate.getDayNum(),this.selectedDate.getMonthNum(),this.selectedDate.getYearNum());
	this.viewDate.setDayNum(1);
	this.writeCalendar();
}

Calendar.prototype.changeViewYear = function(changeBy){
	this.viewDate.addYears(changeBy);
	if (this.viewDate.getMonthComparator()<this.earliestDate.getMonthComparator()) this.viewDate.setMonthNum(this.earliestDate.getMonthNum());
	else if (this.viewDate.getMonthComparator()>this.latestDate.getMonthComparator()) this.viewDate.setMonthNum(this.latestDate.getMonthNum());
	this.writeCalendar();
}
