//<!--//---------------------------------------------------------------------------//// File:    DHTMLCal.js// Version: 2.02//// Purpose: This is the source file for DHTML Javascript Calendar////	    This program is shareware.//          Please find all Shareware information at//          http://www.geocities.com/dshipe/cadown.htm//// Author:  Dan Shipe//	    312 Druid Oaks Drive//          Atlanta GA 30329//          dshipe@yahoo.com//          http://www.geocities.com/dshipe/////    Date     By   Ver   Description// ----------  ---  ----  ---------------------------------------------------// 09-01-2000  DS   1.00  Initial creation// 04-10-2001  DS   1.01  Now supports Netscape 6, Gekko// 05-30-2001  DS   1.02  Added cookies to track month & year if user "refreshs"// 07-06-2001  DS   1.03  Fixed bug to set main table border color to mclrBorder// 07-09-2001  DS   1.04  Added DHTMLCal_PopUp to support event pop-up windows// 07-10-2001  DS   1.05  Added support to place text in dead cells// 08-23-2001  DS   1.06  Added inidividual date cell custom colors// 08-30-2001  DS   1.07  Added booleans to hide Month and Year drop-downs// 09-04-2001  DS   1.08  Supports "every month" and "every year" dates// 09-11-2001  DS   1.09  A week may now begin Sunday or Monday// 11-16-2001  DS   1.10  Added independent active weekend color// 01-03-2001  DS   1.11  Supports relatively positioned DHTML elements in NS 4.75// 03-03-2002  DS   2.00  Object Oriented Design// 04-10-2002  DS   2.01  Fix for floating year and null weekday// 06-24-2002  DS   2.02  Fix for Monday weeks and first day is Sundayvar maEvents = new Array();var msKey = "k1!2db/84$jrgoop!upu.ou6lnuhtwxlocslt9xp/h5t";// ************************************************************// ***  CALENDAR class and related functions// ************************************************************// constructor for calendar classfunction Calendar (name) {	this.r = "\r\n";	this.q = "\"";		this.name = name;	// table cell sizes	this.cellWidth  = 100;	// width of weekday columns and dates	this.cellHeight = 90;   // height of date cells 	// flags	this.beginMonday 		= false;	//Adjust the maLongDays array if TRUE	this.displayDeadText 		= false;	this.displayDeadNumber 		= false;	this.displayMonthCombo 		= true;	this.displayYearCombo 		= true;	this.todayText 			= null;		// colors	this.clrTable	= "#fffffe";    // table background DO NOT CHANGE	this.clrDead	= "#c0c0c0";	// background color - unused this month	this.clrNow	= "#ffffc0";	// background color - the current date	this.clrPast	= "#e0e0e0";	// background color - previous dates	this.clrFuture	= "#ffffff";	// background color - future dates	this.clrWeekend	= null;	        // background color - weekend dates	this.clrBorder	= "#800000";	// border color of calendar	this.clrHdrBg   = "#c04040";	// header background (sun, mon, tues...)   	this.clrHdrText	= "#ffffff";	// header test color	this.clrCellText= "#800000";	// event text color		// fonts	var szFont = "Arial, Helvetica, Sans Serif";	this.hdrFace	= szFont;	this.hdrSize	= "2";	this.numFace	= szFont;	this.numSize	= "3";	this.cellFace	= szFont;	this.cellSize	= "2";	// arrays	this.daysPerMonth = new Array( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); 	this.longMonths   = new Array( "January", "February", "March", "April",	 		"May", "June", "July", "August", 			"September", "October", "November", "December" );	this.longDays = new Array( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" );	// methods	this.createDateSelect = dcCreateDateSelect;	this.fillMonth = dcFillMonth;	this.fillYear = dcFillYear;	this.chkLeapYear = dcChkLeapYear;	this.createCalendar = dcCreateCalendar;	this.calendarHTML = dcCalendarHTML;	this.chkColor = dcChkColor;	this.getDay = dcGetDay;	this.isWeekday = dcIsWeekday;};// ------------------------------------------------------------function dcCreateDateSelect() {	var szHTML;	var szTag;		var szHide;	var szOutput = "";	var dteCurr = new Date();	var cy = dteCurr.getFullYear();	var m = dcReadDate("m");	var y = dcReadDate("y");	// exit if user doesn't want the month or year drop-downs	if (this.displayMonthCombo==false 	&& this.displayYearCombo==false) return null;	// begin form	szHTML = "<form name='frmCal' method='post' action=''>" + this.r;	szOutput = szOutput + szHTML;	// begin table	szHTML = "<table"		+ " align=center"		+ " width='" + ((this.cellWidth) * 7) + "'"		+ " border='1'"		+ " bordercolor='" + this.clrBorder + "'"		+ " bordercolordark='" + this.clrBorder + "'"		+ " bordercolorlight='" + this.clrBorder + "'"		+ " cellspacing=0"//		+ " cellpadding=4"		+ " >" + this.r;	szOutput = szOutput + szHTML;	// month & year selector	szHTML = "<tr><td"		+ " align=center"		+ " bgcolor=" + this.clrHdrBg//		+ " colspan = 7"		+ " >" + this.r + this.r;	szOutput = szOutput + szHTML;	// month combo	szTemp = " cboYear.options[frmCal.cboYear.selectedIndex].value";	if (this.displayYearCombo==false) szTemp = y.toString();	szHTML = "<select name='cboMonth'"		+ " onchange='dcUpdate(" + this.name + ", " + this.r		+ " cboMonth.options[frmCal.cboMonth.selectedIndex].value"		+ "," + this.r		+ szTemp		+ ");'>" + this.r		+ this.fillMonth(m)		+ "</select>" + this.r + this.r;	if (this.displayMonthCombo==true) szOutput = szOutput + szHTML;	// year combo	szTemp = " cboMonth.options[frmCal.cboMonth.selectedIndex].value";	if (this.displayMonthCombo==false) szTemp = m.toString();	szHTML = "<select name='cboYear'"		+ " onchange='dcUpdate(" + this.name + ", " + this.r		+ szTemp		+ "," + this.r		+ " cboYear.options[frmCal.cboYear.selectedIndex].value"		+ ");'>" + this.r		+ this.fillYear(y, cy)		+ "</select>" + this.r + this.r;	if (this.displayYearCombo==true) szOutput = szOutput + "&nbsp;" + szHTML;	szHTML = "</td></tr>" + this.r;	szOutput = szOutput + szHTML;	// end the table	szOutput = szOutput + "</table></form>" + this.r + this.r;	document.writeln(szOutput);	return szOutput;};// ------------------------------------------------------------function dcCreateCalendar(m, y) {	var obj;	var szHTML;	var bRedraw = true;	var szBrowName = dcBrowserName();	var szBrowVer = dcBrowserVer();	if (m==null && y==null) {		bRedraw = false;		m = dcReadDate("m");		y = dcReadDate("y");	};	// write the current month and year to a cookie	// will expire in one hour	dcSaveDate(m, y)	// get the html for the calendar	szHTML = this.calendarHTML( m, y );	if ( szBrowName=="IE" ) {		// microsoft internet explorer (handle ver 4 & 5)		if (bRedraw==true) {			document.all["MSIE"].innerHTML = szHTML;		} else {			document.writeln(szHTML);		};			} else if ( szBrowName=="NS" ) {		if ( szBrowVer<"5" ) {			// netscape version 4			if (bRedraw==true) {				document.NSALIGN.document.NSLAYER.document.write(szHTML);				document.NSALIGN.document.NSLAYER.document.close();			} else {				document.NSALIGN.document.NSLAYER.document.writeln(" ");				document.NSALIGN.document.NSLAYER.document.writeln(szHTML);				document.NSALIGN.document.NSLAYER.document.writeln(" ");			};					} else {			// netscape version 5 and up					obj = document.getElementById("MSIE");			dcSetInnerHTML(obj, szHTML);		};	};};// ---------------------------------------------------------------------------------------function dcChkColor( nRow, nCol, dteCal, dteNow, m ) {	var szID = "c" + nCol + "r" + nRow; 	var currD = this.getDay(dteCal);	var currM = dteCal.getMonth();	var currY = dteCal.getYear();	if ( currD > nCol + (nRow * 7) || currM != m ) return this.clrDead;	if (this.clrWeekend!=null && this.isWeekday(dteCal)==false) return this.clrWeekend;		
	if (dteCal.getYear() < dteNow.getYear()) return this.clrPast;	if (dteCal.getYear() > dteNow.getYear()) return this.clrFuture;	if (dteCal.getMonth() < dteNow.getMonth() ) return this.clrPast;	if (dteCal.getMonth() > dteNow.getMonth() ) return this.clrFuture;	if (dteCal.getDate() < dteNow.getDate()) return this.clrPast;	if (dteCal.getDate() > dteNow.getDate()) return this.clrFuture;	return this.clrNow;};// ------------------------------------------------------------function dcCalendarHTML( m, y ) {	var chkM, chkD, chkY	var szBackcolor;	var szEvText;	var szEvForecolor, szEvBackcolor;	var szOutput, szHTML;	var szCell, szNum;	var szText;	var szTag;	var nRow, nCol;	var nDeadDay;	var nWidth;	var bGoodDate=false;		var dteNow = new Date();	var dteCal = new Date(y, m, 1);	var dteMonth = new Date(y, m, 1);	szOutput = "";	// check for leap year	this.chkLeapYear(m, y);	// find the first day and subtract back to Sun	dteCal.setDate( dteCal.getDate() - this.getDay(dteCal) );	// if week begins with Monday, we must check that first day is not Sunday	if ( dteCal.getDate() == 2 ) dteCal.setDate( dteCal.getDate() - 7 );	// determine the sequence of the "dead" cells	nDeadDay = dteMonth.getDate() - this.getDay(dteMonth);  	// set the column width (fix for Netscape NOWRAP)	nWidth = this.cellWidth;	if (dcBrowserName=="NS") nWidth = nWidth - 15;	// begin table	szHTML = "<table align=center"		+ " bgColor=" + this.clrTable		+ " border='1'"		+ " bordercolor='" + this.clrBorder + "'"		+ " bordercolordark='" + this.clrBorder + "'"		+ " bordercolorlight='" + this.clrBorder + "'"		+ " width='" + (this.cellWidth * 7) + "'"		+ " cellspacing=0"		+ " cellpadding=4"		+ " >";	szOutput = szOutput + szHTML + this.r + this.r;	// create the WEEKDAY headers	szOutput = szOutput + "<tr>" + this.r;	for (nCol=0; nCol<7; nCol++) {		szHTML = "<td align=center"			+ " width=" + nWidth 			+ " bgcolor=" + this.clrHdrBg			+ " nowrap "			+ " >"			+ dcFontStr( this.hdrFace, this.hdrSize, this.clrHdrText )			+ " <b><center>" + this.longDays[nCol]			+ " </center></b></font></td>";		szOutput = szOutput + szHTML + this.r;	}	szOutput = szOutput + "</tr>" + this.r + this.r;	// create calendar grid ( 7 columns by 6 rows ) 	for (nRow=0; nRow<6; nRow++) {		szOutput = szOutput + "<tr>";		for (nCol=0; nCol<7; nCol++) {			ev = null;			szBackcolor = this.chkColor( nRow, nCol, dteCal, dteNow, m );			szNum = dteCal.getDate();			if (szBackcolor == this.clrDead) {				if (this.displayDeadText==false) {					if (this.displayDeadNumber==false) szNum="&nbsp;";					ev = evChkForEvent(parseInt(m), nDeadDay, parseInt(y));				} else {					ev = evChkForEvent2(dteCal);				};			} else {				ev = evChkForEvent2(dteCal);			};			szEvText = "&nbsp;";			szEvForecolor = this.clrCellText;			szEvBackcolor = szBackcolor;			if (ev!=null) {				if (dteCal.getDate()<=31 || decode(msKey)==document.location) {					if (ev.text!="" && ev.text!=null) szEvText= ev.text;					if (ev.forecolor!="" && ev.forecolor!=null) szEvForecolor = ev.forecolor;					if (ev.backcolor!="" && ev.backcolor!=null) szEvBackcolor = ev.backcolor;				};			};				// today text			if (this.todayText!="" && this.todayText!=null) {				if (szEvText=="&nbsp;" && szBackcolor==this.clrNow) szEvText = this.todayText;			};			// HTML for Event			szCell = dcFontStr(this.numFace, this.numSize, szEvForecolor) + this.r				+ "<strong>" + szNum + "</strong></font>" + this.r				+ "<br>"				+ dcFontStr(this.cellFace, this.cellSize, szEvForecolor) + this.r				+ szEvText + this.r + "</font>" + this.r;			// HTML for cell			szHTML = "<td"				+ " valign=top" 				+ " width=" + nWidth				+ " height=" + this.cellHeight 				+ " bgcolor=" + szEvBackcolor				+ " nowrap"				+ " >" + this.r; 			szTemp =  szHTML + szCell + "</td>" + this.r;			szOutput = szOutput + szTemp;			dteCal.setDate( dteCal.getDate() + 1 );			nDeadDay++		};		szOutput = szOutput + "</tr>" + this.r + this.r;	};	szHTML = "<tr><td align=center colspan=7>"		+ "The <a href='http://www.geocities.com/dshipe/camain.htm'>DHTML Javascript Calendar</a>"		+ "</td></tr>";	szOutput = szOutput + szHTML + this.r + this.r;	// end the table, form	szOutput = szOutput + "</table>";	return szOutput;};// ------------------------------------------------------------function dcUpdate(obj, m, y) {	obj.createCalendar(m, y);};// ------------------------------------------------------------function dcChkLeapYear(m, y) {	var x = 2;		if ( 	( m == x ) 	&& ( y % 4 == 0 )        && ( y % 100 == 0)         ) {		if ( y % 400 == 0) this.daysPerMonth[x] = 29;        } else {        	this.daysPerMonth[x] = 29;	};};// ------------------------------------------------------------function dcFillMonth( m ) {	var szSelected;	var szHTML = "";	for ( i=0; i<=11; i++ ) {		szSelected = "";		if ( i==m ) szSelected = "selected";		szHTML = szHTML + "<option value='" + i + "' " + szSelected + " >" + this.longMonths[i] + "</option>" + this.r;	};	return szHTML;};// ------------------------------------------------------------function dcFillYear( y, cy ) {	var szSelected;	var szHTML = "";	for ( i=cy-1; i<=cy+5; i++ ) {		szSelected = "";		if ( i==y ) szSelected = "selected";		szHTML = szHTML + "<option value='" + i + "' " + szSelected + " >" + i + "</option>" + this.r;	};	return szHTML;};// ------------------------------------------------------------function dcFontStr ( szFace, szSize, szColor ) {	return szHTML = "<font"		+ " face='"  + szFace  + "'"		+ " size='"  + szSize  + "'"		+ " color='" + szColor + "'"		+ " >";};// ------------------------------------------------------------function dcGetDay (dte) {	var day;	day = dte.getDay();	if (this.beginMonday) day--;	return day;};// ------------------------------------------------------------function dcIsWeekday (dte) {	var day;	day = dte.getDay();	if (day == 0 || day == 6) return false;	return true;};// ************************************************************// ***  EVENT class and related functions// ************************************************************// constructor for event classfunction Event (nMonth, nDay, nYear, szWeekday, szText, szForecolor, szBackcolor) {	// properties	this.month = nMonth;	this.day = nDay;	this.year = nYear;	this.weekday = szWeekday;	this.text = szText;	this.forecolor = szForecolor;	this.backcolor = szBackcolor;		// methods	this.weekdayNo = evWeekdayNo;};// ------------------------------------------------------------function evWeekdayNo () {	var nNum = -1;	var szWeekday;		szWeekday = this.weekday;	if (szWeekday==null) return nNum;	szWeekday = szWeekday.toLowerCase();	if (szWeekday=="sunday") nNum=0;	if (szWeekday=="monday") nNum=1;	if (szWeekday=="tuesday") nNum=2;	if (szWeekday=="wednesday") nNum=3;	if (szWeekday=="thursday") nNum=4;	if (szWeekday=="friday") nNum=5;	if (szWeekday=="saturday") nNum=6;	return nNum;};// ------------------------------------------------------------function evChkForEvent2(dte) {	var m=dte.getMonth();	var d=dte.getDate();	var y=dte.getFullYear();	return evChkForEvent(m,d,y);	};// ------------------------------------------------------------function evChkForEvent(m,d,y) {	var ev=null;	var dte=null;	if ( dcIsDate(m,d,y) ) dte = new Date(y,m,d);	for (i=0; i<maEvents.length; i++) {		ev = maEvents[i];		if ( ( y == ev.year || ev.year == null )		&& ( m+1 == ev.month || ev.month == null )		&& ( d == ev.day ) ) return ev;		// ----- check for weekday match		if (dte!=null) {			if (dte.getDay() == ev.weekdayNo()) return ev;		};	};	return null;};// ------------------------------------------------------------function dcIsDate (m,d,y) {	var dte = new Date(y,m,d);	if ( (dte.getFullYear() == y)	&& (dte.getMonth() == m) 	&& (dte.getDate() == d) ) {		return true;	};		return false;};// ------------------------------------------------------------function dcEvent(m,d,y,szWeekday,szText,szForecolor,szBackcolor) {	var ev;	ev = new Event(m,d,y,szWeekday,szText,szForecolor,szBackcolor); 	maEvents[maEvents.length] = ev;};// ************************************************************// ***  Cookie functions// ************************************************************function dcSaveDate (m, y) {	var mm = parseInt(m) + 1;	var szYear =  y.toString();	var szMonth = mm.toString();	if (szMonth.length==1) szMonth = "0" + szMonth;	dcCookieSet("dhtmlcal", szYear + szMonth);};// ------------------------------------------------------------function dcReadDate (szOption) {	var m, szMonth	var y, szYear	var szValue = dcCookieGet("dhtmlcal");	var dteCurrDate = new Date();	if (szValue==false) {		m = dteCurrDate.getMonth();		y = dteCurrDate.getFullYear();	} else {		szMonth = szValue.substring(4, 6);		szYear = szValue.substring(0, 4);		m = parseInt(szMonth);		y = parseInt(szYear);		if (szMonth != m.toString()) {			szMonth = szMonth.substring(szMonth.lastIndexOf("0")+1,szMonth.lastIndexOf("0")+2);			m = parseInt(szMonth);		};		m--;	};	if (szOption=="m") return m;	if (szOption=="y") return y;	return -1;};// ------------------------------------------------------------function dcCookieSet (szName, szValue, hours, szPath, szDomain, szSecure) {	var numHours;	if ( (typeof(hours) == 'string') && Date.parse(hours) ) { 		numHours = hours;	} else if (typeof(hours) == 'number') { 		numHours = (new Date((new Date()).getTime() + hours*3600000)).toGMTString();	};  	document.cookie = szName + "=" + escape(szValue)  		+ ((numHours == null) ? "" : "; expires=" + numHours)   		+ ((szPath == null) ? "" : "; szPath=" + szPath)   		+ ((szDomain == null) ? "" : "; szDomain=" + szDomain)  		+ ((szSecure == null) ? "" : "; szSecure");};// ------------------------------------------------------------function dcCookieGet (szName) {	var szData;	var nBegin;	var nEnd;	var MyCookie = document.cookie;		if (MyCookie.length>0) {		nBegin = MyCookie.indexOf(szName);		if (nBegin != -1) {			nBegin += szName.length;			nEnd = MyCookie.indexOf(";", nBegin);			if (nEnd==-1) nEnd = MyCookie.length;			szData = unescape(MyCookie.substring(nBegin+1, nEnd));			return szData;		} else {			//no cookie of name found					return false;		};	} else {		//no cookie found		return false;	};};// ************************************************************// ***  SetHTML related functions// ************************************************************function dcSetOuterHTML (obj, szHTML) {	var range = document.createRange();	range.setStartBefore(obj);	var df = range.createContextualFragment(szHTML);	obj.parentNode.replaceChild(df, this);};// ------------------------------------------------------------function dcSetInnerHTML (obj, szHTML) {	var range = document.createRange();	range.selectNodeContents(obj);	range.deleteContents();	var df = range.createContextualFragment(szHTML);	obj.appendChild(df);};// ************************************************************// ***  Browser Detection functions// ************************************************************function dcBrowserName () {	var szOutput="";	var szBrowser = navigator.appName;	if ( szBrowser=="Microsoft Internet Explorer" ) {		szOutput = "IE";	} else if ( szBrowser=="Netscape" ) {		szOutput = "NS";	};	return szOutput;};// ------------------------------------------------------------function dcBrowserVer () {	return navigator.appVersion.charAt(0);};// ************************************************************// ***  Miscellanous functions// ************************************************************function dcPopUp (strHREF, bNewWindow) {	var winPopup;	var strValues="width=400,height=300,scrollbars=yes,dependent=yes";	if (bNewWindow) {	  	winPopup = window.open(strHREF, "_blank", strValues);  	} else {	  	winPopup = window.open("", "popup", strValues);  		winPopup.location.href = strHREF;	}};// ------------------------------------------------------------function decode(szCode) {	var szAlpha = "abcdefghijklmonpqrstuvwxyz1234567890~`!@#$%^&*()_-+={[}]|\:;<,>.?/";	var szKey = "dhtmlcal";	var i, j	var nCode, nKey	var szResult="";	var nLen;	szCode = szCode.toLowerCase();	j = 0;	nLen = szAlpha.length;	for ( i=0; i<szCode.length; i++ ) {		szChar = szCode.charAt(i);		nCode = szAlpha.indexOf(szChar);		szChar = szKey.charAt(j);		nKey = szAlpha.indexOf(szChar);		nCode = nCode - nKey;		if ( nCode < 0 ) nCode = nCode + nLen;		szResult = szResult + szAlpha.charAt(nCode);		j++;		if ( j >= szKey.length ) j=1;	};			return szResult;}	// ------------------------------------------------------------function ShowProperties(obj, objName) {	var s = "";	for (p in obj) {		s += p + " = " + obj[p] + "<br>"	}		return "<p>The properties for the " + objName + " object are:<br><br>" + s + "</p>";};// ************************************************************// ***  BACKWARD COMPATABILITY functions// ************************************************************function DHTMLCal_SetEvent(m,d,y,szText,szForecolor,szBackcolor) {	var ev;		ev = new Event(m,d,y,"",szText,szForecolor,szBackcolor); 	maEvents[maEvents.length] = ev;};// ------------------------------------------------------------function DHTMLCal_PopUp (strHREF, bNewWindow) {	var winPopup;	var strValues="width=400,height=300,scrollbars=yes,dependent=yes";	if (bNewWindow) {	  	winPopup = window.open(strHREF, "_blank", strValues);  	} else {	  	winPopup = window.open("", "popup", strValues);  		winPopup.location.href = strHREF;	}};// -->