/* Written by: Vic Hollis */
var SELECTED 	= 1;
var ENABLED 	= 2;
var HIGHLIGHTED = 4;
var INITALIZED	= 8;

if(document.all) {
	var gDivId = null;
	var gDivRect = null;
}
var gCal=null;
var gOldVal=null;

function OnMBDown(e) {
	var x, y;
	
	if(gCal == null)
		return;
		
	if(document.all) {
			var e = window.event;
			x = e.clientX;
			y = e.clientY;
			
			if(gDivRect != null) {
				if(document.getElementById(gDivId).style.display == "block" && !gDivRect.PtInRect(x, y)) {
					document.getElementById(gDivId).style.display = "none";
					showElement("SELECT");
					gCal.Visible = false;
				}
			}
		}
		else {
			x = e.clientX;
			y = e.clientY;
			if(gDivId != null && document.getElementById(gCal.DivId).style.display == "block" && !gCal.DivRect.PtInRect(x, y)) {
				document.getElementById(gCal.DivId).style.display = "none";
				showElement("SELECT");
				gCal.Visible = false;
			}
		}
	
}
document.onmousedown = OnMBDown;
if (document.captureEvents && typeof event != "undefined") 
	document.captureEvents(event.MOUSEDOWN);
	
// Sample calendar Interface.... all calendar interfaces should follow the below example.
// Parameters are in order: DateRange object, html input Id of arrival text box, 
// 	 html input Id of departure text box, calendars js name so it can reference itself.
function TwoMonthCalendar(dtRng, arrId, depId, divId, nm) {
	
	if(document.all) {
		gDivId = divId;
	}
	this.DivId = null;
	
	
	// METHODS
	function OnChange() {
		if(this.value == gOldVal)
			return;
			
		if(this.value.length > 0) {
			var Write = false;
			if(this.value.length > 0) {
				var Arr = this.value.split("/");
				if(!isUndefined(Arr[0]) && Arr[0].length > 0) {
					gCal.Month = parseInt(Arr[0], 10);
					Write = true;
				}
				
				if(!isUndefined(Arr[2]) && Arr[2].length > 0) {
					if(Arr[2].length == 1 || Arr[2] == '2' || Arr[2] == '20' || Arr[2] == '200') {
						Write = false;
					}
					else {
						if(Arr[2].length == 2) {
							gCal.Year = parseInt(Arr[2], 10);
							gCal.Year += 2000;
							var tdt = new Date(Arr[0] + "/" + Arr[1] + "/" + gCal.Year);
							if(isObject(gCal.Range) && !gCal.Range.isBeforeRange(tdt) && !gCal.Range.isAfterRange(tdt)) {
								this.value = Arr[0] + "/" + Arr[1] + "/" + gCal.Year;
							}
						}
					}
				}
				else {
					var dt = new Date();
					gCal.Year = dt.getFullYear();
				}
				
				if(Write) {
					var sd = document.getElementById(gCal.ArrivalId);
					var ed = document.getElementById(gCal.DepartureId);
					var sdd = new Date(sd.value);
					var edd = new Date(ed.value);
					if(sdd.getTime() > edd.getTime()) {
						alert("Start date is after end date");
						this.value = "";
					}
					gCal.WriteCal();
				}
			}
		}
		gOldVal = this.value;		
	}
	this.OnChange = OnChange;
	
	function OpenCal(OpenedFromElem) {
		// GOTTA FIX MOZILLA IE STABLE BUILD 
		if(!document.all)
			if(this.Visible == true)
				return;
		
		gCal = this;
		OpenedFromElem.onkeyup = this.OnChange;
		if (OpenedFromElem.captureEvents) 
			OpenedFromElem.captureEvents(event.KEYUP);

		this.Visible = true;		
		
		this.Opener = OpenedFromElem;
		
		// This is being called in WriteCal no need to call here because its wasted
		this.WriteCal();
		hideElement("SELECT");
		document.getElementById(this.DivId).style.display = "block";
		this.DivRect = MoveDivTo(this.DivId, this.Opener);
		gDivRect = this.DivRect;
	}
	this.OpenCal = OpenCal;
	function OnNextMonth() {
		if(!document.all)
			if(!this.Visible)
				return;
		if(this.Month == 12) {
			this.Month = 1;
			this.Year++;
		}
		else if(this.Month < 12) {
			this.Month++;
		}
		this.WriteCal();
	}
	this.OnNextMonth = OnNextMonth;
	
	function OnPrevMonth() {
		if(!document.all)
			if(!this.Visible)
				return;
			
		if(this.Month == 1) {
			this.Month = 12;
			this.Year--;
		}
		else if(this.Month > 1) {
			this.Month--;
		}
		this.WriteCal();
	}
	this.OnPrevMonth = OnPrevMonth;
	
	function OnSelect(selHash) {
		var SelDate = new Date(selHash);
		
		if(this.Opener != null && this.ArrivalId == this.Opener.id && document.getElementById(this.DepartureId).value.length > 0) {
			var DepDate = new Date(document.getElementById(this.DepartureId).value);
			if(DepDate == "Invalid Date") {
				//alert("Your departure date is invalid please try re-selecting a new departure date.");
				//return;	
			}
			
			if(SelDate.getTime() > DepDate.getTime()) {
				document.getElementById(this.DepartureId).value = "";
			}
		}
								
		if(this.Opener != null && this.DepartureId == this.Opener.id && document.getElementById(this.ArrivalId).value.length > 0) {
			var ArrDate = new Date(document.getElementById(this.ArrivalId).value);
			if(ArrDate == "Invalid Date") {
				//alert("Your arrival date is invalid please try re-selecting a new arrival date.");
				//return;
			}
			
			if(SelDate.getTime() < ArrDate.getTime()) {
				//alert("Sorry but your departure date can not come before your arrival date.");
				//return;
			}
		}
			
		this.Opener.value = selHash;
		document.getElementById(this.DivId).style.display = "none";
		this.Visible = false;
		showElement("SELECT");
		
		if(this.Opener != null && this.ArrivalId == this.Opener.id) {
			document.getElementById(this.DepartureId).focus();
		}
	}
	this.OnSelect = OnSelect;
	
	// MAY CHANGE FOR DIFFERENT CALENDAR TYPES
	// UI RELATED
	function SetDateHTML(N, Type, mon, Cell) {
		var SelHTML 	= "<a class='SelectedDates' href='javascript:void(0);' onclick='" + this.name + ".OnSelect'><b>" + N + "</b></a>";
		var EnableHTML 	= "<a class='EnabledDates' href='javascript:void(0);' onclick=\"" + this.name + ".OnSelect('" + mon + "/" + N + "/" + this.Year + "');\">" + N + "</a>";
		var HighHTML 	= "<span class='HighlightedDates'>" + N + "</span>";
		var InitHTML 	= N;
		
		if(Type == INITALIZED) {
			Cell.innerHTML = InitHTML;
		}
		
		if(Type & ENABLED && Type & INITALIZED) {
			Cell.className = "EnabledDates";
			Cell.innerHTML = EnableHTML;
		}
		else {
			Cell.className = "DisabledDates";
		}
		
		if(Type & SELECTED) {
			Cell.className = "SelectedDates";
			Cell.innerHTML = SelHTML;
		}
		
		if(Type & HIGHLIGHTED) {
			Cell.className = "HighlightedDates";
			Cell.innerHTML = HighHTML;	
		}
	}
	this.SetDateHTML = SetDateHTML;
	
	// MAY CHANGE FOR DIFFERENT CALENDAR TYPES
	// UI RELATED
	function WriteCal() {
		if(!document.all) 
			if(!this.Visible)
				return;
			
		var Div = document.getElementById(this.DivId);
		var Ref = this.Refresh();
		if(Ref == -1) {
			Div.innerHTML = CalPodHTML("The date you have entered has already passed.", "Error");
			return;	
		}
		
		if(Ref == -2) {
			Div.innerHTML = CalPodHTML("The date you have entered is not within an acceptable range.", "Error");
			return;	
		}
		
		if(this.Desc == null)
			Div.innerHTML = CalPodHTML("<table><tr><td valign='top'><table id='cal1' cellspacing='0' cellpadding='3'></table></td><td class='VerticalSpacer'></td><td valign='top'><table id='cal2' cellspacing='0' cellpadding='3'></table></td></tr></table>", "Main");
		else
			Div.innerHTML = CalPodHTML("<table class='cal_bdr'><tr><td valign='top'><table id='cal1' cellspacing='0' cellpadding='3'></table></td><td class='VerticalSpacer'></td><td valign='top'><table id='cal2' cellspacing='0' cellpadding='3'></td></tr></table></td></tr></table>" + this.Desc, "Main");			
			
		var Tbl = document.getElementById('cal1');
		var Tbl2 = document.getElementById('cal2');
		
		var Rw = Tbl.insertRow(0);
		Rw.style.width = "8px";
		Rw.style.height = "18px";
		var cell = Rw.insertCell(0);
		var Rw2 = Tbl2.insertRow(0);
		Rw2.style.width = "8px";
		Rw2.style.height = "18px";
		var cell2 = Rw2.insertCell(0);
		
		if(this.Range.startDate.getMonth() != (this.Month - 1) || this.Range.startDate.getFullYear() != this.Year) {
				cell.innerHTML = "<span style='cursor: pointer;'><img src='images/leftarrow.gif' onclick='"+this.name+".OnPrevMonth();' border='0'></span>"; 
		}
		
		cell.className = "PrevAnchor";
		cell2.className = "PrevAnchor";
		
		cell = Rw.insertCell(1); 
		
		cell.innerHTML = GetMonthName(this.Month) + " " + this.Year; 
		
		cell.colSpan = 5;
		cell.className = "MonthName";
		
		if(this.Month + 1 == 13) {
			this.Month = 0;
			this.Year++;
		}	
		
		cell2 = Rw2.insertCell(1); 
		cell2.innerHTML = GetMonthName(this.Month+1 > 12 ? 1 : this.Month+1) + " " + this.Year; 
		cell2.colSpan = 5;
		cell2.className = "MonthName";
		
		if(this.Month == 0) {
			this.Month = 12;
			this.Year--;
		}	
		
		cell2 = Rw2.insertCell(2); 
		if(this.Range.endDate.getMonth() != (this.Month) || this.Range.endDate.getFullYear() != this.Year) {
			var dat = this.Range.endDate.getFullYear();
			
		if(this.Month!=12)
			{
				cell2.innerHTML = "<span style='cursor: pointer;'><img src='images/rightarrow.gif' onclick='"+this.name+".OnNextMonth();' border='0'></span>";
		}
		}
		
		cell2.height = "18px;";
		cell2.className = "NextAnchor";
		
		Rw = Tbl.insertRow(1);
		cell = Rw.insertCell(0);
		cell.innerHTML = "S";
		cell.className = "WeekLetters";
		
		cell = Rw.insertCell(1);
		cell.innerHTML = "M";
		cell.className = "WeekLetters";
		
		cell = Rw.insertCell(2);
		cell.innerHTML = "T";
		cell.className = "WeekLetters";
		
		cell = Rw.insertCell(3);
		cell.innerHTML = "W";
		cell.className = "WeekLetters";
		
		cell = Rw.insertCell(4);
		cell.innerHTML = "T";
		cell.className = "WeekLetters";
		
		cell = Rw.insertCell(5);
		cell.innerHTML = "F";
		cell.className = "WeekLetters";
		
		cell = Rw.insertCell(6);
		cell.innerHTML = "S";
		cell.className = "WeekLetters";
		
		Rw2 = Tbl2.insertRow(1);
		cell2 = Rw2.insertCell(0);
		cell2.innerHTML = "S";
		cell2.className = "WeekLetters";
		
		cell2 = Rw2.insertCell(1);
		cell2.innerHTML = "M";
		cell2.className = "WeekLetters";
		
		cell2 = Rw2.insertCell(2);
		cell2.innerHTML = "T";
		cell2.className = "WeekLetters";
		
		cell2 = Rw2.insertCell(3);
		cell2.innerHTML = "W";
		cell2.className = "WeekLetters";
		
		cell2 = Rw2.insertCell(4);
		cell2.innerHTML = "T";
		cell2.className = "WeekLetters";
		
		cell2 = Rw2.insertCell(5);
		cell2.innerHTML = "F";
		cell2.className = "WeekLetters";
		
		cell2 = Rw2.insertCell(6);
		cell2.innerHTML = "S";
		cell2.className = "WeekLetters";
		
		rw = Tbl.insertRow(2); rw.insertCell(0); rw.insertCell(1); rw.insertCell(2); rw.insertCell(3); rw.insertCell(4); rw.insertCell(5); rw.insertCell(6);
		rw = Tbl.insertRow(3); rw.insertCell(0); rw.insertCell(1); rw.insertCell(2); rw.insertCell(3); rw.insertCell(4); rw.insertCell(5); rw.insertCell(6);
		rw = Tbl.insertRow(4); rw.insertCell(0); rw.insertCell(1); rw.insertCell(2); rw.insertCell(3); rw.insertCell(4); rw.insertCell(5); rw.insertCell(6);
		rw = Tbl.insertRow(5); rw.insertCell(0); rw.insertCell(1); rw.insertCell(2); rw.insertCell(3); rw.insertCell(4); rw.insertCell(5); rw.insertCell(6);
		rw = Tbl.insertRow(6); rw.insertCell(0); rw.insertCell(1); rw.insertCell(2); rw.insertCell(3); rw.insertCell(4); rw.insertCell(5); rw.insertCell(6);
		rw = Tbl.insertRow(7); rw.insertCell(0); rw.insertCell(1); rw.insertCell(2); rw.insertCell(3); rw.insertCell(4); rw.insertCell(5); rw.insertCell(6);
		
		rw2 = Tbl2.insertRow(2); rw2.insertCell(0); rw2.insertCell(1); rw2.insertCell(2); rw2.insertCell(3); rw2.insertCell(4); rw2.insertCell(5); rw2.insertCell(6);
		rw2 = Tbl2.insertRow(3); rw2.insertCell(0); rw2.insertCell(1); rw2.insertCell(2); rw2.insertCell(3); rw2.insertCell(4); rw2.insertCell(5); rw2.insertCell(6);
		rw2 = Tbl2.insertRow(4); rw2.insertCell(0); rw2.insertCell(1); rw2.insertCell(2); rw2.insertCell(3); rw2.insertCell(4); rw2.insertCell(5); rw2.insertCell(6);
		rw2 = Tbl2.insertRow(5); rw2.insertCell(0); rw2.insertCell(1); rw2.insertCell(2); rw2.insertCell(3); rw2.insertCell(4); rw2.insertCell(5); rw2.insertCell(6);
		rw2 = Tbl2.insertRow(6); rw2.insertCell(0); rw2.insertCell(1); rw2.insertCell(2); rw2.insertCell(3); rw2.insertCell(4); rw2.insertCell(5); rw2.insertCell(6);
		rw2 = Tbl2.insertRow(7); rw2.insertCell(0); rw2.insertCell(1); rw2.insertCell(2); rw2.insertCell(3); rw2.insertCell(4); rw2.insertCell(5); rw2.insertCell(6);
		
		var c = new Date(this.Month + "/01/" + this.Year);
		var Days = getDaysInMonth(c);
		var RowN = 2;
		
		for(var DiM=1; DiM <= Days; DiM++) {
			c.setDate(DiM);
			if(c.getDay() == 0 && RowN < 7)
				RowN++;
			var val = this.Range.Iterate('SEEK', c);
			
			this.SetDateHTML(DiM, val, this.Month, Tbl.rows[RowN].cells[c.getDay()]);
		}
		
		if(this.Month + 1 == 13) {
			this.Month = 0;
			this.Year++;
		}	
		
		c.setDate(c.getDate() + 1);
		Days = getDaysInMonth(c);
		RowN = 2;
		
		for(var DiM=1; DiM <= Days; DiM++) {
			c.setDate(DiM);
			if(c.getDay() == 0 && RowN < 7)
				RowN++;
			var val = this.Range.Iterate('SEEK', c);
			this.SetDateHTML(DiM, val, this.Month + 1, Tbl2.rows[RowN].cells[c.getDay()]);
		}
		
		if(this.Month == 0) {
			this.Month = 12;
			this.Year--;
		}	
		
	}
	this.WriteCal = WriteCal;
	
	// THIS FUNCTION ENABLES/DISABLES DATES
	// WILL CHANGE FOR DIFFERENT CALENDAR TYPES.
	// THE TYPE THAT IS SPECIFIED HERE IS A CALENDAR
	// LIKE WE HAVE ON THE MAIN WEB SITE
	function Refresh() {
		var ArrSel = null;
		var DepSel = null;
		
		if(this.DepartureId && document.getElementById(this.ArrivalId).value.length > 0)
			ArrSel = new Date(document.getElementById(this.ArrivalId).value);
		
		if(this.DepartureId && document.getElementById(this.DepartureId).value.length > 0)
			DepSel = new Date(document.getElementById(this.DepartureId).value);
		
		if(this.Range.isBeforeRange(ArrSel)) {
			return -1;	
		}
		if(this.Range.isAfterRange(ArrSel)) {
			return -2;
		}
		
		if(this.Range.isBeforeRange(DepSel)) {
			return -1;
		}
		if(this.Range.isAfterRange(DepSel)) {
			alert("Is after failed");
			return -2;	
		}
		
		if(this.Opener != null && this.ArrivalId == this.Opener.id) {
			if(DepSel == "Invalid Date" || DepSel == null) {
				// Enable everything
				this.Range.RangeSetFlag(this.Range.startDate, this.Range.startInc, this.Range.endDate, this.Range.endInc, INITALIZED | ENABLED);
			}
			else {
				// Enable all before the departure date
				this.Range.RangeSetFlag(this.Range.startDate, this.Range.startInc, this.Range.endDate, this.Range.endInc, INITALIZED | ENABLED);
				
			}	
		}
		
		if(this.Opener != null && this.DepartureId == this.Opener.id) {
			if(ArrSel == "Invalid Date" || ArrSel == null) {
				// Enable everything
				this.Range.RangeSetFlag(this.Range.startDate, this.Range.startInc, this.Range.endDate, this.Range.endInc, INITALIZED | ENABLED);
			}
			else {
				// Enable all after the arrival date
				this.Range.RangeSetFlag(ArrSel, false, this.Range.endDate, this.Range.endInc, INITALIZED | ENABLED);
				// Disable all before and including the arrival date.
				this.Range.RangeSetFlag(this.Range.startDate, this.Range.startInc, ArrSel, true, INITALIZED);
			}
		}

		if(isObject(ArrSel)) {
			this.Range.Iterate("SEEK", document.getElementById(this.ArrivalId).value);
			this.Range.SetFlag(INITALIZED | ENABLED | HIGHLIGHTED);
		}
		
		if(isObject(DepSel)) {
			this.Range.Iterate("SEEK", document.getElementById(this.DepartureId).value);
			this.Range.SetFlag(INITALIZED | ENABLED | HIGHLIGHTED);
		}
						
		return 0;
	}
	this.Refresh = Refresh;
	
	// Properties
	this.Refresh = Refresh;
	this.Range = dtRng;
	this.ArrivalId = arrId;
	this.DepartureId = depId;
	this.DivId = divId;
	this.DivRect = null;
	this.Month = dtRng.startDate.getMonth()+1;
	this.Year = dtRng.startDate.getFullYear();
	this.name = nm;
	this.Opener = null;
	this.WriteCal();
	this.Desc = null;
}

