// @(#)dates.js %W%
// Author: Keith Thompson
// Description: Popup Calander to pick a date
// Created: 04/10/2002
/***
	Assumptions Made
	================
	- they use standard numbers (0-9)
	- their month mask is either 1 or 2 characters
	- their day mask is either 1 or 2 characters
	- their year mask is either 2 or 4 characters
	- typing a 4-digit year over a 2-digit mask is OK
	- year will be auto-populated if omitted only for formats that end with year (M/D/Y or D/M/Y)
	- year range is from 1980 to 2079
***/

/****** begin added by servlet ******/
//gDateFormat = top.vars.document.frmVars.DateFormat.value;
//gSepChar = top.vars.document.frmVars.SepChar.value;
//gMM = parseInt(top.vars.document.frmVars.MM.value, 10);
//gDD = parseInt(top.vars.document.frmVars.DD.value, 10);
//gYY = parseInt(top.vars.document.frmVars.YY.value, 10);

gDateFormat = "MM/DD/YYYY";
gSepChar = "/";

gMM = 0;
gDD = 1;
gYY = 2;

gMonthChar = "M";
gDayChar = "D";
gYearChar = "Y";

/****** end added by servlet ******/

// check the date format to determine the order of M, D and Y
dateFormatStr = gDateFormat;
sep1 = dateFormatStr.indexOf(gSepChar);
sep2 = dateFormatStr.lastIndexOf(gSepChar);
dateMask = new Array(3);
dateMask[0] = dateFormatStr.substring(0, sep1);
dateMask[1] = dateFormatStr.substring(sep1 + 1, sep2);
dateMask[2] = dateFormatStr.substring(sep2 + 1, dateFormatStr.length);

var gDateField;

dayOfWeek = new Array();
dayOfWeek[0] = "Sun";
dayOfWeek[1] = "Mon";
dayOfWeek[2] = "Tue";
dayOfWeek[3] = "Wed";
dayOfWeek[4] = "Thu";
dayOfWeek[5] = "Fri";
dayOfWeek[6] = "Sat";



/*********************************************************************************************
	Function:		showCalendar
	
	Description:	When the calendar widget button is clicked, read the date out of the
					field (if one exists) and pass it into the generateCalendar function
					so it can be highlighted.
					
	Parameters:		field = the form field to return the results of the calendar widget to
					
	Output:			n/a
*********************************************************************************************/
function showCalendar(field)
{
	gDateField = field;
	tmpDate = field.value;
        //tmpDate.value = trim(tmpDate.value);
	
	// parse a date if one exists so the calendar starts at that date
        if (tmpDate == "?") { 
          tmpDate = "" 
        };

	if (tmpDate == "") {
		today = new Date();
		tmp_mm = today.getMonth();
		tmp_dd = 0;
		tmp_yy = today.getYear();
		if (tmp_yy < 2000) {
			tmp_yy += 1900;
		}
	}
	else {
		sep1 = tmpDate.indexOf(gSepChar);
		sep2 = tmpDate.lastIndexOf(gSepChar);
		tmp = new Array(3);
		tmp[0] = tmpDate.substring(0, sep1);
		tmp[1] = tmpDate.substring(sep1 + 1, sep2);
		tmp[2] = tmpDate.substring(sep2 + 1, tmpDate.length);
	
		tmp_mm = parseInt(tmp[gMM], 10) - 1;
		tmp_dd = parseInt(tmp[gDD], 10);
		tmp_yy = parseInt(tmp[gYY], 10);
		if (tmp_yy < 100) {
			if (tmp_yy >= 80) {
				tmp_yy += 1900;
			}
			else {
				tmp_yy += 2000;
			}
		}
	}
	
	calendarWindow = window.open("","Calendar","width=250,height=250,resizable=no,scrollbars=no,screenx=100,screeny=100,left=100,top=100");
	
	generateCalendar(calendarWindow, tmp_mm, tmp_yy, tmp_mm, tmp_dd, tmp_yy);
}



