	/******************************************************************************************************
	 *					 			DatePicker widget and prototypes 		
	 *										  
	 * Created on June 15, 2007
	 *
	 * @author 	
	 * @company WebMeridian Technologies
	 * @contact www.webmeridian.com
	 * @copyright 2007 All Rights Reserved. Company confidential.
	 *
	 * Notes:
	 *		June 14, 2007 - Modified by WebMeridian Technologies to become a pop-up
	 *						widget class with self-closing ability.
	 *
	 *		December 4, 2005 - version 1.5. Copyright by Julian Robichaux
	 *
	 ******************************************************************************************************/

	 
	/**
	  * Obfuscation: Do NOT obfuscate these terms. JS will execute with erros!
	  *
	  *		DatePicker (public class)
	  *		datepicker (public object var)
	  *		display (public method)
	  *		rootcontext (global var)
	  *
	  */
	
	 
	var DEFAULTDATESEPARATOR = "/";					// common values would be "/" or "."
	var DEFAULTDATEFORMAT = "mdy"    				// valid values are "mdy", "dmy", and "ymd"
	var DATEPICKERDIVID = "dpDatePick";
	var IFRAMEDIVID = "dpDatePick_Iframe";

	var dayArrayShort = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
	var dayArrayMed = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	var dayArrayLong = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
	var monthArrayShort = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
	var monthArrayMed = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec');
	var monthArrayLong = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
 
	// check whether Opera and Firefox browser is being used
	var is_opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
	var is_firefox = (navigator.userAgent.toLowerCase().indexOf("firefox") != -1);
	var is_msie = (navigator.userAgent.toLowerCase().indexOf("msie") != -1);
	
	var closeTimer = null;

	/**
	  * Constructor (public)
	  */
	DatePicker = function ( that ) {

		// PROBLEM! This cannot be done this way when using WebMeridian.prototype.setClassStyle().
		// dynamically include its CSS file.
//		var headID = document.getElementsByTagName("head")[0];
//		var cssNode = document.createElement('link');
//		cssNode.type = 'text/css';
//		cssNode.rel = 'stylesheet';
//		if (that) 
//			cssNode.href = that.rootcontext + '/webmeridian/datetime/css/datepicker.css';
//		else
//			cssNode.href = wm_rootcontext + '/webmeridian/datetime/css/datepicker.css';
//		cssNode.media = 'all';
//		headID.appendChild(cssNode);
//		document.appendChild(cssNode);
		
		this.path = "(new DatePicker())";
		if (that) this.path = that.path.datepicker;

		this.dtFormat = DEFAULTDATEFORMAT;
		this.dtSep = DEFAULTDATESEPARATOR;
		this.startDate = "";
	}


	/**
	  *=-----------------------------------------------------------=
	  * displayDatePicker (public)
	  *=-----------------------------------------------------------=
	  * 
	  *	This is the main function you'll call from the onClick event of a button.
	  * Normally, you'll have something like this on your HTML page:
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.display = function( dateFieldName, displayBelowThisObject, startDate, dtFormat, dtSep )
	{
		this.startDate = (startDate) ? this.getFieldDate(startDate) : "";
		this.dtFormat = (dtFormat) ? dtFormat : DEFAULTDATEFORMAT;
		this.dtSep = (dtSep) ? dtSep : DEFAULTDATESEPARATOR;

		// if we weren't told what node to display the datepicker beneath, just display it
		// beneath the date field we're updating
		this.targetDateField = document.getElementsByName(dateFieldName).item(0);
		if (!displayBelowThisObject) displayBelowThisObject = this.targetDateField;

		var x = displayBelowThisObject.offsetLeft;
		var y = displayBelowThisObject.offsetTop + displayBelowThisObject.offsetHeight ;

		// deal with elements inside tables and such
		var parent = displayBelowThisObject;
		while (parent.offsetParent) {
			parent = parent.offsetParent;
			x += parent.offsetLeft;
			y += parent.offsetTop ;
		}

		this.drawDatePicker(x, y);
	}


	/**
	  *=-----------------------------------------------------------=
	  * drawDatePicker
	  *=-----------------------------------------------------------=
	  * 
	  * Draw the datepicker object (which is just a table with calendar elements) at the
	  * specified x and y coordinates, using the this.displayBelowThisObject object as the input tag
	  * that will ultimately be populated with a date.
	  *
	  * This function will normally be called by the display() function.
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.drawDatePicker = function( x, y ) {
		var dt = this.getFieldDate(this.targetDateField.value);

		// the datepicker table will be drawn inside of a <div> with an ID defined by the
		// global DATEPICKERDIVID variable. If such a div doesn't yet exist on the HTML
		// document we're working with, add one.
		if (!document.getElementById(DATEPICKERDIVID)) {
		// don't use innerHTML to update the body, because it can cause global variables
		// that are currently pointing to objects on the page to have bad references
		//document.body.innerHTML += "<div id='" + DATEPICKERDIVID + "' class='dpDiv'></div>";
			var newNode = document.createElement("div");
			newNode.setAttribute("id", DATEPICKERDIVID);
			newNode.setAttribute("class", DATEPICKERDIVID);
			newNode.setAttribute("style", "visibility: hidden;");
			document.body.appendChild(newNode);
		}

		// move the datepicker div to the proper x,y coordinate and toggle the visiblity
		var pickerDiv = document.getElementById(DATEPICKERDIVID);
		pickerDiv.style.position = "absolute";
		pickerDiv.style.left = x + "px";
		pickerDiv.style.top = y + "px";
		pickerDiv.style.visibility = (pickerDiv.style.visibility == "visible" ? "hidden" : "visible");
		pickerDiv.style.display = (pickerDiv.style.display == "block" ? "none" : "block");
		pickerDiv.style.zIndex = 999;

		// draw the datepicker table
		this.refreshDatePicker(this.targetDateField.name, dt.getFullYear(), dt.getMonth(), dt.getDate());


		document.onmouseout = this.rollOutDatePicker;
	}

	
	
	
	DatePicker.prototype.rollOutDatePicker = function( evt ) {
		evt = evt || window.event;
		var target = evt.target || evt.srcElement;

		var pickerDiv = document.getElementById(DATEPICKERDIVID);
		if (pickerDiv.nodeName != 'DIV') return;

		var relativeTarget = evt.relatedTarget || evt.toElement;
		if (relativeTarget) 
		{
			while ((relativeTarget) && (relativeTarget != pickerDiv) && (relativeTarget.nodeName != 'BODY'))
			{
				relativeTarget = relativeTarget.parentNode;
			}
			if (relativeTarget != pickerDiv)	// out, so hide layer
			{
				closeTimer = setTimeout(function() {
								document.onmouseout = null;
								document.onmouseover = null;
								pickerDiv.style.visibility = "hidden";
								pickerDiv.style.display = "none";
								
								// cannot call this.adjustiFrame() here because mouse
								// is no longer focusong on the datepicker object.
								// this.adjustiFrame() does not exist once pickerDiv is none.
								if (is_msie) {
									var iFrameDiv = document.getElementById(IFRAMEDIVID);
									iFrameDiv.style.visibility = pickerDiv.style.visibility ;
									iFrameDiv.style.display = pickerDiv.style.display;
								}
							}, 1000);
			} else
			{
				// clear timeout since mouse moved back into pickerDiv layer
				clearTimeout(closeTimer);
				closeTimer = null;
			}
		}
	}
	
	

	/**
	  *=-----------------------------------------------------------=
	  * refreshDatePicker
	  *=-----------------------------------------------------------=
	  * 
	  * This is the function that actually draws the datepicker calendar.
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.refreshDatePicker = function( dateFieldName, year, month, day )
	{
		// if no arguments are passed, use today's date; otherwise, month and year
		// are required (if a day is passed, it will be highlighted later)
		var thisDay = new Date();

		if ((month >= 0) && (year > 0)) {
			thisDay = new Date(year, month, 1);
		} else {
			day = thisDay.getDate();
			thisDay.setDate(1);
		}

		// the calendar will be drawn as a table
		// you can customize the table elements with a global CSS style sheet,
		// or by hardcoding style and formatting elements below
		var crlf = "\r\n";
		var TABLE = "<table cols=7 class='dpTable'>" + crlf;
		var xTABLE = "</table>" + crlf;
		var TR = "<tr class='dpTR'>";
		var TR_title = "<tr class='dpTitleTR'>";
		var TR_days = "<tr class='dpDayTR'>";
		var TR_todaybutton = "<tr class='dpTodayButtonTR'>";
		var xTR = "</tr>" + crlf;
		var TD = "<td class='dpTD' onMouseOut='this.className=\"dpTD\";' onMouseOver=' this.className=\"dpTDHover\";' ";    // leave this tag open, because we'll be adding an onClick event
		var TD_title = "<td colspan=5 class='dpTitleTD'>";
		var TD_buttons = "<td class='dpButtonTD'>";
		var TD_todaybutton = "<td colspan=7 class='dpTodayButtonTD'>";
		var TD_days = "<td class='dpDayTD'>";
		var TD_selected = "<td class='dpDayHighlightTD' onMouseOut='this.className=\"dpDayHighlightTD\";' onMouseOver='this.className=\"dpTDHover\";' ";    // leave this tag open, because we'll be adding an onClick event
		var xTD = "</td>" + crlf;
		var DIV_title = "<div class='dpTitleText'>";
		var DIV_selected = "<div class='dpDayHighlight'>";
		var xDIV = "</div>";

		// start generating the code for the calendar table
		var html = TABLE;

		// this is the title bar, which displays the month and the buttons to
		// go back to a previous month or forward to the next month
		html += TR_title;
		html += TD_buttons + this.getButtonCode(dateFieldName, thisDay, -1, "&lt;") + xTD;
		html += TD_title + DIV_title + monthArrayShort[ thisDay.getMonth()] + " " + thisDay.getFullYear() + xDIV + xTD;
		html += TD_buttons + this.getButtonCode(dateFieldName, thisDay, 1, "&gt;") + xTD;
		html += xTR;

		// this is the row that indicates which day of the week we're on
		html += TR_days;
		for(i = 0; i < dayArrayShort.length; i++)
			html += TD_days + dayArrayShort[i] + xTD;
		html += xTR;

		// now we'll start populating the table with days of the month
		html += TR;

		// first, the leading blanks
		for (i = 0; i < thisDay.getDay(); i++) html += TD + "&nbsp;" + xTD;

		// now, the days of the month
		do {
			dayNum = thisDay.getDate();
			TD_onclick = " onclick=\"datepicker.updateDateField('" + dateFieldName + "', '" + this.getDateString(thisDay) + "');\">";

			if (dayNum == day)
				html += TD_selected + TD_onclick + DIV_selected + dayNum + xDIV + xTD;
			else
				html += TD + TD_onclick + dayNum + xTD;

			// if this is a Saturday, start a new row
			if (thisDay.getDay() == 6) html += xTR + TR;

			// increment the day
			thisDay.setDate(thisDay.getDate() + 1);
		} while (thisDay.getDate() > 1)

		// fill in any trailing blanks
		if (thisDay.getDay() > 0) {
			for (i = 6; i > thisDay.getDay(); i--)
				html += TD + "&nbsp;" + xTD;
		}
		html += xTR;

		// add a button to allow the user to easily return to today, or close the calendar
		var today = new Date();
		var todayString = "Today is " + dayArrayMed[today.getDay()] + ", " + monthArrayMed[ today.getMonth()] + " " + today.getDate();
		html += TR_todaybutton + TD_todaybutton;
		html += "<button class='dpTodayButton' onClick='" + this.path + ".refreshDatePicker(\"" + dateFieldName + "\");'>today</button> ";
//		html += "<button class='dpTodayButton' onClick='" + this.path + ".updateDateField(\"" + dateFieldName + "\");'>close</button>";
		html += xTD + xTR;

		// and finally, close the table
		html += xTABLE;

		document.getElementById(DATEPICKERDIVID).innerHTML = html;
		// add an "iFrame shim" to allow the datepicker to display above selection lists
		this.adjustiFrame();
	}




	/**
	  *=-----------------------------------------------------------=
	  * updateDateField
	  *=-----------------------------------------------------------=
	  * 
	  * Update the field with the given dateFieldName with the dateString that has been passed,
	  * and hide the datepicker. If no dateString is passed, just close the datepicker without
	  * changing the field value.
	  *  
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.updateDateField = function( dateFieldName, dateString ) {
		var verboseDateString = "";
		
		var arrDate = dateString.split("/");
		switch (this.dtFormat) {
			case "dmy" :
				verboseDateString = monthArrayLong[arrDate[1] - 1] + " " + arrDate[0] + ", " + arrDate[2];
			case "ymd" :
				verboseDateString = monthArrayLong[arrDate[1] - 1] + " " + arrDate[2] + ", " + arrDate[0];
			case "mdy" :
			default :
				verboseDateString = monthArrayLong[arrDate[0] - 1] + " " + arrDate[1] + ", " + arrDate[2];
		}

		this.displayBelowThisObject = document.getElementsByName(dateFieldName).item(0);
		if (dateString) {
			this.displayBelowThisObject.value = dateString;
			if (document.getElementsByName(dateFieldName + "_display").item(0)) {
				document.getElementsByName(dateFieldName + "_display").item(0).value = verboseDateString;
			}
		}
		
		// after the datepicker has closed, optionally run a user-defined function called
		// datePickerClosed, passing the field that was just updated as a parameter
		// (note that this will only run if the user actually selected a date from the datepicker)
		var closeDatePicker = true;
		if ((dateString) && (this.startDate))
			closeDatePicker = this.datePickerClosed(this.displayBelowThisObject);
			
		if (closeDatePicker) {
			var pickerDiv = document.getElementById(DATEPICKERDIVID);
			pickerDiv.style.visibility = "hidden";
			pickerDiv.style.display = "none";

			this.adjustiFrame();
			this.displayBelowThisObject.focus();
		}
	}

	
	

	/**
	  *=-----------------------------------------------------------=
	  * getButtonCode
	  *=-----------------------------------------------------------=
	  * 
	  * Convenience function for writing the code for the buttons 
	  * that bring us back or forward a month.
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.getButtonCode = function( dateFieldName, dateVal, adjust, label )
	{
		var newMonth = (dateVal.getMonth () + adjust) % 12;
		var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12);
		if (newMonth < 0) {
			newMonth += 12;
			newYear += -1;
		}

		return "<button class='dpButton' onClick='" + this.path + ".refreshDatePicker(\"" + dateFieldName + "\", " + newYear + ", " + newMonth + ");'>" + label + "</button>";
	}



	/**
	  *=-----------------------------------------------------------=
	  * datePickerClosed
	  *=-----------------------------------------------------------=
	  * 
	  * If given a startDate, make sure selected date is startDate.
	  *
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.datePickerClosed = function( dateField )
	{
		var dateObj = this.getFieldDate(dateField.value);

		if (dateObj < this.startDate) {
			// if the date is before today, alert the user and display the datepicker again
			alert("Please enter a date that is on or after " + this.startDate);
			dateField.value = "";
//			document.getElementById(DATEPICKERDIVID).style.visibility = "visible";
//			this.adjustiFrame();
			return false;
		} else {
			// if the date is okay, set the EndDate field to 7 days after the StartDate
//			dateObj.setTime(dateObj.getTime() + (7 * 24 * 60 * 60 * 1000));
//			var endDateField = document.getElementsByName ("EndDate").item(0);
//			endDateField.value = this.getDateString(dateObj);
			return true;
		}
	}



	/**
	  *=-----------------------------------------------------------=
	  * adjustiFrame
	  *=-----------------------------------------------------------=
	  * 
	  * Use an "iFrame shim" to deal with problems where the datepicker shows up behind
	  * selection list elements, if they're below the datepicker.
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.adjustiFrame = function( pickerDiv, iFrameDiv )
	{
		// we know that Opera and Firefox do not need iFrame shimming around combo-boxes.
		if (!is_msie) return;
	  
		// put a try/catch block around the whole thing, just in case
		try {
			if (!document.getElementById(IFRAMEDIVID)) {
				// don't use innerHTML to update the body, because it can cause global variables
				// that are currently pointing to objects on the page to have bad references
				//document.body.innerHTML += "<iframe id='" + IFRAMEDIVID + "' src='javascript:false;' scrolling='no' frameborder='0'>";
				var newNode = document.createElement("iFrame");
				newNode.setAttribute("id", IFRAMEDIVID);
				newNode.setAttribute("src", "/blank.html");
				newNode.setAttribute("scrolling", "no");
				newNode.setAttribute ("frameborder", "0");
				document.body.appendChild(newNode);
			}

			if (!pickerDiv) pickerDiv = document.getElementById(DATEPICKERDIVID);
			if (!iFrameDiv) iFrameDiv = document.getElementById(IFRAMEDIVID);

			try {
				iFrameDiv.style.position = "absolute";
				iFrameDiv.style.width = pickerDiv.offsetWidth;
				iFrameDiv.style.height = pickerDiv.offsetHeight ;
				iFrameDiv.style.top = pickerDiv.style.top;
				iFrameDiv.style.left = pickerDiv.style.left;
				iFrameDiv.style.zIndex = pickerDiv.style.zIndex - 1;
				iFrameDiv.style.visibility = pickerDiv.style.visibility ;
				iFrameDiv.style.display = pickerDiv.style.display;
			} catch(e) {}
		} catch (ee) {}
	 
	}


	
	
	/**
	  *=-----------------------------------------------------------=
	  * getDateString
	  *=-----------------------------------------------------------=
	  * 
	  * Convert a JavaScript Date object to a string, based on 
	  * the this.dtFormat and this.dtSep variables at the beginning of this script library.
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.getDateString = function( dateVal )
	{
		var dayString = "00" + dateVal.getDate();
		var monthString = "00" + (dateVal.getMonth()+1);
		dayString = dayString.substring(dayString.length - 2);
		monthString = monthString.substring(monthString.length - 2);

		switch (this.dtFormat) {
			case "dmy" :
				return dayString + this.dtSep + monthString + this.dtSep + dateVal.getFullYear();
			case "ymd" :
				return dateVal.getFullYear() + this.dtSep + monthString + this.dtSep + dayString;
			case "mdy" :
			default :
				return monthString + this.dtSep + dayString + this.dtSep + dateVal.getFullYear();
		}
	}



	/**
	  *=-----------------------------------------------------------=
	  * getButtonCode
	  *=-----------------------------------------------------------=
	  * 
	  * Convert a string to a JavaScript Date object 
	  * where time is not relevant (thus, set to mid-night).
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 
	  * Notes:
	  *		new Date(year, month, day, hours, minutes, seconds, milliseconds)
	  *
	  */
	DatePicker.prototype.getFieldDate = function( dateString )
	{
		var dateVal;
		var dArray;
		var d, m, y;

		try {
			dArray = this.splitDateString(dateString);
			if (dArray) {
				switch (this.dtFormat) {
					case "dmy" :
						d = parseInt(dArray[0], 10);
						m = parseInt(dArray[1], 10) - 1;
						y = parseInt(dArray[2], 10);
						break;
					case "ymd" :
						d = parseInt(dArray[2], 10);
						m = parseInt(dArray[1], 10) - 1;
						y = parseInt(dArray[0], 10);
						break;
					case "mdy" :
					default :
						d = parseInt(dArray[1], 10);
						m = parseInt(dArray[0], 10) - 1;
						y = parseInt(dArray[2], 10);
						break;
				}
				dateVal = new Date(y, m, d, 0, 0, 0);
			} else if (dateString) {
				dateVal = new Date(dateString.getFullYear(), dateString.getMonth(), dateString.getDate(), 0, 0, 0);
			} else {
				var today = new Date();
				dateVal = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
			}
		} catch(e) {
			var today = new Date();
			dateVal = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
		}

		return dateVal;
	}



	/**
	  *=-----------------------------------------------------------=
	  * splitDateString
	  *=-----------------------------------------------------------=
	  * 
	  * Try to split a date string into an array of elements, using common date separators.
	  * If the date is split, an array is returned; otherwise, we just return false. 
	  *  
	  * Parameters:
	  * 
	  * Returns:
	  * 	none
	  * 		 
	  */
	DatePicker.prototype.splitDateString = function( dateString )
	{
		var dArray;
		if (dateString.indexOf("/") >= 0)
			dArray = dateString.split("/");
		else if (dateString.indexOf(".") >= 0)
			dArray = dateString.split(".");
		else if (dateString.indexOf("-") >= 0)
			dArray = dateString.split("-");
		else if (dateString.indexOf("\\") >= 0)
			dArray = dateString.split("\\");
		else
			dArray = false;

		return dArray;
	}