/* 
	This object is responsible for wrapping up all details of a rectangle
	Methods: 
		PtInRect(x, y): Takes x/y coordinates and returns true of false depeneding of if the element is visible and inside the rectangle.
		IsZero():		Obselete
		getElementRect:	Takes an id of an element on the page and creats a rect from its area on page.
*/
function Rect(eId) {
	this.Left = 0;
	this.Top = 0;
	this.Right = 0;
	this.Bottom = 0;
	this.Height = 0;
	this.Width = 0;
	this.sx = 0;
	this.sy = 0;
	
	function AlertRect() {
		alert("Left: " + this.Left + " Right: " + this.Right + " Top: " + this.Top + " Bottom: " + this.Bottom);
	}
	this.AlertRect = AlertRect;
	

	function PtInRect(x, y)	{
		// ACCOUNT FOR SCROLLING
		if(document.all) {
			// IE sucks donkey balls! can't use document.body.scrollTop for <!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>
			// which happens to be what we are using..... if you switch then you have to use the other.... here is the fix for IE's bug btw.... I HATE IE.
			this.sx = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft;
			this.sy = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
		}
		else {
			this.sx = pageXOffset;
			this.sy = pageYOffset;
		}
			
		if(this.Left <= x && x <= this.Right) {
			if(this.Top <= y + this.sy && y + this.sy <= this.Bottom) {
				return true;
			}	
		}
		return false;
	}
	this.PtInRect = PtInRect;
	
	function IsZero() {
		if(this.Left == 0 && this.Right == 0 && this.Top == 0 && this.Bottom == 0)
			return true;
		return false;	
	}
	this.IsZero = IsZero;
	
	function Union(elemId, recurse) {
		var rct = new Rect(elemId, recurse);
		if(rct.Left < this.Left) 
			this.Left = rct.Left;
		if(rct.Right > this.Right)
			this.Right = rct.Right;
		if(rct.Bottom > this.Bottom)
			this.Bottom = rct.Bottom;
		if(rct.Top < this.Top)
			this.Top = rct.Top;
	}
	this.Union = Union;
	
	function getElementRect(elemId) {
		var elm = document.getElementById(elemId);	
		var debug = document.getElementById('Debug');
		
		this.Left = getAbsX(elm);
		this.Width = getAbsW(elm);
		this.Top = getAbsY(elm);
		this.Height = getAbsH(elm);
		this.Top = this.Left + this.Width;
		this.Bottom = this.Top + this.Height;
	}
	this.getElementRect = getElementRect;
	
	if(isString(eId)) 
		this.getElementRect(eId);
}