/*********************************************************************************************
	Function:		generateCalendar
	
	Description:	Creates the HTML of the calendar widget based on the specified
					month/year.  Calendar date range is January 1980 to December 2079.
					
	Parameters:		target = window to write the HTML to
	
					mthIdx = month index (0-11) of month to create widget for
					
					year = year to create widget for
					
					curr_mm = month index (0-11) of current value in field
					
					curr_dd = day of current value in field
					
					curr_yy = year of current value in field
					
	Output:			n/a
*********************************************************************************************/
function generateCalendar(target, mthIdx, year, curr_mm, curr_dd, curr_yy)
{
	var monthName = new Array ("January","February","March","April","May","June","July","August","September","October","November","December")

	//begin table for calendar
	target.document.open("text/html", "replace");
	calendar = "<html><head><title>Calendar</title>";
	calendar += "<link rel=stylesheet type=\"text/css\" href=\"gelco.css\"></head>";
	calendar += "<body bgcolor=ffffff>";
	calendar += "<table border=0 cellspacing=0 cellpadding=2 width=100% >";
	calendar += "<tr valign=top>";
	var endday = getDaysInMonth(mthIdx, year);
	
	//month header
	calendar += "<td colspan=7 align=center bgcolor=9900cc>";
	calendar += "<span class=\"brandtextbold\">" + monthName[mthIdx] + " " + year + "<span>";

	//next month and previous month buttons
	var goPrevMonth = prevMonth(mthIdx);
	var goNextMonth = nextMonth(mthIdx);
	var nextYear = changeYear("next", mthIdx, parseInt(year, 10));
	var prevYear = changeYear("prev", mthIdx, parseInt(year, 10));
	var goPrevYear = doPrevYear(year);
	var goNextYear = doNextYear(year);
	var goYearPlus10 = year + 10;
	var goYearMinus10 = year - 10;
	

	calendar += "<tr>";
	// nothing prior to 1/1/1980
	if (mthIdx == 0 && parseInt(year, 10) == 1980) {
		calendar += "<td colspan=2><span class=\"maintextbold\">&nbsp;</span></td>";
	}
	else {
		calendar += "<td colspan=2><span class=\"maintextbold\"><a href=\"javascript:opener.generateCalendar(self, " + goPrevMonth + ", " + prevYear + ", " + curr_mm + ", " + curr_dd + ", " + curr_yy + ")\">< Month</a></span></td>";
	}
	calendar += "<td colspan=3 align=center><span class=\"maintext\"><a href=\"javascript:self.close()\">Cancel</a></span></td>";
	// nothing after 12/31/2079
	if (mthIdx == 11 && parseInt(year, 10) == 2079) {
		calendar += "<td colspan=2 align=right><span class=\"maintextbold\">&nbsp;</span></td>";
	}
	else {
		calendar += "<td colspan=2 align=right><span class=\"maintextbold\"><a href=\"javascript:opener.generateCalendar(self, " + goNextMonth + ", " + nextYear + ", " + curr_mm + ", " + curr_dd + ", " + curr_yy + ")\">Month ></a></span></td>";
	}
	calendar += "</tr>";
	calendar += "<tr>";
	// nothing prior to 1/1/1980
	if (parseInt(year, 10) == 1980) {
		calendar += "<td colspan=2><span class=\"maintextbold\">&nbsp;</span></td>";
	}
	else {
		calendar += "<td class=\"maintextbold\"><a href=\"javascript:opener.generateCalendar(self, " + mthIdx + ", " + goYearMinus10 + ", " + curr_mm + ", " + curr_dd + ", " + curr_yy + ")\"><<</a>";	
		calendar += "<td colspan=2><span class=\"maintextbold\"><a href=\"javascript:opener.generateCalendar(self, " + mthIdx + ", " + goPrevYear + ", " + curr_mm + ", " + curr_dd + ", " + curr_yy + ")\">< Year</a></span></td>";
	}
	calendar += "<td></td>";
	// nothing after 12/31/2079
	if (parseInt(year, 10) == 2079) {
		calendar += "<td colspan=2 align=right><span class=\"maintextbold\">&nbsp;</span></td>";
	}
	else {
		calendar += "<td colspan=2 align=right><span class=\"maintextbold\"><a href=\"javascript:opener.generateCalendar(self, " + mthIdx + ", " + goNextYear + ", " + curr_mm + ", " + curr_dd + ", " + curr_yy + ")\">Year ></a></span></td>";
		calendar += "<td align=right><a href=\"javascript:opener.generateCalendar(self, " + mthIdx + ", " + goYearPlus10 + ", " + curr_mm + ", " + curr_dd + ", " + curr_yy + ")\">>></a></td>";

	}
	calendar += "</tr>";
	
	//writes in the day of the week labels
	calendar += "<tr align=center>";
	calendar += "<td width=15%><span class=\"smalltextbold\">" + dayOfWeek[0] + "</span></td>";
	calendar += "<td width=14%><span class=\"smalltextbold\">" + dayOfWeek[1] + "</span></td>";
	calendar += "<td width=14%><span class=\"smalltextbold\">" + dayOfWeek[2] + "</span></td>";
	calendar += "<td width=14%><span class=\"smalltextbold\">" + dayOfWeek[3] + "</span></td>";
	calendar += "<td width=14%><span class=\"smalltextbold\">" + dayOfWeek[4] + "</span></td>";
	calendar += "<td width=14%><span class=\"smalltextbold\">" + dayOfWeek[5] + "</span></td>";
	calendar += "<td width=15%><span class=\"smalltextbold\">" + dayOfWeek[6] + "</span></td>";
	
	thedate = new Date(year, mthIdx, 1);
	firstDay = thedate.getDay();
	selectedmonth = mthIdx;
	var today = new Date();
	var this_mm = today.getMonth();
	var this_dd = today.getDate();
	var this_yy = today.getYear();
	if (this_yy < 2000) {
		this_yy += 1900;
	}
	
	selectedyear = year;
	var lastDay = (endday + firstDay + 1);
	calendar += "<tr align=center>";
	for (var i = 1; i < lastDay; i++) {
		if (i <= firstDay) {
			// 'empty' boxes prior to first day
			calendar += "<td><span class=\"maintext\">&nbsp;</span></td>";
		}
		else {
			// enter date number
			if (curr_mm == mthIdx && curr_dd == (i - firstDay) && parseInt(year, 10) == curr_yy) {
				calendar += "<td bgcolor=cccccc>";
			}
			else if (this_mm == mthIdx && this_dd == (i - firstDay) && parseInt(year, 10) == this_yy) {
				calendar += "<td bgcolor=ffff66>";
			}
			else {
				calendar += "<td>";
			}
			calendar += "<span class=\"maintext\"><a href=\"javascript:self.close();opener.closeCalendar(" + (mthIdx+1) + ", " + (i-firstDay) + ", " + year + ")\">" + (i-firstDay) + "</a></span></td>";
		}
		// must start new row after each week
		if (i % 7 == 0 &&  i != lastDay) {
			calendar += "<tr align=center>";
		}
	}
	
	//separator line
	calendar += "<tr><td colspan=7><span class=\"maintext\">&nbsp;</span></td>";
	
	calendar += "</table></body></html>";
	target.document.write(calendar);
	target.document.close();
	return;
}



