/*
 * Web DatePicker javascript library.
 *
 * Copyright (c) 2002-2004 Sunwest Technologies. All rights reserved.
 * http://www.SunwestTek.com
 */

var dpVars = new Array();
var dpConfigs = new Array();

function DPDateRange(startDate, endDate) {
	this.startDate = startDate;
	this.endDate = endDate;
}

function DPVar(id, dpConfig, dpVar, field, selYear, selMonth, selDay, showAt) {
	this.id = id;
	this.dpVar = dpVar;

	this.field = field;
	this.selYear = selYear;
	this.selMonth = selMonth;
	this.selDay = selDay;

	this.showAt = showAt;
	this.dpConfig = dpConfig;
}

function DPConfig(id) {
	this.id = id;

	this.inputType = '';
	this.inputFieldId = '';
	this.selectYearId = '';
	this.selectMonthId = '';
	this.selectDayId = '';

	this.dateFormat = '';

	this.defaultDate = null;
	this.startDate = null;
	this.endDate = null;
	this.weekDayMasks = null;
	this.disabledDateRanges = null;

	this.isIE = false;
	this.isIE4 = false;
	this.isMac = false;
	this.isAncient = false;

	this.zIndex = 100;
	this.bgColor = '';

	this.titleText = '';

	this.showPrevYear = '';
	this.prevYearText = '';
	this.prevYearImage = '';

	this.showNextYear = '';
	this.nextYearText = '';
	this.nextYearImage = '';

	this.showPrevMonth = '';
	this.prevMonthText = '';
	this.prevMonthImage = '';

	this.showNextMonth = '';
	this.nextMonthText = '';
	this.nextMonthImage = '';

	this.showFooter = '';
	this.footerText = '';
	this.footerImage = '';

	this.showPrevMonthDate = true;
	this.showNextMonthDate = true;

	this.firstWeekDayToShow = '';

	this.ancientSettings = null;

	this.msgInvalidInput = '';
	this.msgDateNotAllowed = '';

	this.calTitleStyles = null;
	this.calTitleTexts = null;

	this.longMonthNames = null;
	this.shortMonthNames = null;
}

function DPDateDisplay(displayDate, dateCode, isSelectable, cellStyle, cellLinkStyle, cellLinkStyleMO) {
	this.displayDate = displayDate;
	this.dateCode = dateCode;
	this.isSelectable = isSelectable;
	this.cellStyle = cellStyle;
	this.cellLinkStyle = cellLinkStyle;
	this.cellLinkStyleMO = cellLinkStyleMO;
}

function DPFind(id) {
	for (var i=0; i<dpVars.length; i++) {
		if (id == dpVars[i].id) {
			return dpVars[i];
		}
	}

	return null;
}

function DPConfigCreate(id) {
	var dpVar = DPFind(id);
	if (dpVar == null) {
		dpVar = new DPVar(id, new DPConfig(id), null, null, null, null, null, null);
		dpVars[dpVars.length] = dpVar;
	}

	return dpVar.dpConfig;
}

function DPCreate(dpConfig, showAt) {
	var dpCal = DPCalendar(dpConfig, new Date(), null);

	var dp;
	if (dpConfig.isAncient) {
		var ww = dpConfig.ancientSettings[0];
		var wh = dpConfig.ancientSettings[1];
		var features = "toolbar=no,location=no,menubar=no,resizable=no,width=" +
			ww + ",height=" + wh; 
		dp = window.open("", "DatePicker", features);
		dp.status = "dp_created";
	} else if (dpConfig.isIE4) {
		var div = "<div id='" + dpConfig.id + "' " +
			"style='position:absolute; left:0px; top:0px; visibility:hidden; " +
			"z-index:" + dpConfig.zIndex + "; background-color:" + dpConfig.bgColor + "'>" +
			"</div>";
		document.body.insertAdjacentHTML(div);
		dp = document.all(dpConfig.id);
	} else {
		dp = document.createElement("div");

		dp.style.visibility = "hidden";
		dp.style.position = "absolute";
		dp.style.left = "0px";
		dp.style.top = "0px";

		dp.id = dpConfig.id;
		dp.style.zIndex = dpConfig.zIndex;
		dp.style.backgroundColor = dpConfig.bgColor;

		if (dpConfig.isIE) {
			document.body.insertBefore(dp, document.body.firstChild);
		} else {
			document.body.appendChild(dp);
		}
	}

	var field, selYear, selMonth, selDay;
	if (dpConfig.inputType == 'T') {
		if (dpConfig.isAncient) {
			field = DPFindFormElementByName("text", dpConfig.inputFieldId);
		} else {
			field = DPFindFormElementById("text", dpConfig.inputFieldId);
		}
	} else if (dpConfig.inputType == 'S') {
		if (dpConfig.isAncient) {
			selYear = DPFindFormElementByName("select-one", dpConfig.selectYearId);
			selMonth = DPFindFormElementByName("select-one", dpConfig.selectMonthId);
			selDay = DPFindFormElementByName("select-one", dpConfig.selectDayId);
		} else {
			selYear = DPFindFormElementById("select-one", dpConfig.selectYearId);
			selMonth = DPFindFormElementById("select-one", dpConfig.selectMonthId);
			selDay = DPFindFormElementById("select-one", dpConfig.selectDayId);
		}
	}

	var dpVar = DPFind(dpConfig.id);
	if (null == dpVar) {
		dpVar = new DPVar(dpConfig.id, dpConfig, dp, field, selYear, selMonth, selDay, showAt);
		dpVars[dpVars.length] = dpVar;
	} else {
		dpVar.dpConfig = dpConfig;
		dpVar.dpVar = dp;
		
		dpVar.field = field;
		dpVar.selYear = selYear;
		dpVar.selMonth = selMonth;
		dpVar.selDay = selDay;

		dpVar.showAt = showAt;
	}

	return dpVar;
}