function showProperties(prop) {
	var Elements = "";
	for (var propName in prop) {
		var value = "NOT WORKING";
		Elements += propName + " = " + value + "<br>";
	}
	document.write(Elements);
}
// This function takes 2 date values.  A starting Date for the range of the
// entire object to operate over and an ending date.  The Inclusive values
// determine if the date is to be included in the domain or not.
function DateRange(StartDate, InclusiveStart, EndDate, InclusiveEnd) {

	// A simple debug function for outputting the entire contents of the
	// domain to a page.
	function OutputDebugDates(DivId) {
		var Result = "";
		for(var i in this.DateArray) {
			Result += (i + " = " + this.DateArray[i] + "<br>");
		}
		document.getElementById(DivId).innerHTML = Result;
	}
	this.OutputDebugDates = OutputDebugDates;
	
	/* 	This function is used to iterate over the date range its usage is 
		similar to c fseek function.  The first parameter can be any of the 
		following:
			SEEK_SET	Moves the hash pointer to the start of the domain.
			NEXT		Moves the hash pointer forward 1 day in the domain.
			PREV		Moves the hash pointer backward 1 day in the domain.
			SEEK		Jumps to a date specified by the 'to' parameter.
			SEEK_END	Moves the hash pointer to the end of the domain.
		This function will return the flag for the particular date that it iterates
		over.  If the date is outside of the domain then null will be returned.
	*/
	
	function isAfterRange(Dt) {
		if(!isObject(Dt)) {
			return false;
		}
		if(this.endDate.getTime() < Dt.getTime())
			return true;
		return false; 	
	}
	this.isAfterRange = isAfterRange;
	
	function isBeforeRange(Dt) {
		if(!isObject(Dt)) {
			return false;
		}
		if(Dt.getTime() < this.startDate.getTime())
			return true;
		return false;	
	}
	this.isBeforeRange = isBeforeRange;
	
	function Iterate(how, to) {
		var dt = new Date(this.curHash);
		
		if(how == 'SEEK_SET') {
			this.curHash = MkHashKey(this.startDate.getFullYear(), this.startDate.getMonth()+1, this.startDate.getDate());
			return this.DateArray[this.curHash];
		}
		else if(how == 'NEXT') {
			dt.setDate(dt.getDate() + 1);
			this.curHash = MkHashKey(dt.getFullYear(), dt.getMonth()+1, dt.getDate());
			return this.DateArray[this.curHash];
		}	
		else if(how == 'PREV') {
			dt.setTime(dt.getTime() - 86400000);
			this.curHash = MkHashKey(dat.getFullYear(), dt.getMonth()+1, dt.getDate());
			return this.DateArray[this.curHash];
		}		
		else if(how == 'SEEK') {
			dt = new Date(to);
			this.curHash = MkHashKey(dt.getFullYear(), dt.getMonth()+1, dt.getDate());
			return this.DateArray[this.curHash];
		}		
		else if(how == 'SEEK_END') {
			this.curHash = MkHashKey(this.endDate.getFullYear(), this.endDate.getMonth()+1, this.endDate.getDate());
			return this.DateArray[this.curHash];
		}	
		else {
			alert("Error unknown iteration.");
		}
	}
	this.Iterate = Iterate;

	// This is a helper function that returns a hash key into the DateArray given 
	// a year, month, and day
	function MkHashKey(yr, mn, dy) {
		return (yr + "/" + mn + "/" + dy);
	}
	this.MkHashKey = MkHashKey;
	
	// Returns the flag at the current hash position.
	function GetFlag() {
		return this.DateArray[this.curHash];
	}
	this.GetFlag = GetFlag;
	
	function GetSubRange(sd, sinc, ed, einc) {
		var SubRange = new DateRange(sd, sinc, ed, einc);
		
		this.Iterate('SEEK', sd);
		do {
			SubRange.SetFlag(this.GetFlag());
			SubRange.Iterate('NEXT');
			
		} while(this.curHash != this.MkHashKey(ed.getFullYear(), ed.getMonth()+1, ed.getDate()) && this.Iterate('NEXT'));
		return SubRange;
	}
	this.GetSubRange = GetSubRange;
	
	// Sets an entire range of flags in the domain.  If the sd, ed parameters are outside
	// of the domain then the domain will be extended to included these dates as well.
	// The first 4 parameters are the same as the first 4 in the constructor and work
	// the same way.
	function RangeSetFlag(sd, incs, ed, ince, Flags) {
		if(!isObject(sd))
			alert("Starting date is not an object in function DateRange.SetRange.");
		if(!isObject(ed))
			alert("Ending date is not an object in function DateRange.SetRange.");
		if(!isBoolean(incs))
			alert("Inculsive start is not a boolean value in function DateRange.SetRange.");
		if(!isBoolean(ince))
			alert("Inclusive end is not a boolean value in function DateRange.SetRange.");
		if(sd == "Invalid Date") {
			alert("Invalid start date passed to RangeClrFlag");
			return;
		}
		if(ed == "Invalid Date") {
			alert("Invalid end date passed to RangeClrFlag");
			return;
		}	
		this.Iterate('SEEK', sd);
		
		if(incs)
			this.SetFlag(Flags);
		
		while(this.curHash != MkHashKey(ed.getFullYear(), ed.getMonth()+1, ed.getDate())) {
			this.Iterate('NEXT')
			this.SetFlag(Flags);
		}
		
		if(ince)
			this.SetFlag(Flags);
	}
	this.RangeSetFlag = RangeSetFlag;
	
	// Adds an entire range of flags in the domain to what is already existing in the domain.  
	// If the sd, ed parameters are outside
	// of the domain then the domain will be extended to included these dates as well.
	// The first 4 parameters are the same as the first 4 in the constructor and work
	// the same way.
	function RangeAddFlag(sd, incs, ed, ince, Flags) {
		if(!isObject(sd))
			alert("Starting date is not an object in function DateRange.AddRange.");
		if(!isObject(ed))
			alert("Ending date is not an object in function DateRange.AddRange.");
		if(!isBoolean(incs))
			alert("Inculsive start is not a boolean value in function DateRange.AddRange.");
		if(!isBoolean(ince))
			alert("Inclusive end is not a boolean value in function DateRange.AddRange.");
		if(sd == "Invalid Date") {
			alert("Invalid start date passed to RangeClrFlag");
			return;
		}
		if(ed == "Invalid Date") {
			alert("Invalid end date passed to RangeClrFlag");
			return;
		}	
		this.Iterate('SEEK', sd);
		
		if(incs)
			this.AddFlag(Flags);
		
		while(this.curHash != MkHashKey(ed.getFullYear(), ed.getMonth()+1, ed.getDate())) {
			this.Iterate('NEXT')
			this.AddFlag(Flags);
		}
		
		if(ince)
			this.AddFlag(Flags);
	}
	this.RangeAddFlag = RangeAddFlag;
	
	// Clears an entire range of flags in the domain (only clears the flags specified).  
	// If the sd, ed parameters are outside
	// of the domain then the domain will be extended to included these dates as well.
	// The first 4 parameters are the same as the first 4 in the constructor and work
	// the same way.
	function RangeClrFlag(sd, incs, ed, ince, Flags) {
		if(!isObject(sd))
			alert("Starting date is not an object in function DateRange.ClrRange.");
		if(!isObject(ed))
			alert("Ending date is not an object in function DateRange.ClrRange.");
		if(!isBoolean(incs))
			alert("Inculsive start is not a boolean value in function DateRange.ClrRange.");
		if(!isBoolean(ince))
			alert("Inclusive end is not a boolean value in function DateRange.ClrRange.");
		if(sd == "Invalid Date") {
			alert("Invalid start date passed to RangeClrFlag");
			return;
		}
		if(ed == "Invalid Date") {
			alert("Invalid end date passed to RangeClrFlag");
			return;
		}
		this.Iterate('SEEK', sd);
		
		if(incs)
			this.ClrFlag(Flags);
		
		while(this.curHash != MkHashKey(ed.getFullYear(), ed.getMonth()+1, ed.getDate())) {
			this.Iterate('NEXT')
			this.ClrFlag(Flags);
		}
		
		if(ince)
			this.ClrFlag(Flags);
	}
	this.RangeClrFlag = RangeClrFlag;
	
	function ClrFlag(Flags) {
		this.DateArray[this.curHash] ^= Flags;
	}
	this.ClrFlag = ClrFlag;
	
	function AddFlag(Flags) {
		this.DateArray[this.curHash] |= Flags;
	}
	this.AddFlag = AddFlag;
	
	// Sets the flag at the current hash position.
	function SetFlag(Flags) {
		this.DateArray[this.curHash] = Flags;
	}
	this.SetFlag = SetFlag;
	
	// PROPERTIES
        this.startDate = StartDate;
	this.startInc = InclusiveStart;
	this.endDate = EndDate;
	this.endInc = InclusiveEnd;
	this.DateArray = {};
	
	// Set the current hash value to the start of the domain.
	var Years=this.startDate.getFullYear();
	var Months=this.startDate.getMonth() + 1;
	var Days=1;
	this.curHash = MkHashKey(Years, Months, Days);
	
	// Construction.  Set everything in the domain to DISABLED
	while(Years < this.endDate.getFullYear()) {
		while(Months < 13) {
			var DaysInMonth = getDaysInMonth(new Date(Months + "/01/" + Years));
			while(Days <= DaysInMonth) {
				var Hash = Years + "/" + Months + "/" +  Days;
				this.DateArray[Hash] = INITALIZED;
				Days++;
			}
			Days = 1;
			Months++;
		}
		Months=1;
		Years++;
	}
	
	while(Months < this.endDate.getMonth() + 2) {
		var DaysInMonth = getDaysInMonth(new Date(Months + "/01/" + Years));
		while(Days <= DaysInMonth) {
			var Hash = Years + "/" + Months + "/" +  Days;
			this.DateArray[Hash] = INITALIZED;
			Days++;
		}
		Days = 1;
		Months++;
	}
	Months=1;
	Years++;
}

