function compareCalendarDates(source, arguments)
{
	try
	{
		var strID = source.id;
		var n = strID.lastIndexOf("_");
		var strStartID = strID.substr(0,n+1) + "dtStart";
		var strEndID = strID.substr(0,n+1) + "dtEnd";
		
		//	Check is year should be taken into account
		var ctrl = document.getElementById(strStartID)
		if (ctrl.noyear == true)
		{
			arguments.IsValid = true;
			return;
		}
		
		var dt1 = convertDate(document.getElementById(strStartID));
		var dt2 = convertDate(document.getElementById(strEndID));

		arguments.IsValid = (dt1 <= dt2);
	}
	catch(e)
	{
		arguments.IsValid = false;
	}
}

function Calendar (cname, id, date, displayYear)
{
	//	User to toggle year display and use feature
	this.displayYear = displayYear;
	
	// Used to notify the calendar that it is attached to a single html field.
	this.fallback_single = 0;
	
	// Used to notify the claendar that it is attached to 3 html fields.
	this.fallback_multi = 1;
	
	// Used to notify the calendar that it is attached to both field sets.
	this.fallback_both = 2;
	
	// Read-only calendar
	this.viewOnly = false;
	
	// Allows the user to select weekends
	this.allowWeekends = true;
	
	// Allows the user to select weekdays
	this.allowWeekdays = true;
	
	// The minimum date that the user can select (inclusive)
	this.minDate = "--";
	
	// The maximum date that the user can select (exclusive)
	this.maxDate = "--";
	
	// Allow the user to scroll dates
	this.scrolling = true;
	
	// The id of this calendar
	this.name = cname;
	
	// The first day of the week in the calendar (0-Sunday, 6-Saturday)
	this.firstDayOfWeek = 0;
	
	// Fallback method
	this.fallback = this.fallback_both;
	
	// Sets the date and strips out time information
	this.calendarDate = date;
	if(!this.displayYear)
	{
		this.calendarDate.setFullYear(2000);
	}
	this.calendarDate.setHours(0);
	this.calendarDate.setMinutes(0);
	this.calendarDate.setSeconds(0);
	this.calendarDate.setMilliseconds(0);
	
	// The field id that the calendar is attached to.
	// For single input, this is used "as is". for the
	// Multi-input, it is given a suffix for _day, _month
	// and _year inputs.
	this.attachedId = id;
	
	if(displayYear == false)
	{
		document.getElementById(id).noyear = true;
	}
	
	// The left and right month control icons
	this.controlLeft = "&#171;";
	this.controlRight = "&#187;";

      // The left and right month control icons (when disabled)
      this.controlLeftDisabled = "";
      this.controlRightDisabled = "";

      // The css classes for the calendar and header
      this.calendarStyle = "cal_calendar";
      this.headerStyle = "cal_header";
      this.headerCellStyle = "cal_cell";
      this.headerCellStyleLabel = "cal_labelcell";

      // The css classes for the rows
      this.weekStyle = "cal_week";
      this.evenWeekStyle = "cal_evenweek";
      this.oddWeekStyle = "cal_oddweek";

      // The css classes for the day elements
      this.dayStyle = "cal_day";
      this.disabledDayStyle = "cal_disabled";
      this.commonDayStyle = "cal_common";
      this.holidayDayStyle = "cal_holiday";
      this.eventDayStyle = "cal_event";
      this.todayDayStyle = "cal_today";

      // specifies the labels for this calendar
      this.dayLabels = document.dayLabels || ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
      this.monthLabels = document.monthLabels || ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
      
      var mc = document.getElementById("cal_month");
      if(mc.options.length == 0){
          for(var i = 0; i < this.monthLabels.length; i++){
            var oOption = document.createElement("OPTION");
            oOption.text = this.monthLabels[i];
            oOption.value = i+1;
            
            try {
                mc.add(oOption);
            }
            catch(e){
                mc.add(oOption, null);
            }
          }
      }

      // Specifies the dates of any event. The events are to be defined as arrays,
      // with element 0 being the date and element 1 being an id.
      this.eventDates = new Array();

      // Attach event handlers to any fallback fields.
      if (this.viewOnly == false) {

      setFieldValue(this, this.calendarDate);

      if ((this.fallback = this.fallback_both) || (this.fallback = this.fallback_single)) {
      eval("document.getElementById(\"" + this.attachedId + "\").onchange = function () {updateFromSingle("+this.name+", this);}");
      }
      }

      selectEvent = new Function();
      }

      function onselectActivate()
      {
      document.all.outer_div.onmouseout = null;
      //	document.onmousedown = null;
      }

      function onselectDeactivate()
      {
      document.all.outer_div.onmouseout = "document.onmousedown = Calendar_Up_LostFocus;";
      //Calendar_curPicker = '';
      //	document.onmousedown = Calendar_Up_LostFocus;
      }

      function updateFromSingle (sender, helper) {
      newDate = convertDate(helper);
      if (isNaN(newDate))
      {
      newDate = new Date(1901, 0, 1);
      }

      //	newDate.setDate(newDate.getDate()+1);
      sender.calendarDate = newDate;

      renderCalendar (sender);
      setFieldValue(sender, sender.calendarDate);
      }

      function updateFromMultiDay (sender, helper) {

      if (isNaN(helper.value)) {
      helper.value = sender.calendarDate.getDate();
      return false;
      }

      sender.calendarDate.setDate(helper.value);
      renderCalendar (sender);
      setFieldValue(sender, sender.calendarDate);
      }

      function updateFromMultiMonth (sender, helper) {

      if (isNaN(helper.value)) {
      helper.value = sender.calendarDate.getMonths() -1;
      return false;
      }

      sender.calendarDate.setMonth(helper.value-1);
      renderCalendar (sender);
      setFieldValue(sender, sender.calendarDate);

      document.all.outer_div.onmouseout = "document.onmousedown = Calendar_Up_LostFocus;";
      //	document.onmousedown = Calendar_Up_LostFocus;
      }

      function updateFromMultiYear (sender, helper) {

      if (isNaN(helper.value)) {
      helper.value = sender.calendarDate.getFullYear();
      return false;
      }

      sender.calendarDate.setFullYear(helper.value);
      renderCalendar (sender);
      setFieldValue(sender, sender.calendarDate);
      }

      function getFirstCalendarDate (calendar)
      {
      if(calendar.displayYear)
      {
      if(calendar.calendarDate.getDate() == 1 && calendar.calendarDate.getFullYear() == 1901 && calendar.calendarDate.getMonth() == 0)
		{
			calendar.calendarDate = new Date();
		}
		return new Date (calendar.calendarDate.getFullYear(), calendar.calendarDate.getMonth(), 1);
	}
	return new Date (2000, calendar.calendarDate.getMonth(), 1);
}