function DPFindFormElementById(type, id) {
	for (var i=0; i<document.forms.length; i++) {
		var form = document.forms[i];
		var elems = form.elements;
		for (var j=0; j<elems.length; j++) {
			var elem = elems[j];
			if ((elem.type == type) && (elem.id == id)) {
				return elem;
			}
		}
	}

	return null;
}

function DPFindFormElementByName(type, name) {
	for (var i=0; i<document.forms.length; i++) {
		var form = document.forms[i];
		var elems = form.elements;
		for (var j=0; j<elems.length; j++) {
			var elem = elems[j];
			if ((elem.type == type) && (elem.name == name)) {
				return elem;
			}
		}
	}

	return null;
}

function DPTrim(s) {
	if (null != s) {
		var str = s;

		if (str.length > 0) {
			var c = str.substring(0, 1);
			while (" " == c) {
				str = str.substring(1, str.length);
				c = str.substring(0, 1);
			}
		}

		if (str.length > 0) {
			var c = str.substring(str.length-1, str.length);
			while (" " == c) {
				str = str.substring(0, str.length-1);
				c = str.substring(str.length-1, str.length);
			}
		}

		return str;
	} else {
		return "";
	}
}

function DPIsDateChar(c) {
	var dateChars = new Array('Y', 'y', 'M', 'm', 'D', 'd');
	for (var i=0; i<dateChars.length; i++) {
		if (c == dateChars[i]) {
			return true;
		}
	}

	return false;
}

function DPDateFormatOption(fs) {
	if (fs == "YYYY") {
		return 0;
	} else if (fs == "YY") {
		return 1;
	} else if (fs == "MM") {
		return 2;
	} else if (fs == "DD") {
		return 3;
	} else {
		return -1;
	}
}

function DPParseDate(dpConfig, dpVar) {
	if (dpConfig.inputType == 'T') {
		if (null == dpVar.field) {
			if (dpConfig.isAncient) {
				dpVar.field = DPFindFormElementByName("text", dpConfig.inputFieldId);
			} else {
				dpVar.field = DPFindFormElementById("text", dpConfig.inputFieldId);
			}	
		}

		var f = dpVar.field;
		if (null != f) {
			var v = DPTrim(f.value);
			if (v.length == dpConfig.dateFormat.length) {
				var year = dpConfig.defaultDate.getFullYear();
				var month = dpConfig.defaultDate.getMonth();
				var day = dpConfig.defaultDate.getDate();

				var lc = '';
				var fb = "";
				var vb = "";
				for (var i=0; i<v.length; i++) {
					var vc = v.charAt(i);
					var fc = dpConfig.dateFormat.charAt(i);

					if (!DPIsDateChar(fc)) {
						if (vc != fc) {
							return null;
						} else {
							if ((fb.length > 0) && (vb.length > 0)) {
								var iv = parseInt(vb, 10);
								if (isNaN(iv)) {
									return null;
								}

								switch (DPDateFormatOption(fb.toUpperCase())) {
									case 0:
									case 1:
										year = iv;
										break;

									case 2:
										month = iv - 1;
										break;

									case 3:
										day = iv;
										break;

									default:
										return null;
								}

								lc = '';
								fb = "";
								vb = "";
							}
						}
					} else {
						if (('' == lc) || (fc == lc)) {
							lc = fc;
							fb = fb + fc;
							vb = vb + vc;

							if (i < (v.length-1)) {
								continue;
							}
						}

						if ((fb.length > 0) && (vb.length > 0)) {
							var iv = parseInt(vb, 10);
							if (isNaN(iv)) {
								return null;
							}

							switch (DPDateFormatOption(fb.toUpperCase())) {
								case 0:
								case 1:
									year = iv;
									break;

								case 2:
									month = iv - 1;
									break;

								case 3:
									day = iv;
									break;

								default:
									return null;
							}

							lc = fc;
							fb = fc;
							vb = vc;
						}
					}
				}

				if (DPIsValidDate(year, month, day)) {
					return new Date(year, month, day);
				}
			}
		}
	} else if (dpConfig.inputType == 'S') {
		var year = dpConfig.defaultDate.getFullYear();
		var month = dpConfig.defaultDate.getMonth();
		var day = dpConfig.defaultDate.getDate();
		var s;

		if (null == dpVar.selYear) {
			if (dpConfig.isAncient) {
				dpVar.selYear = DPFindFormElementByName("select-one", dpConfig.selectYearId);
			} else {
				dpVar.selYear = DPFindFormElementById("select-one", dpConfig.selectYearId);
			}
		}

		if (null == dpVar.selMonth) {
			if (dpConfig.isAncient) {
				dpVar.selMonth = DPFindFormElementByName("select-one", dpConfig.selectMonthId);
			} else {
				dpVar.selMonth = DPFindFormElementById("select-one", dpConfig.selectMonthId);
			}
		}
		
		if (null == dpVar.selDay) {
			if (dpConfig.isAncient) {
				dpVar.selDay = DPFindFormElementByName("select-one", dpConfig.selectDayId);
			} else {
				dpVar.selDay = DPFindFormElementById("select-one", dpConfig.selectDayId);
			}
		}

		s = dpVar.selYear;
		if (null != s) {
			var v = parseInt(s.options[s.selectedIndex].value, 10);
			if (!isNaN(v)) {
			  year = v;
			}
		}

		s = dpVar.selMonth;
		if (null != s) {
			var v = parseInt(s.options[s.selectedIndex].value, 10);
			if (!isNaN(v)) {
			  month = v;
			}
		}

		s = dpVar.selDay;
		if (null != s) {
			var v = parseInt(s.options[s.selectedIndex].value, 10);
			if (!isNaN(v)) {
			  day = v;
			}
		}

		if (DPIsValidDate(year, month, day)) {
			return new Date(year, month, day);
		}
	}

	return null;
}