function getAbsX(elt) { return parseInt(elt.x) ? elt.x : getAbsPos(elt,"Left"); };
function getAbsY(elt) { return parseInt(elt.y) ? elt.y : getAbsPos(elt,"Top"); };
function getAbsW(elt) { return parseInt(elt.clientWidth) ? elt.clientWidth : elt["offsetWidth"]; };
function getAbsH(elt) { return parseInt(elt.clientHeight) ? elt.clientHeight : elt["offsetHeight"]; };

function getAbsPos(elt,which) {
	iPos = 0;
	while (elt != null) {
		iPos += elt["offset" + which];
		elt = elt.offsetParent;
	}
	return iPos;
}

function showElement(elmID) {
        var ie  = document.all;
        if(ie) {
	        	for(i = 0; i < document.all.tags( elmID ).length; i++) {
                        obj = document.all.tags(elmID)[i];
                        if(!obj || !obj.offsetParent) continue;
                        obj.style.visibility = '';
                }
        }
}

function hideElement(elmID) {
        var ie  = document.all;
        
        if(ie) {
                for(i = 0; i < document.all.tags( elmID ).length; i++) {
                        obj = document.all.tags(elmID)[i];
                        if(!obj || !obj.offsetParent) continue;
                        obj.style.visibility = 'hidden';
                }
        }
}