/*********************************************************************************************
	Function:		isLeapYear
	
	Description:	Determine is the given year is a leap year.
					
	Parameters:		yrStr = year to check
					
	Output:			Returns true if the year is a leap and false if not.
*********************************************************************************************/
function isLeapYear(yrStr)
{
	var leapYear = false;
	var year = parseInt(yrStr, 10);
	// every fourth year is a leap year
	if (year % 4 == 0) {
		leapYear = true;
		// unless it's a multiple of 100
		if (year % 100 == 0) {
			leapYear = false;
			// unless it's a multiple of 400
			if (year % 400 == 0) {
				leapYear = true;
			}
		}
	}
	return leapYear;
}



/*********************************************************************************************
	Function:		getDaysInMonth
	
	Description:	Determine the maximum number of days in a given month/year.
					
	Parameters:		mthIdx = month index (0-11) to check
	
					YrStr = year to check
					
	Output:			Returns the maximum number of days in the given month/year.
*********************************************************************************************/
function getDaysInMonth(mthIdx, YrStr)
{
	// all the rest have 31
	var maxDays = 31;
	// except Feb. (of course)
	if (mthIdx == 1) {
		if (isLeapYear(YrStr)) {
			maxDays = 29;
		}
		else {
			maxDays = 28;
		}
	}
	// thirty days hath...
	if (mthIdx == 3 || mthIdx == 5 || mthIdx == 8 || mthIdx == 10) {
		maxDays = 30;
	}
	return maxDays;
}