function DPIsValidDate(y, m, d) {
  var da = new Date(y, m, d);
	return ((da.getMonth() == m) && (da.getDate() == d));
}

function DPCalendar(dpConfig, d, sd) {
	return DPCalHeader(dpConfig, d) +
		DPCalBody(dpConfig, d, sd) + 
		DPCalFooter(dpConfig, d);
}

function DPCalHeader(dpConfig, d) {
	var cal;

	if (dpConfig.isAncient) {
		var cellWidth = parseInt(dpConfig.ancientSettings[0])/8;
		cal = 
			// background
			"<html><head><title>DatePicker</title></head>" +
			"<body bgcolor='" + dpConfig.bgColor +"'>" +

			// calendar
			"<table align='center' valign='middle' width='100%' border='0' " +
			"cellspacing='" + dpConfig.ancientSettings[2] + "' " +
			"cellpadding='" + dpConfig.ancientSettings[3] + "' " +
			"bgcolor='" + dpConfig.ancientSettings[4] + "'>" +

			// title
			"<tr align='center' valign='middle'>";

		cal = cal + "<td bgcolor='" + dpConfig.ancientSettings[5] + "' align='center' valign='middle'>";
		var prevYear = DPIsPrevYearSelectable(dpConfig, d);
		if ((dpConfig.showPrevYear == 'T') && (prevYear)) {
			cal = cal + 
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevYear(d)) + "\");'>" +
				dpConfig.ancientSettings[6] +
				dpConfig.prevYearText +
				dpConfig.ancientSettings[7] +
				"</a>";
		} else if ((dpConfig.showPrevYear == 'I') && (prevYear)) {
			cal = cal +
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevYear(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.prevYearImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "<td bgcolor='" + dpConfig.ancientSettings[5] + "' align='center' valign='middle'>";
		var prevMonth = DPIsPrevMonthSelectable(dpConfig, d);
		if ((dpConfig.showPrevMonth == 'T') && (prevMonth)) {
			cal = cal + 
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevMonth(d)) + "\");'>" +
				dpConfig.ancientSettings[6] +
				dpConfig.prevMonthText +
				dpConfig.ancientSettings[7] +
				"</a>";
		} else if ((dpConfig.showPrevMonth == 'I') && (prevMonth)) {
			cal = cal +
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevMonth(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.prevMonthImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "<td bgcolor='" + dpConfig.ancientSettings[5] + "' colspan='3' align='center' valign='middle'>";
	  cal = cal +	dpConfig.ancientSettings[6];
		cal = cal + DPFormatTitleText(dpConfig, d);
	  cal = cal +	dpConfig.ancientSettings[7];
		cal = cal + "</td>";

		cal = cal + "<td bgcolor='" + dpConfig.ancientSettings[5] + "' align='center' valign='middle'>";
		var nextMonth = DPIsNextMonthSelectable(dpConfig, d);
		if ((dpConfig.showNextMonth == 'T') && (nextMonth)) {
			cal = cal + 
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextMonth(d)) + "\");'>" +
				dpConfig.ancientSettings[6] +
				dpConfig.nextMonthText +
				dpConfig.ancientSettings[7] +
				"</a>";
		} else if ((dpConfig.showNextMonth == 'I') && (nextMonth)) {
			cal = cal +
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextMonth(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.nextMonthImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "<td bgcolor='" + dpConfig.ancientSettings[5] + "' align='center' valign='middle'>";
		var nextYear = DPIsNextYearSelectable(dpConfig, d);
		if ((dpConfig.showNextYear == 'T') && (nextYear)) {
			cal = cal + 
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextYear(d)) + "\");'>" +
				dpConfig.ancientSettings[6] +
				dpConfig.nextYearText +
				dpConfig.ancientSettings[7] +
				"</a>";
		} else if ((dpConfig.showNextYear == 'I') && (nextYear)) {
			cal = cal +
				"<a href='javascript:window.opener.DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextYear(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.nextYearImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "</tr>";

		// calendar title
		cal = cal + "<tr align='center' valign='middle'>";

		var fwd = 0;
		if (dpConfig.firstWeekDayToShow == 'M') {
		  fwd = 1;
		}
		
		for (var i=0; i<7; i++) {
			cal = cal +
				"<td bgcolor='" + dpConfig.ancientSettings[8] + "' align='center' valign='middle'>" +
				dpConfig.ancientSettings[9] +
				dpConfig.calTitleTexts[(i+fwd)%7] +
				dpConfig.ancientSettings[10] +
				"</td>";
		}

		cal = cal + "</tr>";
	} else {
		cal = 
			"<table class='dpCalendar'>" +
			"<tr align='center' valign='middle'>";

		cal = cal + "<td class='dpTitlePrevYear'>";
		var prevYear = DPIsPrevYearSelectable(dpConfig, d);
		if ((dpConfig.showPrevYear == 'T') && (prevYear)) {
			cal = cal + 
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevYear(d)) + "\");' " +
				"class='dpTitlePrevYearLink'>" +
				dpConfig.prevYearText +
				"</a>";
		} else if ((dpConfig.showPrevYear == 'I') && (prevYear)) {
			cal = cal +
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevYear(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.prevYearImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "<td class='dpTitlePrevMonth'>";
		var prevMonth = DPIsPrevMonthSelectable(dpConfig, d);
		if ((dpConfig.showPrevMonth == 'T') && (prevMonth)) {
			cal = cal + 
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevMonth(d)) + "\");' " +
				"class='dpTitlePrevMonthLink'>" +
				dpConfig.prevMonthText +
				"</a>";
		} else if ((dpConfig.showPrevMonth == 'I') && (prevMonth)) {
			cal = cal +
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPPrevMonth(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.prevMonthImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "<td colspan='3' class='dpTitleText'>";
		cal = cal + DPFormatTitleText(dpConfig, d);
		cal = cal + "</td>";

		cal = cal + "<td class='dpTitleNextMonth'>";
		var nextMonth = DPIsNextMonthSelectable(dpConfig, d);
		if ((dpConfig.showNextMonth == 'T') && (nextMonth)) {
			cal = cal + 
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextMonth(d)) + "\");' " +
				"class='dpTitleNextMonthLink'>" +
				dpConfig.nextMonthText +
				"</a>";
		} else if ((dpConfig.showNextMonth == 'I') && (nextMonth)) {
			cal = cal +
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextMonth(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.nextMonthImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "<td class='dpTitleNextYear'>";
		var nextYear = DPIsNextYearSelectable(dpConfig, d);
		if ((dpConfig.showNextYear == 'T') && (nextYear)) {
			cal = cal + 
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextYear(d)) + "\");' " +
				"class='dpTitleNextYearLink'>" +
				dpConfig.nextYearText +
				"</a>";
		} else if ((dpConfig.showNextYear == 'I') && (nextYear)) {
			cal = cal +
				"<a href='javascript:DPUpdate(\"" + dpConfig.id + "\", " +
				"\"" + DPDateEncode(DPNextYear(d)) + "\");'>" +
				"<img border='0' src='" + dpConfig.nextYearImage + "'>";
				"</a>";
		} else {
			cal = cal + "&nbsp;";
		}
		cal = cal + "</td>";

		cal = cal + "</tr>";

		// calendar title
		cal = cal + "<tr align='center' valign='middle'>";
		var fwd = 0;
		if (dpConfig.firstWeekDayToShow == 'M') {
		  fwd = 1;
		}
		
		for (var i=0; i<7; i++) {
			cal = cal +
				"<td class='" + dpConfig.calTitleStyles[(i+fwd)%7] + "'>" +
				dpConfig.calTitleTexts[(i+fwd)%7] +
				"</td>";
		}

		cal = cal + "</tr>"
	}

	return cal;
}

function DPCalBody(dpConfig, d, sd) {
	var cal = "";

	var dds = DPGetDateDisplays(dpConfig, d, sd);

	if (dpConfig.isAncient) {
		for (var i=0; i<dds.length; i++) {
			if (i%7 == 0) {
				cal = cal + "<tr align='center' valign='middle'>";
			}

			var dd = dds[i];
			cal = cal + "<td nowrap bgcolor='";
			if (dd.isSelectable) {
				cal = cal + dpConfig.ancientSettings[11] + "'>" +
					"<a href='javascript:window.opener.DPPickDate(\"" + dpConfig.id + "\", \"" +
					dd.dateCode + "\");'>" + 
					dpConfig.ancientSettings[12] +
					dd.displayDate +
					dpConfig.ancientSettings[13] +
					"</a>";
			} else {
				cal = cal + dpConfig.ancientSettings[14] + "'>" +
					dpConfig.ancientSettings[15] +
					dd.displayDate +
					dpConfig.ancientSettings[16];
			}
			cal = cal + "</td>";

			if (i%7 == 6) {
				cal = cal + "</tr>";
			}
		}
	} else {
		for (var i=0; i<dds.length; i++) {
			if (i%7 == 0) {
				cal = cal + "<tr align='center' valign='middle'>";
			}

			var dd = dds[i];
			cal = cal + "<td nowrap class='" + dd.cellStyle + "'>";
			if (dd.isSelectable) {
				cal = cal + 
					"<a href='javascript:DPPickDate(\"" + dpConfig.id + "\", \"" +
					dd.dateCode + "\");' class='" + 
					dd.cellLinkStyle + "' " +
					"onmouseover='DPOnMouseOver(this, \"" + dpConfig.id + "\", \"" + dd.cellLinkStyleMO + "\");'" +
					"onmouseout='DPOnMouseOut(this, \"" + dpConfig.id + "\", \"" + dd.cellLinkStyle + "\");'" +
					">" +
					dd.displayDate +
					"</a>";
			} else {
				cal = cal + dd.displayDate;
			}
			cal = cal + "</td>";

			if (i%7 == 6) {
				cal = cal + "</tr>";
			}
		}
	}

	return cal;
}

function DPGetFirstDay(d) {
	var nd = new Date(d.getFullYear(), d.getMonth(), 1);
	return nd.getDay();
}

function DPGetDaysForMonth(d) {
	var year = d.getFullYear();
	var month = d.getMonth();

	for (var i=31; i>=28; i--) {
		var nd = new Date(year, month, i);
		if (month == nd.getMonth()) {
			return i;
		}
	}

	return 31;
}

function DPIsDateSelectable(dpConfig, d) {
	// check starting date
	if (dpConfig.startDate) {
		if (d.getTime() < dpConfig.startDate.getTime()) {
			return false;
		}
	}

	// check ending date
	if (dpConfig.endDate) {
		if (d.getTime() > dpConfig.endDate.getTime()) {
			return false;
		}
	}

	// check weekdays
	if (dpConfig.weekDayMasks) {
		var day = d.getDay();
		if (dpConfig.weekDayMasks[day] == false) {
			return false;
		}
	}

	// disabled date ranges
	if (dpConfig.disabledDateRanges) {
		for (var i=0; i<dpConfig.disabledDateRanges.length; i++) {
			var dr = dpConfig.disabledDateRanges[i];
			var sd = dr.startDate;
			var ed = dr.endDate;
			if ((sd) && (ed)) {
				if ((d.getTime() >= sd.getTime()) && (d.getTime() <= ed.getTime())) {
					return false;
				}
			} else if (sd) {
				if (d.getTime() >= sd.getTime()) {
					return false;
				}
			} else if (ed) {
				if (d.getTime() <= ed.getTime()) {
					return false;
				}
			}
		}
	}

	return true;
}

function DPIsPrevYearSelectable(dpConfig, d) {
	if (dpConfig.startDate) {
		var ly = DPPrevYear(d);
		var nd = DPGetDaysForMonth(ly);
		var ld = new Date(ly.getFullYear(), ly.getMonth(), nd);
		if (ld.getTime() < dpConfig.startDate.getTime()) {
			return false;
		}
	}

	return true;
}

function DPIsPrevMonthSelectable(dpConfig, d) {
	if (dpConfig.startDate) {
		var lm = DPPrevMonth(d);
		var nd = DPGetDaysForMonth(lm);
		var ld = new Date(lm.getFullYear(), lm.getMonth(), nd);
		if (ld.getTime() < dpConfig.startDate.getTime()) {
			return false;
		}
	}

	return true;
}

function DPIsNextYearSelectable(dpConfig, d) {
	if (dpConfig.endDate) {
		var ny = DPNextYear(d);
		var nd = new Date(ny.getFullYear(), ny.getMonth(), 1);
		if (nd.getTime() > dpConfig.endDate.getTime()) {
			return false;
		}
	}

	return true;
}

function DPIsNextMonthSelectable(dpConfig, d) {
	if (dpConfig.endDate) {
		var nm = DPNextMonth(d);
		var nd = new Date(nm.getFullYear(), nm.getMonth(), 1);
		if (nd.getTime() > dpConfig.endDate.getTime()) {
			return false;
		}
	}

	return true;
}

function DPGetDateDisplays(dpConfig, d, sd) {
	var year = d.getFullYear();
	var month = d.getMonth();

	var fd = DPGetFirstDay(d);
	var nd = DPGetDaysForMonth(d);

	var pm, pmy, pmm, pmd;
	if (dpConfig.showPrevMonthDate) {
		pm = DPPrevMonth(d);
		pmy = pm.getFullYear();
		pmm = pm.getMonth();
		pmd = DPGetDaysForMonth(pm);
	}

	var nm, nmy, nmm, nmd;
	if (dpConfig.showPrevMonthDate) {
		nm = DPNextMonth(d);
		nmy = pm.getFullYear();
		nmm = pm.getMonth();
		nmd = DPGetDaysForMonth(pm);
	}

	var offset;
	if (dpConfig.firstWeekDayToShow == 'M') {
		offset = (fd + 6) % 7;
	} else {
		offset = fd;
	}

	var dds = new Array(42);

	for (var i=0; i<offset; i++) {
		var dd;
		if (dpConfig.showPrevMonthDate) {
			var da = new Date(pmy, pmm, pmd-offset+i+1);
			dd = new DPDateDisplay(da.getDate()+"",
					DPDateEncode(da),
					false,
					"dpPrevMonthDate",
					"",
					""
					);
		} else {
			dd = new DPDateDisplay("",
					"",
					false,
					"",
					"",
					""
					);
		}
		dds[i] = dd;
	}

	var selectedDate = DPDateEncode(sd);
	var today = DPDateEncode(new Date());

	for (var i=0; i<nd; i++) {
		var da = new Date(year, month, i+1);
		var ds = DPDateEncode(da);

		var sl = DPIsDateSelectable(dpConfig, da);

		var day = da.getDay();
		var style = "";
		var linkStyle = "";
		var linkStyleMO = "";

		if (ds == selectedDate) {
			if (sl) {
				style = "dpSelectedDate";
				linkStyle = "dpSelectedDateLink";
				linkStyleMO = "dpSelectedDateLinkMouseOver";
			} else {
				style = "dpSelectedDateDisabled";
			}
		} else if (ds == today) {
			if ((day == 0) || (day == 6)) {
				if (sl) {
					style = "dpTodayWeekend";
					linkStyle = "dpTodayWeekendLink";
					linkStyleMO = "dpTodayWeekendLinkMouseOver";
				} else {
					style = "dpTodayWeekendDisabled";
				}
			} else {
				if (sl) {
					style = "dpTodayWeekday";
					linkStyle = "dpTodayWeekdayLink";
					linkStyleMO = "dpTodayWeekdayLinkMouseOver";
				} else {
					style = "dpTodayWeekdayDisabled";
				}
			}
		} else if ((day == 0) || (day == 6)) {
			if (sl) {
				style = "dpCurrentMonthWeekend";
				linkStyle = "dpCurrentMonthWeekendLink";
				linkStyleMO = "dpCurrentMonthWeekendLinkMouseOver";
			} else {
				style = "dpCurrentMonthWeekendDisabled";
			}
		} else {
			if (sl) {
				style = "dpCurrentMonthWeekday";
				linkStyle = "dpCurrentMonthWeekdayLink";
				linkStyleMO = "dpCurrentMonthWeekdayLinkMouseOver";
			} else {
				style = "dpCurrentMonthWeekdayDisabled";
			}
		}

		var dd = new DPDateDisplay(da.getDate()+"",
				DPDateEncode(da),
				sl,
				style,
				linkStyle,
				linkStyleMO
				);
		dds[offset+i] = dd;
	}

	var ei = Math.floor((offset+nd+6)/7) * 7 ;
	for (var i=offset+nd; i<ei; i++) {
		var dd;
		if (dpConfig.showNextMonthDate) {
			var da = new Date(nmy, nmm, i-(offset+nd)+1);
			dd = new DPDateDisplay(da.getDate()+"",
					DPDateEncode(da),
					false,
					"dpNextMonthDate",
					"",
					""
					);
		} else {
			dd = new DPDateDisplay("",
					"",
					false,
					"",
					"",
					""
					);
		}
		dds[i] = dd;
	}

	for (var i=ei; i<dds.length; i++) {
		var dd = new DPDateDisplay("",
				"",
				false,
				"",
				"",
				""
				);
		dds[i] = dd;
	}

	return dds;
}

function DPCalFooter(dpConfig, d) {
	var cal;

	if (dpConfig.isAncient) {
		cal = "<tr align='center' valign='middle'>" +
			"<td colspan='7' bgcolor='" + dpConfig.ancientSettings[17] + "' align='center' valign='middle'>";

		if (dpConfig.showFooter == 'I') {
			cal = cal +
				"<a href='javascript:window.opener.DPClose(\"" + dpConfig.id + "\");'>" +
				"<img border='0' src='" + dpConfig.footerImage + "'>";
				"</a>";
		} else if (dpConfig.showFooter == 'T') {
			cal = cal + 
				"<a href='javascript:window.opener.DPClose(\"" + dpConfig.id + "\");'>" +
				dpConfig.ancientSettings[18] + 
				dpConfig.footerText +
				dpConfig.ancientSettings[19] + 
				"</a>";
		}

		cal = cal + "</td></tr></table></body></html>";
	} else {
		cal = 
			"<tr align='center' valign='middle'>" +
			"<td colspan='7' class='dpFooter'>";

		if (dpConfig.showFooter == 'I') {
			cal = cal +
				"<a href='javascript:DPClose(\"" + dpConfig.id + "\");'>" +
				"<img border='0' src='" + dpConfig.footerImage + "'>";
			  "</a>";
		} else if (dpConfig.showFooter == 'T') {
			cal = cal + 
				"<a href='javascript:DPClose(\"" + dpConfig.id + "\");' class='dpFooterLink'>" +
				dpConfig.footerText +
				"</a>";
		}

		cal = cal + "</td></tr></table>";
	}

	return cal;
}

function DPFormatTitleText(dpConfig, d) {
	var yyyy = d.getFullYear() + "";
	var yy = yyyy.substring(2,4);

	var m = d.getMonth() + 1;
	var mm = (m < 10) ? ("0" + m) : ("" + m);

	var lmn = dpConfig.longMonthNames[m-1];
	var smn = dpConfig.shortMonthNames[m-1];

	return dpConfig.titleText
		.replace(/#YYYY#/gi,yyyy)
		.replace(/#YY#/gi,yy)
		.replace(/#LMN#/gi,lmn)
		.replace(/#SMN#/gi,smn)
		.replace(/#MM#/gi,mm)
		.replace(/#M#/gi,m+"")
		;
}

function DPDateEncode(d) {
	if (null == d) {
		return "";
	} else {
		return d.getFullYear() + "|" + 
			(d.getMonth()+1) + "|" + d.getDate();
	}
}

function DPDateDecode(ds) {
	var idx = ds.indexOf("|");
	if (idx > 0) {
		var year = ds.substring(0, idx);

		ds = ds.substring(idx+1, ds.length);
		idx = ds.indexOf("|");
		if (idx > 0) {
			var month = ds.substring(0, idx);
			var day = ds.substring(idx+1, ds.length);

			if ((!isNaN(parseInt(year, 10))) && 
					(!isNaN(parseInt(month, 10))) && 
					(!isNaN(parseInt(day, 10))))
			{
				return new Date(parseInt(year, 10), parseInt(month, 10)-1, parseInt(day, 10));
			}
		}
	}

	return new Date();
}

function DPDateFormat(dpConfig, d) {
	var yyyy = d.getFullYear() + "";
	var yy = yyyy.substring(2,4);

	var m = d.getMonth() + 1;
	var mm = (m < 10) ? ("0" + m) : ("" + m);

	var md = d.getDate();
	var mdd = (md < 10) ? ("0" + md) : ("" + md);

	return dpConfig.dateFormat
		.replace(/YYYY/gi,yyyy)
		.replace(/YY/gi,yy)
		.replace(/MM/gi,mm)
		.replace(/M/gi,m+"")
		.replace(/DD/gi,mdd)
		.replace(/D/gi,md+"")
		;
}

function DPPrevYear(d) {
	var year = d.getFullYear();
	var month = d.getMonth();

	year --;

	return new Date(year, month, 1);
}

function DPNextYear(d) {
	var year = d.getFullYear();
	var month = d.getMonth();

	year ++;

	return new Date(year, month, 1);
}

function DPPrevMonth(d) {
	var year = d.getFullYear();
	var month = d.getMonth();

	month --;
	if (month < 0) {
		month = 11;
		year --;
	}

	return new Date(year, month, 1);
}

function DPNextMonth(d) {
	var year = d.getFullYear();
	var month = d.getMonth();

	month ++;
	if (month > 11) {
		month = 0;
		year ++;
	}

	return new Date(year, month, 1);
}

function DPGetX(dp, dpConfig, elem) {
	if (dpConfig.isAncient) {
		return elem.pageX;
	} else {
		var w = dp.offsetWidth;
		var h = dp.offsetHeight;

		var l = DPGetOffsetX(dpConfig, elem);

		var x = 0;
		if (dpConfig.align == 'R') {
			x = l;
		} else if (dpConfig.align == 'C') {
			x = l - (w-elem.offsetWidth)/2;
		} else {
			x = l - (w-elem.offsetWidth);
		}

		return (x > 0) ? x : 0;
	}
}

function DPGetOffsetX(dpConfig, elem) {
  var left = elem.offsetLeft;

  if (elem.offsetParent) {
	  return left+DPGetOffsetX(dpConfig, elem.offsetParent);
	} else {
		if (dpConfig.isIE && dpConfig.isMac) {
		  return left+parseInt(document.body.leftMargin);
		} else {
		  return left;
		}
	}
}

function DPGetY(dp, dpConfig, elem) {
	if (dpConfig.isAncient) {
		return elem.pageY;
	} else {
		var t = DPGetOffsetY(dpConfig, elem);

	  var y;
		if (dpConfig.valign == 'T') {
			y = t - dp.offsetHeight;
		} else {
			y = t + elem.offsetHeight;
		}

		return y;
	}
}

function DPGetOffsetY(dpConfig, elem) {
  var top = elem.offsetTop;

  if (elem.offsetParent) {
	  return top+DPGetOffsetY(dpConfig, elem.offsetParent);
	} else {
		if (dpConfig.isIE && dpConfig.isMac) {
		  return top+parseInt(document.body.topMargin);
		} else {
		  return top;
		}
	}
}

function DPPopUp(dpConfig, showAt) {
	var dpVar = DPFind(dpConfig.id);
	if ((null == dpVar) || (null == dpVar.dpVar))  {
		dpVar = DPCreate(dpConfig, showAt);
	}

	DPCloseAllBut(dpConfig.id);

	var dp = dpVar.dpVar;
	if (dpConfig.isAncient) {
		if (dp.status != "dp_created") {
			dp.close();
			dpVar.dpVar = null;
			return;
		}
	} else {
		if (dp.style.visibility == 'visible') {
			dp.style.visibility = "hidden";
			return;
		}
	}

	var d = DPParseDate(dpConfig, dpVar);
	var sd = d;
	if (null == d) {
		d = new Date();
	}

	var cal = DPCalendar(dpConfig, d, sd);

	DPShow(dp, cal, dpConfig, showAt);
}

function DPShow(dp, cal, dpConfig, showAt) {
	if (dpConfig.isAncient) {
		dp.document.open();
		dp.document.write(cal);
		dp.document.close();

		dp.status = "dp_showing";
		dp.focus();
	} else if (dpConfig.isIE) {
		dp.innerHTML = cal;

		dp.style.pixelLeft = DPGetX(dp, dpConfig, showAt);
		dp.style.pixelTop = DPGetY(dp, dpConfig, showAt);

		dp.style.clip = "rect(0px; " + 
			dp.children[0].offsetWidth + "px; " +
			dp.children[0].offsetHeight + "px; " +
			"0px)";
		dp.style.visibility = "visible";
	} else {
		dp.innerHTML = cal;

		dp.style.left = DPGetX(dp, dpConfig, showAt) + "px";
		dp.style.top = DPGetY(dp, dpConfig, showAt) + "px";

		dp.style.visibility = "visible";
	}
}

function DPUpdate(id, ds) {
	var dpVar = DPFind(id);
	if (null != dpVar) {
		var dp = dpVar.dpVar;
		var showAt = dpVar.showAt;
		var dpConfig = dpVar.dpConfig;
		var d = DPDateDecode(ds);

		var sd = DPParseDate(dpConfig, dpVar);
		if (sd == null) {
			sd = new Date();
		}

		var cal = DPCalendar(dpConfig, d, sd);

		DPShow(dp, cal, dpConfig, showAt);
	}
}

function DPClose(id) {
	var dpVar = DPFind(id);
	if (null != dpVar) {
		var dp = dpVar.dpVar;
		if (null != dp) {
			var dpConfig = dpVar.dpConfig;
			if (dpConfig.isAncient) {
				dp.close();
				dpVar.dpVar = null;
			} else {
				dp.style.visibility = "hidden";
			}
		}
	}
}

function DPCloseAllBut(id) {
	for (var i=0; i<dpVars.length; i++) {
		var dpVar = dpVars[i];

		if (dpVar.id == id) {
			continue;
		}

		var dp = dpVar.dpVar;
		if (null != dp) {
			var dpConfig = dpVar.dpConfig;
			if (dpConfig.isAncient) {
				dp.close();
				dpVar.dpVar = null;
			} else {
				dp.style.visibility = "hidden";
			}
		}
	}
}

function DPPickDate(id, ds) {
	var dpVar = DPFind(id);
	if (null != dpVar) {
		var dp = dpVar.dpVar;
		var dpConfig = dpVar.dpConfig;
		if (dpConfig.isAncient) {
			dp.close();
			dpVar.dpVar = null;
		} else {
			dp.style.visibility = "hidden";
		}

			var d = DPDateDecode(ds);
			if (dpConfig.inputType == 'T') {
				var field = dpVar.field;
				if (field) {
					field.value = DPDateFormat(dpConfig, d)
				}
			} else if (dpConfig.inputType == 'S') {
				var sy = dpVar.selYear;
				if (sy) {
					var year = d.getFullYear();
					for (var i=0; i<sy.options.length; i++) {
						if (year == sy.options[i].value) {
						  sy.options[i].selected = true;
							break;
						}
					}
				}

				var sm = dpVar.selMonth;
				if (sm) {
					var month = d.getMonth();
					for (var i=0; i<sm.options.length; i++) {
						if (month == sm.options[i].value) {
						  sm.options[i].selected = true;
							break;
						}
					}
				}

				var sd = dpVar.selDay;
				if (sd) {
					var day = d.getDate();
					for (var i=0; i<sd.options.length; i++) {
						if (day == sd.options[i].value) {
						  sd.options[i].selected = true;
							break;
						}
					}
				}
		}
	}
}

function DPOnMouseOver(elem, id, style) {
	elem.className = style;
	return true;
}

function DPOnMouseOut(elem, id, style) {
	elem.className = style;
	return true;
}

function DPInputCheck(id, f) {
	var dpVar = DPFind(id);
	if (null != dpVar) {
		var dpConfig = dpVar.dpConfig;
		var d = DPParseDate(dpConfig, dpVar);
		if (null == d) {
		  alert(dpConfig.msgInvalidInput);
			if (f.focus) {
			  f.focus();
			}
			if (f.select) {
			  f.select();
			}
			return false;
		} else if (!DPIsDateSelectable(dpConfig, d)) {
		  alert(dpConfig.msgDateNotAllowed);
			if (f.focus) {
			  f.focus();
			}
			if (f.select) {
			  f.select();
			}
			return false;
		}
	}

	return true;
}