function MoveDivTo(SourceId, TargetElem, Alignment) {
	var S = document.getElementById(SourceId);
	var SLeft = getAbsX(S);
	var SWidth = getAbsW(S);
	var Left = getAbsX(TargetElem);
	var Width = getAbsW(TargetElem);
	var Top = getAbsY(TargetElem);
	var Height = getAbsH(TargetElem);
	var SH = getAbsH(S);
	var Rct = new Rect(null);
	
	var BrowserWidth = 0;
	if(document.all)
		BrowserWidth = document.body.clientWidth;
	else
		BrowserWidth = document.width;
		
	if((Left + Width + SWidth) > BrowserWidth) {
		S.style.left = Left - SWidth + "px";
		S.style.top = ((Top + Height) - (SH / 2)) + "px";	
		Rct.Left = Left - SWidth;
		Rct.Right = Left;
		Rct.Top = ((Top + Height) - (SH / 2));
		Rct.Bottom = ((Top + Height) + (SH / 2));
	}
	else {
		// Align to the right of the element
		S.style.left = (Left + Width) + "px";
		S.style.top = ((Top + Height) - (SH / 2)) + "px";
		Rct.Left = Left + Width;
		Rct.Right = Left + Width + getAbsW(S);
		Rct.Top = ((Top + Height) - (SH / 2));
		Rct.Bottom = ((Top + Height) + (SH / 2));
	}
	return Rct;
}