function renderCalendar (calendar)
{
	var div = document.getElementById('outer_div');
	if(div.style.visibility == 'hidden') 
	{
		return;
	}
	
	currentDate = getFirstCalendarDate(calendar);
	
//	calHtml1 =  buildHelperControls();
	calHtml1 =  ("<table cellspacing=0 cellpadding=0 id=\"cal_display\" class=\"" + calendar.calendarStyle +"\">");
	calHtml1 += ((calendar.scrolling)?buildHeader(calendar):buildStaticHeader(calendar));
	calHtml1 += buildCalendarTable (calendar);
	calHtml1 += ("</table>");

			document.getElementById("cal_display").innerHTML = calHtml1;
			}

			function scrollMonthBack (calendar)
			{
			var dt = new Date(calendar.calendarDate);
			dt.setMonth(calendar.calendarDate.getMonth() - 1);
			if(dt.getMonth() == calendar.calendarDate.getMonth()){
			dt.setDate(0);
			}
			calendar.calendarDate = dt;
			setFieldValue(calendar, calendar.calendarDate);
			renderCalendar (calendar);
			}

			function selectDate (calendar, day)
			{
			if (!calendar.viewOnly)
			{
			if(!calendar.displayYear)
			{
			calendar.calendarDate.setFullYear(2000);
			}
			calendar.calendarDate.setDate(day);

			setFieldValue(calendar, calendar.calendarDate);

			//renderCalendar (calendar);
			document.getElementById(Calendar_curPicker).style.visibility = 'hidden';
			document.getElementById("outer_frame").style.visibility = 'hidden';
			document.getElementById("cal_year").style.visibility = 'hidden';
			Calendar_Up_ShowHideDDL('visible');
			Calendar_curPicker = '';
			}
			}

			function scrollMonthForward (calendar)
			{
			var dt = new Date(calendar.calendarDate);
			dt.setMonth(calendar.calendarDate.getMonth() + 1);
			if(dt.getMonth() == (calendar.calendarDate.getMonth()+2)){
			dt.setDate(0);
			}
			calendar.calendarDate = dt;
			setFieldValue(calendar, calendar.calendarDate);
			renderCalendar (calendar);
			}

			function setFieldValue(cal, date) {
			cal.calendarDate = date;
			if(typeof(cal.onchanged) == "function")
			{
			cal.onchanged(date);
			}
			if(cal.displayYear)
			{
			if(date.getDate() == 1 && date.getFullYear() == 1901 && date.getMonth() == 0)
		{
			document.getElementById(cal.attachedId).value = '';
			return;
		}
		else
		{
			document.getElementById(cal.attachedId).value =  date.getDate() + "/" + (date.getMonth()+1) + "/" + date.getFullYear();
		}
	}
	else
	{
		var dtVal = cal.monthLabels[date.getMonth()].substr(0,3) + " " + date.getDate();
		var day = date.getDate();
		if (day == 11 || day == 12 || day == 13) 
		{
			dtVal += "th";
		}
		else if (day == 1 || day == 31) 
		{
			dtVal += "st";
		}
		else if (day == 2 || day == 22) 
		{
			dtVal += "nd";
		}
		else if (day == 3 || day == 23)
		{
			dtVal += "rd";
		}
		else
		{
			dtVal += "th";
		}
		
		document.getElementById(cal.attachedId).value = dtVal;
	}
	document.getElementById("cal_year").value = date.getFullYear();
	document.getElementById("cal_month").selectedIndex = date.getMonth();
	document.getElementById("cal_day").value = date.getDate();
	if(typeof(cal.onnotifychange) == "function")
	{
		cal.onnotifychange(date);
	}
}