/*********************************************************************************************
	Function:		nextMonth
	
	Description:	Subset of the generateCalendar function.  Used to handle the "Next"
					link in the calendar widget so December of one year becomes January
					of the following year.
					
	Parameters:		month = month index (0-11) to evaluate
					
	Output:			Returns the month index (0-11) of the next month
*********************************************************************************************/
function nextMonth(month)
{
	if (month == 11) {
		return 0;
	}
	else {
		return (month + 1);
	}
}



/*********************************************************************************************
	Function:		prevMonth
	
	Description:	Subset of the generateCalendar function.  Used to handle the "Previous"
					link in the calendar widget so January of one year becomes December of
					the previous year.
					
	Parameters:		month = month index (0-11) to evaluate
					
	Output:			Returns the month index (0-11) of the previous month
*********************************************************************************************/
function prevMonth(month)
{
	if (month == 0) {
		return 11;
	}
	else {
		return (month - 1);
	}
}

/*********************************************************************************************
	Function:		nextYear
	
	Description:	Subset of the generateCalendar function.  Used to handle the "Next Year"
					link in the calendar for the next year.
					
	Parameters:		year 
					
	Output:			Returns the next Year
*********************************************************************************************/
function doNextYear(year)
{
	return (year + 1);
}


/*********************************************************************************************
	Function:		prevYear
	
	Description:	Subset of the generateCalendar function.  Used to handle the "Previous Year"
					link in the calendar for the previous year.
					
	Parameters:		year
					
	Output:			Returns the previous year
*********************************************************************************************/
function doPrevYear(year)
{
	return (year - 1);
}


/*********************************************************************************************
	Function:		changeYear
	
	Description:	Subset of the generateCalendar function.  Used to handle the "Previous"
					and "Next" links in the calendar widget so moving prior to January or
					after December rolls the year forward to backward.
					
	Parameters:		direction = which way to evaluate ("next" or "prev")
	
					month = month index (0-11) to evaluate
	
					year = year to evaluate
					
	Output:			Returns the new year.
*********************************************************************************************/
function changeYear(direction, month, year)
{
	if (direction == "next" && month == 11) {
		// forward from december
		return (year + 1);
	}
	else if (direction == "prev" && month == 0) {
		// backward from january
		return (year - 1);
	}
	else {
		// forward or back from february thru november
		return year;
	}
}


/*********************************************************************************************
	Function:		closeCalendar
	
	Description:	Called from the calendar widget once a date link is clicked and it
					formats the date clicked and populates the proper field.
					
	Parameters:		mm = month value (1-12) of the date clicked
	
					dd = day value of the date clicked
	
					yy = year value of the date clicked
	
	Output:			n/a
*********************************************************************************************/
function closeCalendar(mm, dd, yy)
{
	field = gDateField;
	field.value = formatDate(mm, dd, yy);
	return;
}