function CalMiniPodHTML(HTML) {
	var Result;
	
	Result  = "<table class='text' border='0' cellpadding='0' cellspacing='0' width='160'>\n";
	Result += "	<tbody>\n";
	Result += "		<tr>\n";
	Result += "			<td width='5'></td>\n";
	Result += "			<td align='center'>" + HTML + "</td>\n";
	Result += "			<td width='5'></td>\n";
	Result += "		</tr>\n";
	Result += "	</tbody>\n";
	Result += "</table>\n";
	
	return Result;
}


function CalPodHTML(HTML, Type) {
	var Result;
	
	Result = "<table id='outerDiv1' style='position: relative; z-index: 10000;' border='0' cellpadding='0' cellspacing='0'>\n";
	Result += "	<tbody><tr style='height: 0px;'>\n";
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td></td>\n";
		
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td></td>\n";
	
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td></td>\n";
		
	Result += "	</tr>\n";
	Result += "	<tr>\n";
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td style='' width: 13px;'></td>\n";
		
	Result += "		<td style=\"background-color: white;\" id='centerRow1'>\n";
	Result += "			<!-- End Pod Begin -->\n";
	Result += "			" + HTML + "\n";
	Result += "			<!-- Start Pod End -->\n";
	Result += "		</td>\n";
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td style=''></td>\n";
		
	Result += "	</tr>\n";
	Result += "	<tr style='height: 0px;'>\n";
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td style=''></td>\n";
	
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td style=''></td>\n";
		
	if(document.all)
		Result += "		<td></td>\n";
	else
		Result += "		<td style=''></td>\n";
		
	Result += "	</tr>\n";
	Result += "</tbody></table>\n";
	
	return Result;
}