function buildHeader (calendar)
{
	enableLeft = true;
	enableRight = true;
	
	if (calendar.minDate != "--") 
	{
		if (calendar.calendarDate.getFullYear() <= calendar.minDate.getFullYear())
		{
			if (calendar.calendarDate.getMonth() <= calendar.minDate.getMonth())
			{
				enableLeft = false;
			}
		}
	}

	if (calendar.maxDate != "--") 
	{
		if (calendar.calendarDate.getFullYear() >= calendar.maxDate.getFullYear())
		{
			if (calendar.calendarDate.getMonth() >= calendar.maxDate.getMonth())
			{
				enableRight = false;
			}
		}
	}

	calHtml2 = "";
	
	calHtml2 +=  (
		"<tr class=\""
		+ calendar.headerStyle
		+ "\">");
	calHtml2 +=  (
		"<td width=\"40\" class=\""
		+ calendar.headerCellStyle
		+ ((enableLeft)?("\" onclick=\"scrollMonthBack(" + calendar.name + ")"):"")
		+ "\">"
		+ ((enableLeft)?calendar.controlLeft:calendar.controlLeftDisabled)
		+ "</td>");
	calHtml2 +=  (
		"<td colspan=\"5\" width=\"170\" class=\""
		+ calendar.headerCellStyleLabel
		+ "\">"
		+ calendar.monthLabels[calendar.calendarDate.getMonth()] 
		+ (calendar.displayYear ? (", " + calendar.calendarDate.getFullYear()) : "")
		+ "</td>");
	calHtml2 +=  (
		"<td width=\"40\" class=\""
		+ calendar.headerCellStyle
		+ ((enableRight)?("\" onclick=\"scrollMonthForward(" + calendar.name + ")"):"")
		+ "\">"
		+ ((enableRight)?calendar.controlRight:calendar.controlRightDisabled)
		+ "</td>");
	
	calHtml2 += ("</tr>");

	if(calendar.displayYear)
	{	
		calHtml2 +=  (
			"<tr class=\""
			+ calendar.headerStyle
			+ "\">")

		for (i = 0; i < 7; i++) {
			showDay = i + calendar.firstDayOfWeek;
			if (showDay > 6) showDay = showDay - 7;
			calHtml2 +=  (
				"<td class=\""
				+ calendar.headerCellStyle
				+ "\">"
				+ calendar.dayLabels[showDay]
				+ "</td>");
		}

		calHtml2 += ("</tr>");
	}
	return calHtml2
}