/*********************************************************************************************
	Function:		validateDate
	
	Description:	Tries to validate a string to a date based on the global
					formatting variables (gDateFormat, gSepChar, gMonthChar, gDayChar,
					gYearChar, gMM, gDD and gYY).
					
	Parameters:		field = the form field being validated
					
	Output:			Returns true if the string validates into a date or false if not.
*********************************************************************************************/
function validateDate(field)
{
	// trim off leading and trailing spaces
	tmpDate = trim(field.value);
	
	if (tmpDate == "") {
		return;
	}
	
	// count the number of date seperator characters in the input and in the format mask
	countSepChar = 0;
	countSepCharInMask = 0;
	for (i = 0; i < tmpDate.length; i++) {
		if (tmpDate.charAt(i) == gSepChar) {
			countSepChar++;
		}
	}
	for (i = 0; i < gDateFormat.length; i++) {
		if (gDateFormat.charAt(i) == gSepChar) {
			countSepCharInMask++;
		}
	}
	// valid combos of date seperator characters are:
	// - input has same number as mask
	// - input has 1, mask has 2 and year comes last in the mask
	// everything else is invalid
	if (countSepChar == countSepCharInMask || (countSepChar == 1 && countSepCharInMask == 2 && gYY == 2)) {
		// a-ok so far
	}
	else {
		alert("Invalid entry.  Dates must entered using the format " + gDateFormat + ".");
		field.value = "";
		field.focus();
		return false;
	}
	
	// if year is last (M/D/YY or D/M/YY) in the format, the user can omit the year
	// in this case, automatically append the year based on today's date
	sep1 = tmpDate.indexOf(gSepChar);
	sep2 = tmpDate.lastIndexOf(gSepChar);
	
	// break the string we're validating into three parts
	tmp = new Array(3);
	if (sep1 != -1 && sep2 != -1) {
		if (sep1 == sep2) {
			// only one seperator char (year was omitted so append it for them)
			tmp[0] = tmpDate.substring(0, sep1);
			tmp[1] = tmpDate.substring(sep1 + 1, tmpDate.length);
			today = new Date();
			this_yy = today.getYear();
			if (this_yy < 2000) {
				this_yy += 1900;
			}
			tmp[2] = String(this_yy);
		}
		else {
			// user entered three parts (M, D and Y in whichever order) ... that's good so far
			tmp[0] = tmpDate.substring(0, sep1);
			tmp[1] = tmpDate.substring(sep1 + 1, sep2);
			tmp[2] = tmpDate.substring(sep2 + 1, tmpDate.length);
		}
	}
	else {
		alert("Invalid entry.  Dates must entered using the format " + gDateFormat + ".");
		field.value = "";
		field.focus();
		return false;
	}
	
	// validate month, year and day in that order (even though the format may not have them
	// in that order) because day needs a valid month and year to be properly validated
	dateValid = validateMonth(tmp[gMM], dateMask[gMM]);
	if (dateValid) {
		dateValid = validateYear(tmp[gYY], dateMask[gYY]);
	}
	if (dateValid) {
		dateValid = validateDay(tmp[gDD], tmp[gMM], tmp[gYY], dateMask[gDD]);
	}
	if (!dateValid) {
		alert("Invalid entry.  Dates must entered using the format " + gDateFormat + ".");
		field.value = "";
		field.focus();
		return false;
	}

	field.value = formatDate(tmp[gMM], tmp[gDD], tmp[gYY]);
	return true;
}



/*********************************************************************************************
	Function:		validateMonth
	
	Description:	Subset of the validateDate function.  Tries to validate a month string
					based on the month mask part of the date format string.
					
	Parameters:		txt_mm = the month string being validated
	
					mask = the month mask part of the date format string
					
	Output:			Returns true if the string validates as a month or false if not.
*********************************************************************************************/
function validateMonth(txt_mm, mask)
{
	// must be numeric
	if (isNaN(txt_mm)) {
		return false;
	}
	
	// must be between 1 and 12
	int_mm = parseInt(txt_mm, 10);
	if (int_mm < 1 || int_mm > 12) {
		return false;
	}
	return true;
}