//This function gets number of day in the month.  The somedate parameter can be either a date or a number*/
function getDaysInMonth(someDate) {
	var Leap=28;
	
	if(isObject(someDate)) {
		if(someDate.getFullYear() / 4 == parseInt(someDate.getFullYear() / 4))
			Leap = 29;
		var MonthArr = Array(31, Leap, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
		return MonthArr[someDate.getMonth()];
	}
	
	return -1
}

function GetMonthName(mon) {
	var MonthArr = Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
	
	if(isObject(mon)) {
		return MonthArr[mon.getMonth()];
	}
	else if(isNumber(mon) && mon >= 1 && mon <= 12) {
		return MonthArr[mon - 1];
	}
	
	return "Error";
}
/*isArray(a)
This function returns true if a is an array, meaning that it was produced by the Array constructor or by the [ ] array literal notation.
*/
function isArray(a) {
	return isObject(a) && a.constructor == Array;
}

/*isBoolean(a)
This function returns true if a is one of the Boolean values, true or false.
*/
function isBoolean(a) {
  	return typeof a == 'boolean';
}

/*isEmpty(a)
This function returns true if a is an object or array or function containing no enumerable members.
*/
function isEmpty(o) {
	if (isObject(o)) {
		for (var i in o) {
	            return false;
	    }
	}
	
	return true;
}

/*isFunction(a)
This function returns true if a is a function. Beware that some native functions in IE were made to look like objects instead of functions. This function does not detect that.Netscape is better behaved in this regard.
*/
function isFunction(a) {
  	return typeof a == 'function';
}

/*isNull(a)
This function returns true if a is the null value.
*/
function isNull(a) {
  	return typeof a == 'object' && !a;
}

/*isNumber(a)
This function returns true if a is a finite number. It returns false if a is NaN or Infinite. It also returns false if a is a string that could be converted to a number.
*/
function isNumber(a) {
  	return typeof a == 'number' && isFinite(a);
}

/*isObject(a)
This function returns true if a is an object, array, or function. It returns false if a is a string, number, Boolean, null, or undefined.
*/
function isObject(a) {
 	return (typeof a == 'object' && !!a) || isFunction(a);
}

/*isString(a)
This function returns true if a is a string.
*/
function isString(a) {
 	return typeof a == 'string';
}

/*isUndefined(a)
This function returns true if a is the undefined value. You can get the undefined value from an uninitialized variable or from an object's missing member.
*/
function isUndefined(a) {
 	return typeof a == 'undefined';
} 