function buildStaticHeader (calendar)
{
	calHtml2 = "";
	
	calHtml2 +=  (
		"<tr class=\""
		+ calendar.headerStyle
		+ "\">");
	calHtml2 +=  (
		"<td colspan=\"7\" width=\"200\" class=\""
		+ calendar.headerCellStyleLabel
		+ "\">"
		+ calendar.monthLabels[calendar.calendarDate.getMonth()] 
		+ ", " + calendar.calendarDate.getFullYear()
		+ "</td>");	
	calHtml2 += ("</tr>");
	
	calHtml2 +=  (
		"<tr class=\""
		+ calendar.headerStyle
		+ "\">")

	for (i = 0; i < 7; i++) {
		showDay = i + calendar.firstDayOfWeek;
		if (showDay > 6) showDay = showDay - 7;
		calHtml2 +=  (
			"<td class=\""
			+ calendar.headerCellStyle
			+ "\">"
			+ calendar.dayLabels[showDay]
			+ "</td>");
	}

	calHtml2 += ("</tr>");
	return calHtml2
}

function RenderDayDisabled (calendar, currentDate)
{
	calHtml += ('<td class="day">');
	calHtml += ("<span class=\"" + calendar.disabledDayStyle + "\">");
	calHtml += (currentDate.getDate());
	calHtml += ("</span>");
	calHtml += ("</td>");
}

function RenderDayEnabled (calendar, currentDate, dayStyle)
{
	currentDayStyle = dayStyle;
	calHtml += ('<td class="day">');
	calHtml += ("<span class=\"" + dayStyle + "\" onclick=\"selectDate(" + calendar.name + ", " + currentDate.getDate() + ")\">");
	calHtml += (currentDate.getDate());
	calHtml += ("</span>");
	calHtml += ("</td>");
}

function RenderDayEvent (calendar, currentDate, dayStyle, eventId)
{
	currentDayStyle = dayStyle;
	calHtml += ('<td class="day">');
	calHtml += ("<span class=\"" + dayStyle + "\" onclick=\"selectDate(" + calendar.name + ", " + currentDate.getDate() + "); " + calendar.name + ".selectEvent('" + eventId + "')\">");
	calHtml += (currentDate.getDate());
	calHtml += ("</span>");
	calHtml += ("</td>");
}