/*********************************************************************************************
	Function:		validateDay
	
	Description:	Subset of the validateDate function.  Tries to validate a day string
					based on the month mask part of the date format string.
					
	Parameters:		txt_dd = the day string being validated
	
					txt_mm = the valid month (1-12) to check max number of days allowed
	
					txt_yy = the valid year to check max number of days allowed
					
					mask = the day mask part of the date format string
					
	Output:			Returns true if the string validates as a day or false if not.
*********************************************************************************************/
function validateDay(txt_dd, txt_mm, txt_yy, mask)
{
	// must be numeric
	if (isNaN(txt_dd)) {
		return false;
	}
	
	int_mm = parseInt(txt_mm, 10);
	int_dd = parseInt(txt_dd, 10);
	int_yy = parseInt(txt_yy, 10);
	
	// must be between 1 and the number of days in the given month, year
	if (int_dd < 1 || int_dd > getDaysInMonth(int_mm - 1, int_yy)) {
		return false;
	}
	
	return true;
}



/*********************************************************************************************
	Function:		validateYear
	
	Description:	Subset of the validateDate function.  Tries to validate a year string
					based on the year mask part of the date format string.  If the mask has
					a 2-digit year, a 4-digit year can still be validated.  This validation
					goes on the assumption that years can range from 1980 to 2079.
					
	Parameters:		txt_yy = the year string being validated
	
					mask = the year mask part of the date format string
					
	Output:			Returns true if the string validates as a year or false if not.
*********************************************************************************************/
function validateYear(txt_yy, mask)
{
	// only accept 2-digit and 4-digit years
	if (txt_yy.length <= 1 || txt_yy.length == 3 || txt_yy.length > 4) {
		return false;
	}
	
	// must be numeric
	if (isNaN(txt_yy)) {
		return false;
	}
	
	// if the year mask is 4 digits, the user entered year must be as well
	if (mask.length == 4 && txt_yy.length != 4) {
		return false;
	}
	
	var today = new Date();
	var this_yy = today.getYear();
	if (this_yy < 2000) {
		this_yy += 1900;
	}
	
	int_yy = parseInt(txt_yy, 10);
	if (int_yy < 100) {
		// 2-digit year entered ... has to be OK (it's just a matter of which century to put it in)
	}
	else {
		// 4-digit year entered ... must be in our 100 year range
		if (int_yy < 1980 || int_yy > 2079) {
			return false;
		}
	}
	
	return true;
}



/*********************************************************************************************
	Function:		formatDate
	
	Description:	Takes a validate date string and formats it based on the global
					formatting variables (gDateFormat, gSepChar, gMonthChar, gDayChar,
					gYearChar, gMM, gDD and gYY).
					
	Parameters:		mm = month value (1-12) of the date to be formatted
	
					dd = day value of the date to be formatted
					
					yy = year value of the date to be formatted
					
	Output:			Returns the formatted date string.
*********************************************************************************************/
function formatDate(mm, dd, yy)
{
	dateStr = "";
	
	for (i = 0; i < 3; i++) {
		if (i > 0) {
			dateStr += gSepChar;
		}
		
		if (gMM == i) {
			tmp = String(mm);
			isYear = false;
		}
		else if (gDD == i) {
			tmp = String(dd);
			isYear = false;
		}
		else if (gYY == i) {
			tmp = String(yy);
			isYear = true;
		}
		
		if (isYear) {
			// years will be either 2 or 4 digits
			if (dateMask[i].length == 2) {
				if (parseInt(tmp, 10) < 100) {
					dateStr += tmp;
				}
				else {
					dateStr += tmp.substring(2, 4);
				}
			}
			else {
				// we've already validated that if the mask is 4 digits, the entry is as well
				dateStr += tmp;
			}
		}
		else {
			// months and days will be either 1 or 2 digits
			// (if it's 1 digit, we still display a 2-digit value if applicable)
			if (dateMask[i].length == 2) {
				if (parseInt(tmp, 10) < 10) {
					// fill in leading zero
					dateStr += "0";
				}
			}
			//dateStr += tmp;
			dateStr += String(parseInt(tmp, 10));
		}
	}
	
	return dateStr;
}