function buildCalendarTable (calendar)
{
	currentDate = getFirstCalendarDate(calendar);
	odd = 0;
	
	if(calendar.displayYear)
	{
		while (currentDate.getDay() != calendar.firstDayOfWeek)
		{
			currentDate.setDate(currentDate.getDate() - 1);
		}
	}

	calHtml = "";
	do
	{
		odd += 1;

		calHtml +=  (
			"<tr class=\"" + (((odd%2)==0) ? calendar.evenWeekStyle : calendar.oddWeekStyle) + "\">")

		for (i = 0;i < 7;i++)
		{
			currentDayStyle = calendar.dayStyle;
			currentEventStyle = calendar.commonDayStyle;
			currentDateString = currentDate.getFullYear() + "/" + (currentDate.getMonth()+1) + "/" + currentDate.getDate();
			
			if(calendar.displayYear)
			{
				if (currentDate < calendar.minDate) 
				{
					RenderDayDisabled (calendar, currentDate);
				} 
				else if (currentDate > calendar.maxDate) 
				{
					RenderDayDisabled (calendar, currentDate);
				} 
				else if (currentDate.getMonth() != calendar.calendarDate.getMonth())
				{
					RenderDayDisabled (calendar, currentDate);
				}
				else if (currentDate.getDate() == calendar.calendarDate.getDate())
				{
					if ((currentDate.getDay() == 0) || (currentDate.getDay() == 6))
					{
						if (calendar.allowWeekends == true)
						{
							RenderDayEnabled (calendar, currentDate, calendar.todayDayStyle);
						} 
						else 
						{
							RenderDayDisabled (calendar, currentDate);	
							month = calendar.calendarDate.getMonth();
							calendar.calendarDate.setDate(calendar.calendarDate.getDate());
							if (month != calendar.calendarDate.getMonth())
							{
								renderCalendar(calendar);
							}
							setFieldValue(calendar, calendar.calendarDate);
						}
					} else {
						if (calendar.allowWeekdays == true)
						{
							RenderDayEnabled (calendar, currentDate, calendar.todayDayStyle);
						} 
						else 
						{
							RenderDayDisabled (calendar, currentDate);	
							month = calendar.calendarDate.getMonth();
							calendar.calendarDate.setDate(calendar.calendarDate.getDate());
							if (month != calendar.calendarDate.getMonth())
							{
								renderCalendar(calendar);
							}
							setFieldValue(calendar, calendar.calendarDate);
						}
					}
				}
				else if ((currentDate.getDay() == 0) || (currentDate.getDay() == 6))
				{
					if (calendar.allowWeekends == true)
					{
						style = calendar.holidayDayStyle
						
						for (j=0; j < calendar.eventDates.length; j++)
						{
							if (calendar.eventDates[j][0] == currentDateString) 
							{
								style = calendar.eventDayStyle;
								RenderDayEvent (calendar, currentDate, style, calendar.eventDates[j][0]);
							}
						}
						
						if (style == calendar.holidayDayStyle)
						{
							RenderDayEnabled (calendar, currentDate, style);
						}
					} 
					else 
					{
						RenderDayDisabled (calendar, currentDate);	
					}
				} else {
					if (calendar.allowWeekdays == true)
					{
						style = calendar.commonDayStyle

						for (j=0; j < calendar.eventDates.length; j++)
						{
							if (calendar.eventDates[j][0] == currentDateString) 
							{
								style = calendar.eventDayStyle;
								RenderDayEvent (calendar, currentDate, style, calendar.eventDates[j][0]);
							}
						}

						if (style == calendar.commonDayStyle)
						{
							RenderDayEnabled (calendar, currentDate, style);
						}
					} 
					else 
					{
						RenderDayDisabled (calendar, currentDate);	
					}
				}
			}
			else
			{
				if(currentDate.getMonth() != calendar.calendarDate.getMonth())
				{
					continue;
				}
				RenderDayEnabled (calendar, currentDate, calendar.commonDayStyle);
			}

			currentDate.setDate(currentDate.getDate() + 1);	
		}
		
		calHtml += ("</tr>");


      } while (currentDate.getMonth() == calendar.calendarDate.getMonth());
      return calHtml;
      }

      var Calendar_curPicker = '';

      if (navigator.appName == 'Netscape')
      {
      document.captureEvents(Event.CLICK);
      }

      function Calendar_Up_LostFocus(e)
      {
      Calendar_Up_HideNonCurrentPicker('');
      }

      function Calendar_Up_HideNonCurrentPicker(divName)
      {
      if(Calendar_curPicker != '')
      {
        document.getElementById(Calendar_curPicker).style.visibility = 'hidden';
        document.getElementById("outer_frame").style.visibility = 'hidden';
        document.getElementById("cal_year").style.visibility = 'hidden';
        Calendar_Up_ShowHideDDL('visible');
        Calendar_curPicker = '';
      }
      if(divName != '')
      {
      Calendar_curPicker = divName;
      }
      }

      function Calendar_Up_ShowHideDDL(visibility)
      {
      for(j=0;j<document.forms.length;j++) 
	{
		for(i=0;i<document.forms[j].elements.length;i++) 
		{
			if(document.forms[j].elements[i].type != null) 
			{
				if(document.forms[j].elements[i].type.indexOf('select') == 0 && document.forms[j].elements[i].id != "cal_month" && document.forms[j].elements[i].id != "cal1_month")
		{
		document.forms[j].elements[i].style.visibility = visibility;
		}
		}
		}
		}
		}

		function Calendar_Up_findPosX(obj)
		{
		var curleft = 0;
		if (obj.offsetParent)
		{
		while (obj)
		{
		curleft += obj.offsetLeft;
		obj = obj.offsetParent;
		}
		}
		else if (obj.x)
		{
		curleft += obj.x;
		}
		return curleft;
		}

		function Calendar_Up_findPosY(obj)
		{
		var curtop = 0;
		if (obj.offsetParent)
		{
		while (obj)
		{
		curtop += obj.offsetTop;
		obj = obj.offsetParent;
		}
		}
		else if (obj.y)
		{
		curtop += obj.y;
		}
		return curtop;
		}

		function Calendar_Up_DisplayPicker(cal, tbName)
		{
		divName = "outer_div";
		enableHide = false;
		var div, tb;
		var frm;
		div = document.getElementById(divName);
		tb = document.getElementById(tbName);
		frm = document.getElementById("outer_frame");

		if(div.style.visibility != 'hidden')
		{
		div.style.visibility = 'hidden';
		frm.style.visibility = 'hidden';
		if(enableHide)
		{
		Calendar_Up_ShowHideDDL('visible');
		}
		document.getElementById("cal_year").style.visibility = 'hidden';
		}
		else
		{
		Calendar_Up_HideNonCurrentPicker(divName)
		if(enableHide)
		{
		Calendar_Up_ShowHideDDL('hidden');
		}
		div.style.position = 'absolute';
		var obj = tb;
		var y = Calendar_Up_findPosY(obj);
		var x = Calendar_Up_findPosX(obj);

		y += (obj.offsetHeight + 1);

		div.style.left = x + 'px';
		div.style.top = y + 'px';
		div.style.border = 'black 1px solid';
		div.style.visibility = 'visible';

		var func = cal.onchanged;
		cal.onchanged = null;

		if(cal.displayYear)
		{
		updateFromSingle(cal, tb);
		}
		else
		{
		if(!updateFromSingle(cal, tb))
		{
		setFieldValue(cal, cal.calendarDate);
		renderCalendar(cal);
		}
		}
		cal.onchanged = func;

		eval("document.getElementById(\"cal_day\").onchange = function () {updateFromMultiDay("+cal.name+", this);}");
		eval("document.getElementById(\"cal_month\").onchange = function () {updateFromMultiMonth("+cal.name+", this);}");
		eval("document.getElementById(\"cal_year\").onchange = function () {updateFromMultiYear("+cal.name+", this);}");
		eval("document.getElementById(\"cal_month\").onactivate = onselectActivate");
		eval("document.getElementById(\"cal_month\").ondeactivate = onselectDeactivate");

		document.getElementById("cal_year").style.visibility = cal.displayYear ? 'visible' : 'hidden';
		}

		frm.style.position = div.style.position;
		frm.style.left = div.style.left;
		frm.style.top = div.style.top;
		frm.style.visibility = div.style.visibility;
		frm.style.width = div.offsetWidth + 'px';
		frm.style.height = div.offsetHeight + 'px';
		frm.style.border = 'none';
		//eq;
		}

		function convertDate(tbDate)
		{
		var strDate = tbDate.value;
		var ss = strDate.split("/");
		if(!tbDate.noyear)
		{
		if(ss[2] < 100)
		{
			ss[2] = 2000 + 1*ss[2];
		}
		return new Date(ss[2], ss[1]-1, ss[0]);
	}
	
	var nDay = parseInt(ss[0]);
	var nMonth = parseInt(ss[1]);
	
	if(isNaN(nDay) || isNaN(nMonth))
	{
		return NaN;
	}
	
	if(nMonth > 12) nMonth = 12;
	if(nMonth < 1) nMonth = 1;
	nMonth -= 1;
	
	if(nDay < 1) nDay = 1;
	
	var dt = new Date(2000, nMonth, nDay)
	
	//	Date was shifted, because date > month's days
	if(dt.getMonth() != nMonth)
	{
		//	Change it to the last day of the month
		dt.setMonth(nMonth+1, 1);
		dt.setDate(0);
	}
	
	return dt;
}
