//' Software by DavidRegier.com. Unauthorized use of this code is prohibited

//////////////////////////////////////// Start Calendar Object Constructor: Cal ////////////////////////////////////////

function Calendar() {

	// Settings are customized on a per client basis
	this.Settings = new Array();
	this.Settings.futureMonthsAdmin = 24;
	this.Settings.futureMonthsPublic = 14;
	this.Settings.pastMonthsAdmin = 2;
	this.Settings.greeting = "Aloha";
	this.Settings.activateActualDates = 1;
	this.Settings.activateSpecials = 0;
	this.Settings.compressData = 1;


	// Nothing beyond this point is customized on a per client basis
	try {
		var test = CalData.length;
	}
	catch( Err ) {
		var eMsg = "ERROR: Data in cal-data.js is malformed (bad syntax). CalData (calendar data) array cannot be initialized.\n\n";
		for( member in Err ) eMsg += member + ": " + Err[ member ] + "\n";
		reportError( "Data Syntax Error", eMsg );
	}

	// Methods
	this.addReservation = addReservation;
	this.cancelEvt = cancelEvt;
	this.changeDate = changeDate;
	this.clear = clear;
	this.editReservation = editReservation;
	this.getCal = getCal;
	this.getDayOfWeek = getDayOfWeek;
	this.getEditResGUI = getEditResGUI;
	this.getBookingType = getBookingType;
	this.getMonthName = getMonthName;
	this.getNewResGUI = getNewResGUI;
	this.getNextSpan = getNextSpan;
	this.getNumDaysInMonth = getNumDaysInMonth;
	this.getNumNights = getNumNights;
	this.getReadAllWin = getReadAllWin;
	this.getValidDates = getValidDates;
	this.getWinWid = getWinWid;
	this.highlight = highlight;
	this.init = init;
	this.logOff = logOff;
	this.publish = publish;
	this.recordModifications = recordModifications;
	this.publishRightClick = publishRightClick;
	this.sendMail = sendMail;
	this.setActualDates = setActualDates;
	this.setDates = setDates;
	this.toHTM = toHTM;
	this.toText = toText;
	this.updateDisplay = updateDisplay;
	this.pollServer = pollServer;

	// Messages & tool tips
	this.Msg = new Array();
	this.Msg.actual = "\n\nNote that the actual dates must always be within the display date period.";
	this.Msg.backToBack = "Click to add a back-to-back; click background to reset";
	this.Msg.bkTypeConf = "a confirmed reservation";
	this.Msg.bkTypeNC = "I&#39;m not changing the booking type";
	this.Msg.bkTypePend = "a pending reservation";
	this.Msg.bkTypeSpc = "I&#39;m designating dates as available for discount";
	this.Msg.butAddOK = "Set new reservation";
	this.Msg.butCancel = "Close this pop-up window";
	this.Msg.butEditOK = "Edit this reservation";
	this.Msg.ckIn = "Click to set new check-in date";
	this.Msg.ckOut = "Click to set check-out date; click background to reset";
	this.Msg.confirmed = "Confirmed Reservation";
	this.Msg.open = "Available for check-in";
	this.Msg.del = "I&#39;m permanently deleting this reservation";
	this.Msg.dtVis = "Check-in/out dates that will show on calendar";
	this.Msg.edit = "Click to edit; right-click for read-only info";
	this.Msg.client = "Name of Client";
	this.Msg.helpCache = "Understanding cache & why it can cause problems";
	this.Msg.logOff = "All Finished? Log-off to end your session";
	this.Msg.noEdit = "No changes were recorded because you did not modify any information";
	this.Msg.notes = "Notes or comments (if any)";
	this.Msg.pending = "Pending Reservation (on hold)";
	this.Msg.pf = "Load printer-friendly version of this page";
	this.Msg.publish = "Save your new calendar data to the web";
	this.Msg.reset = "Click a check-out date; click background to reset";
	this.Msg.sendMail = "Send e-mail to selected Administrator(s)";
	this.Msg.special = "Dates available for discount";
	this.Msg.today = "Today";
	this.Msg.write = "Writing calendar, please wait...";

	// Object variables
	// Declare Hashtable for each property
	this.CarryBookingForward = new Array();

	this.Span = null;
	this.SpanOld = null;
	this.SpanIn = null;
	this.SpanOut = null;
	this.nextMon;
	this.nextYr;
	this.userWithWritePrivileges = ( GetCookie( "userWithWritePrivileges" ) );
	if( this.userWithWritePrivileges ) {
		this.userWithWritePrivileges = this.userWithWritePrivileges.replace( /_/, " " );
		DeleteCookie( "userHasReadAllPrivileges" );
	}

	this.userHasReadAllPrivileges = 0;
	if( qStr.getVal( "pw" ) == rapw || GetCookie( "userHasReadAllPrivileges" ) ) {
		SetCookie( "userHasReadAllPrivileges", "yes" );
		DeleteCookie( this.userWithWritePrivileges );
		this.userHasReadAllPrivileges = 1;
	}

	this.publicUser = !this.userWithWritePrivileges && !this.userHasReadAllPrivileges;

	this.calPending = 0;
	this.calSpecial = 0;

	// pollServer variables
	this.Request = null;
	this.timer = 0;
	this.logFile = "last-administrator.js";
	this.dataFile = "cal-data.js";
	this.downloadedData = 0;

	this.readAllURL = document.location.href.split( "?" )[ 0 ] + "?pw=" + rapw;


	//------------------------------ Method: Cal ------------------------------
	// Use AJAX to poll server for (1) file containing info about active administrator & (2) file containing calendar data

	function pollServer() {

		var debug = 0;

		// W3C
		if( window.XMLHttpRequest ) {
			try { this.Request = new XMLHttpRequest(); }
			catch( Err ) { this.Request = null; }
		}

		// IE 6-
		else if( window.ActiveXObject ) {
			try { this.Request = new ActiveXObject( "Msxml2.XMLHTTP" ); }
			catch( Err ) {
				try { this.Request = new ActiveXObject( "Microsoft.XMLHTTP" ); }
				catch( Err ) { this.Request = null; }
			}
		}

		clearTimeout( Cal.timer );

		if( this.Request ) {

			// User w/ Write Privileges so get last-administrator.js, but only after we've downloaded cal-data.js once
			if( this.userWithWritePrivileges && this.downloadedData ) {

				this.Request.onreadystatechange = function() {
					if( Cal.Request.readyState == 4 ) {
						if( Cal.Request.status == 200 ) {
							eval( Cal.Request.responseText );
							var admin_user = admin_user.replace( /_/, " " );
							if( admin_user && Cal.userWithWritePrivileges != admin_user ) {
								DeleteCookie ( Cal.userWithWritePrivileges );
								alert( "Sorry but " + admin_user + " has just forced a log-in and is now the Administrator! In order to protect the integrity of our data, our calendar software does not allow concurrent administrators (two or more users editing the same data at the same time). Please contact " + admin_user.split( " " )[ 0 ] + " if you have any questions.\n\n==> You will now be logged-off as Administrator." );
								document.location.replace( fileName + "?logoff=yes&forcedOut=yes" );
							}
							if( debug ) self.status = Cal.logFile + " retrieved " + new Date().toLocaleString() + "; admin_user=" + admin_user;
						}
						else {
							if( debug ) alert( "Cal.pollServer() preloader encountered an error retrieving " + Cal.logFile + ":\n Status: " + Cal.Request.status + "\n StatusText: " + Cal.Request.statusText );
						}

						Cal.timer = setTimeout( "Cal.pollServer();", 5000 );

					}
				}
				this.Request.open( "GET", Cal.logFile + "?" + Math.random() );
				this.Request.send( null );

			}
			else { // Public or Read-All User so get cal-data.js
				this.downloadedData = 1;

				this.Request.onreadystatechange = function() {
					if( Cal.Request.readyState == 4 ) {
						if( Cal.Request.status == 200 ) {
							var CalDataInitial = CalData;
							eval( Cal.Request.responseText );
							var CalDataFinal = CalData;
							if( CalDataInitial.toString() != CalDataFinal.toString() ) {
								document.getElementById( "CalID" ).innerHTML = Cal.getCal();
								Cal.init();
							}
							if( debug ) self.status = Cal.dataFile + " retrieved " + new Date().toLocaleString();
						}
						else {
							if( debug ) alert( "Cal.pollServer() preloader encountered an error retrieving " + Cal.dataFile + ":\n Status: " + Cal.Request.status + "\n StatusText: " + Cal.Request.statusText );
						}

						Cal.timer = setTimeout( "Cal.pollServer();", 5000 );

					}
				}
				this.Request.open( "GET", Cal.dataFile + "?" + Math.random() );
				this.Request.send( null );

			}

		}
		// Browser cannot make http request
		else if( debug )
			self.status = "Browser does not support the HttpRequest Request Protocol";

	}

	//------------------------------ Method: Cal ------------------------------
	// Called when user clicks OK in Edit-Reservation pop-up GUI. This method writes new data to hidden textbox which may ultimately be publshed to web as a js data file.

	function editReservation( Form ) {

		// sub reset
		function subGetDateOpenTags( dates ) {

			var Dates = dates.split( " " );
			for( var j in Dates )
				Dates[ j ] = "<span onClick='Cal.setDates( this, event );' onMouseOver='if( window.Cal ) return Cal.highlight( this, 1 );' onMouseOut='if( window.Cal ) return Cal.highlight( this, 0 );' class='calOpen'>" + Dates[ j ] + "</span>";
			return Dates.join( " " );

		}

		var propNum = parseInt( Form.Property_Number.value );
		var bookNum = parseInt( Form.Booking_Number.value ) + 1;

		var propName = CalData[ propNum - 1 ][ 0 ];
		var BookingToEdit  = CalData[ propNum - 1 ][ bookNum ];

		var delBooking = ( Form.delBooking.checked ), editBooking = !delBooking;

		var existingBookNum = CalData[ propNum - 1 ][ bookNum ][ 1 ], newBookNum = -1;
		for( var i = 0; i < Form.BookType.length; i++ ) {
			if( Form.BookType[ i ].checked ) { newBookNum = parseInt( Form.BookType[ i ].value ); break; }
		}
		if( newBookNum == 0 ) newBookNum = existingBookNum;

		var Now = new Date();

		var CkInArr = this.getValidDates( Form.Checkin_Date, "Checkin" );
		if( CkInArr == null ) return false;

		var CkOutArr = this.getValidDates( Form.Checkout_Date, "Checkout" );
		if( CkOutArr == null ) return false;

		// Store dates as 3-member int arrays as returned from getValidDates
		var CkInDate = new Date( CkInArr[ 2 ] + 2000, CkInArr[ 0 ] - 1, CkInArr[ 1 ] );
		var newCkInDate = CkInDate.getTime();
		var existingCkInDate = new Date( CalData[ propNum - 1 ][ bookNum ][ 0 ][ 2 ] + 2000, CalData[ propNum - 1 ][ bookNum ][ 0 ][ 0 ] - 1, CalData[ propNum - 1 ][ bookNum ][ 0 ][ 1 ] ).getTime();

		var CkOutDate = new Date( CkOutArr[ 2 ] + 2000, CkOutArr[ 0 ] - 1, CkOutArr[ 1 ] );
		var newCkOutDate = CkOutDate.getTime();
		var existingCkOutDate = new Date( CalData[ propNum - 1 ][ bookNum ][ 0 ][ 5 ] + 2000, CalData[ propNum - 1 ][ bookNum ][ 0 ][ 3 ] - 1, CalData[ propNum - 1 ][ bookNum ][ 0 ][ 4 ] ).getTime();

		if( newCkInDate == newCkOutDate ) {
			alert( "Check-in & Check-out dates are the same date." );
			Form.Checkin_Date.focus();
			return false;
		}
		else if( newCkInDate > newCkOutDate ) {
			alert( "Check-in date is after the Check-out date. Sorry but this is just not possible on planet earth!" );
			Form.Checkout_Date.focus();
			return false;
		}

		var ckInActualOffset = 0, ckOutActualOffset = 0;

		// Read actual Check-in/out date offsets
		if( this.Settings.activateActualDates ) {

			var ActualDates = this.setActualDates( Form, newCkInDate, newCkOutDate );
			if( ActualDates ) {
				ckInActualOffset  = ActualDates[ 0 ];
				ckOutActualOffset = ActualDates[ 1 ];
			}
			else return false;
		}

		var nonDisplayDateEdit = ( !delBooking && Form.Checkin_Date.value == Form.Checkin_Date.defaultValue && Form.Checkout_Date.value == Form.Checkout_Date.defaultValue );
		var displayDateEdit = ( !delBooking && ( Form.Checkin_Date.value != Form.Checkin_Date.defaultValue || Form.Checkout_Date.value != Form.Checkout_Date.defaultValue ) );

		var br = ( this.Settings.compressData ) ? "" : "\n";
		var newCalData = "";

		newCalData += "CalData=[" + br + br;

		///////////////////////// Update cal-data.js /////////////////////////

		var delBookingsEndingBeforeMS = new Date( Now.getFullYear(), Now.getMonth() - this.Settings.pastMonthsAdmin, 1 ).getTime();

		// Loop thru each property in CalData
		outer:
		for( var j = 0; j < CalData.length - 1; j++ ) {

			newCalData +=  "[\"" + CalData[ j ][ 0 ] + "\",";
			var ExistingDates = CalData[ j ].slice( 1 );

			// Loop thru each individual existing booking of this property
			for( var k = 0; k < ExistingDates.length; k++ ) {

				var endDateMS = new Date( ExistingDates[ k ][ 0 ][ 5 ] + 2000, ExistingDates[ k ][ 0 ][ 3 ] - 1, ExistingDates[ k ][ 0 ][ 4 ] ).getTime();

				var existingCalData = ( endDateMS >= delBookingsEndingBeforeMS ) ? "[[" + ExistingDates[ k ][ 0 ][ 0 ] + "," + ExistingDates[ k ][ 0 ][ 1 ] + "," + ExistingDates[ k ][ 0 ][ 2 ] + "," + ExistingDates[ k ][ 0 ][ 3 ] + "," + ExistingDates[ k ][ 0 ][ 4 ] + "," + ExistingDates[ k ][ 0 ][ 5 ] + "," + ExistingDates[ k ][ 0 ][ 6 ] + "," + ExistingDates[ k ][ 0 ][ 7 ] + "]," + ExistingDates[ k ][ 1 ] + ",\"" + ExistingDates[ k ][ 2 ] + "\"," + ExistingDates[ k ][ 3 ] + ",\"" + ExistingDates[ k ][ 4 ] + "\",\"" + ExistingDates[ k ][ 5 ] + "\"," + ExistingDates[ k ][ 6 ] + "]," : "";

				// Found the property
				if( propName == CalData[ j ][ 0 ] ) {

					// This booking is NOT the one to be deleted/edited so keep it's data unless it's expired
					if( BookingToEdit != ExistingDates[ k ] )
						newCalData += existingCalData;

					else { // This is the booking to be deleted/edited

						var guest = Form.Client.value;
						guest = guest.toHTM();

						var notes = Form.Notes.value;
						notes = notes.toHTM();

						// Prepare data to add-back or delete booking
						var thisBooking = "[[" + CkInArr[ 0 ] + "," + CkInArr[ 1 ] + "," + CkInArr[ 2 ] + "," + CkOutArr[ 0 ] + "," + CkOutArr[ 1 ] + "," + CkOutArr[ 2 ] + "," + ckInActualOffset + "," + ckOutActualOffset + "]," + newBookNum + ",\"" + this.userWithWritePrivileges + "\"," + Now.getTime() + ",\"" + guest + "\",\"" + notes + "\"," + ExistingDates[ k ][ 6 ] + "]";

						// Edit booking (not delete)
						if( editBooking ) {

							var begDateMS = newCkInDate;
							var endDateMS = newCkOutDate;
							var dayMS = 86400000;

							var nDaysCheckInMonth = this.getNumDaysInMonth( CkInArr[ 0 ], CkInArr[ 2 ] + 2000 );
							var nDaysCheckOutMonth = this.getNumDaysInMonth( CkOutArr[ 0 ], CkOutArr[ 2 ] + 2000 );

							// User attempting to set non-existant check-in/out dates (9/31, 2/30)
							if( CkInArr[ 1 ] > nDaysCheckInMonth ) {
								alert( "Bad Dates: You are attempting to change the check-in date to " + CkInArr[ 0 ] + "/" + CkInArr[ 1 ] + " but there are only " + nDaysCheckInMonth + " days that month" );
								return false;
							}
							else if( CkOutArr[ 1 ] > nDaysCheckOutMonth ) {
								alert( "Bad Dates: You are attempting to change the check-out date to " + CkOutArr[ 0 ] + "/" + CkOutArr[ 1 ] + " but there are only " + nDaysCheckOutMonth + " days that month" );
								return false;
							}

							// Now step thru all ExistingDates to make sure thisRequestedDay does not fall w/i an existing booking
							for( var i = 0; i < ExistingDates.length; i++ ) {

								// Compare BookingToEdit only with other existing bookings
								if( BookingToEdit != ExistingDates[ i ] ) {

									var ExistingCheckIn =  new Date( ExistingDates[ i ][ 0 ][ 2 ] + 2000, ExistingDates[ i ][ 0 ][ 0 ] - 1, ExistingDates[ i ][ 0 ][ 1 ] );
									var existingCheckInMS = ExistingCheckIn.getTime();
									var ExistingCheckOut = new Date( ExistingDates[ i ][ 0 ][ 5 ] + 2000, ExistingDates[ i ][ 0 ][ 3 ] - 1, ExistingDates[ i ][ 0 ][ 4 ] );
									var existingCheckOutMS = ExistingCheckOut.getTime();

									// Step thru each requested booking day of this newly edited booking one day at a time
									for( var thisRequestedDay = begDateMS; thisRequestedDay < endDateMS; thisRequestedDay += dayMS ) {

										// Got a conflict so return false and exit now
										if( thisRequestedDay >= existingCheckInMS && thisRequestedDay < existingCheckOutMS ) {

											alert( "Conflicting Dates: Your requested booking from " + Form.Checkin_Date.value + " to " + Form.Checkout_Date.value + " conflicts with an existing booking from " + ExistingDates[ i ][ 0 ][ 0 ] + "/" + ExistingDates[ i ][ 0 ][ 1 ] + "/" + ExistingDates[ i ][ 0 ][ 2 ] + " to " + ExistingDates[ i ][ 0 ][ 3 ] + "/" + ExistingDates[ i ][ 0 ][ 4 ] + "/" + ExistingDates[ i ][ 0 ][ 5 ] + "." );
											return false;
										}
									}
								}
							}

							newCalData += thisBooking + ",";

							// new data but w/ old last-updated date & old administrator allows for comparision
							var newDataSet = "[[" + CkInArr[ 0 ] + "," + CkInArr[ 1 ] + "," + CkInArr[ 2 ] + "," + CkOutArr[ 0 ] + "," + CkOutArr[ 1 ] + "," + CkOutArr[ 2 ] + "," + ckInActualOffset + "," + ckOutActualOffset + "]," + newBookNum + ",\"" + ExistingDates[ k ][ 2 ]  + "\"," + ExistingDates[ k ][ 3 ] + ",\"" + guest + "\",\"" + notes + "\"," + ExistingDates[ k ][ 6 ] + "],";

							if( newDataSet == existingCalData ) {
								alert( this.Msg.noEdit );
								return false;
							}
						}
					}

				} // End found property

				else // Other property, so just maintain existing bookings
					newCalData += existingCalData;

			} // End Loop thru each individual existing booking of this property

			newCalData = newCalData.replace( /,$/, "" );
			newCalData += "]," + br + br;

		} // End Loop thru each property in CalData
		newCalData += "[\"" + this.userWithWritePrivileges + "\"," + Now.getTime() + "]" + br + br;
		newCalData += "];";

		///////////////////////// Sort Bookings So They Are In Ascending Order /////////////////////////

		// New on 8/9/07: User can edit start & end dates of a booking and jump over existing booking(s). This causes a problem because booking will be continue to be stored in array at the original location and is now out of sequence. Note that order is naturally maintained unless user jumps over booking(s).

		if( displayDateEdit ) {

			function subSortAscNum( a, b ) {
				return a[ 7 ]<b[ 7 ]?-1: a[ 7 ]>b[ 7 ]?1: a[ 7 ]==b[ 7 ]? 7 : a[ 7 ]<b[ 7 ]?-1: 1;
			}

			// Initialize new CalData array into memory
			eval( newCalData );
			newCalData = "CalData=[" + br + br;

			// Loop thru each property in new CalData
			for( var j = 0; j < CalData.length - 1; j++ ) {

				var ExistingDates = CalData[ j ].slice( 1 );

				// Loop thru each booking of this property
				for( var k = 0; k < ExistingDates.length; k++ ) {

					// Create this bookings start-date time in MS and temporarily tack onto to end of booking as member 7
					var startDateMS = new Date( ExistingDates[ k ][ 0 ][ 2 ] + 2000, ExistingDates[ k ][ 0 ][ 0 ] - 1, ExistingDates[ k ][ 0 ][ 1 ] ).getTime();
					ExistingDates[ k ][ 7 ] = startDateMS;
				}

				// Sort Bookings on startDateMS
				ExistingDates.sort( subSortAscNum );

				// Now begin rebuilding properly sorted newCalData as a string
				newCalData +=  "[\"" + CalData[ j ][ 0 ] + "\",";
				for( var k = 0; k < ExistingDates.length; k++ ) {

					var existingCalData = "[[" + ExistingDates[ k ][ 0 ][ 0 ] + "," + ExistingDates[ k ][ 0 ][ 1 ] + "," + ExistingDates[ k ][ 0 ][ 2 ] + "," + ExistingDates[ k ][ 0 ][ 3 ] + "," + ExistingDates[ k ][ 0 ][ 4 ] + "," + ExistingDates[ k ][ 0 ][ 5 ] + "," + ExistingDates[ k ][ 0 ][ 6 ] + "," + ExistingDates[ k ][ 0 ][ 7 ] + "]," + ExistingDates[ k ][ 1 ] + ",\"" + ExistingDates[ k ][ 2 ] + "\"," + ExistingDates[ k ][ 3 ] + ",\"" + ExistingDates[ k ][ 4 ] + "\",\"" + ExistingDates[ k ][ 5 ] + "\"," + ExistingDates[ k ][ 6 ] + "],";
					newCalData += existingCalData;
				}
				newCalData = newCalData.replace( /,$/, "" );
				newCalData += "]," + br + br;
			}
			newCalData += "[\"" + this.userWithWritePrivileges + "\"," + Now.getTime() + "]" + br + br;
			newCalData += "];";
		}


		// Write new data to textarea
		var Form = document.AspForm;
		Form.EditedJS.value = newCalData;


		///////////////////////// Update the Calendar Display /////////////////////////


		// Deleting or modifying (any edit but dates) booking using range
		if( delBooking || nonDisplayDateEdit ) {

			var Spans = document.getElementsByTagName( "span" );

			// Loop thru all spans on entire page
			for( var i = 0; i < Spans.length; i++ ) {

				// Found a reservation type span
				if( Spans[ i ].className == "calBooked" || Spans[ i ].className == "calPending" || Spans[ i ].className == "calSpecial" ) {

					// Read propNum, month and year stored in TD.id
					var Td = Spans[ i ].parentNode;
					var PropData = Td.id.split( "_" );
					for( var k in PropData ) PropData[ k ] = parseInt( PropData[ k ] );

					var spanNum = PropData[ 0 ];
					var spanMon = PropData[ 1 ];
					var spanYr  = PropData[ 2 ];
					var DaysOfSpan = Spans[ i ].innerHTML.split( " " );
					var spanStartDay = DaysOfSpan[ 0 ];
					var spanDay = parseInt( spanStartDay.replace( /^0/, "" ) );

					if( propNum == spanNum ) {

						var firstDayOfSpan = new Date( spanYr + 2000, spanMon - 1, spanDay ).getTime();

						// Found one of the span tags that show this booking, there may be more than 1 since bookings can span multiple TDs
						if( firstDayOfSpan >= existingCkInDate && firstDayOfSpan < existingCkOutDate ) {
							// Read existing booking class which is used if user not changing status
							var existingBookClass = "";
							switch( existingBookNum ) {
								case 1: existingBookClass = "calBooked"; break;
								case 2: existingBookClass = "calPending"; break;
								case 3: existingBookClass = "calSpecial"; break;
								default: alert( "Switch/Case Error at Cal.editReservation: switch( existingBookNum )" );
							}

							// Read new booking class
							var newClass = "";
							switch( newBookNum ) {
								case 0: newClass = existingBookClass; break;
								case 1: newClass = "calBooked"; break;
								case 2: newClass = "calPending"; break;
								case 3: newClass = "calSpecial"; break;
								default: alert( "Switch/Case Error at Cal.editReservation: switch( newBookNum )" );
							}

							var spanOn = "<span onClick='if( window.Cal ) Cal.getEditResGUI( this, event );' oncontextmenu='if( window.Cal ) { return Cal.getReadAllWin( this, event ); }' onMouseover='if( window.Cal ) { this.title = ( ( Cal.SpanOld ) ? Cal.Msg.backToBack : Cal.Msg.edit ); this.style.cursor = \"pointer\"; return true; }' class='" + newClass + "'>", spanOff = "</span>";

							if( document.createRange ) { // W3C

								var Range = document.createRange();
								Range.selectNode( Spans[ i ] );
								var dates = ( delBooking ) ? subGetDateOpenTags( Range.toString() ) : spanOn + Range.toString() + spanOff;
								var frag = Range.createContextualFragment( dates );
								Td.replaceChild( frag, Spans[ i ] );

							}
							else { // IE
								var htm = ( delBooking ) ? subGetDateOpenTags( Spans[ i ].innerHTML ) : spanOn + Spans[ i ].innerHTML + spanOff;
								Spans[ i ].outerHTML = htm;
							}

						}
					}
				}
			}

			// Deflate serialized data and initialize into memory
			eval( newCalData );
			document.getElementById( "calLastUpdateUserID" ).innerHTML = CalData[ CalData.length - 1 ][ 0 ];
			document.getElementById( "calLastUpdateTimeID" ).innerHTML = new Date( CalData[ CalData.length - 1 ][ 1 ] ).toLocaleString();
			DW.removeWin();
			return false;

		}

		// Changing dates of existing booking so redraw entire calendar
		else {
			eval( newCalData );
			document.getElementById( "CalID" ).innerHTML = Cal.getCal();
			DW.removeWin();
			Cal.init();
			return false;
		}


	}

	//------------------------------ Method: Cal ------------------------------
	// This method launches Edit-Reservation pop-up GUI

	function getEditResGUI( Span, evt ) {

		var launchEditWin = ( this.SpanOld == null );

		if( launchEditWin ) {

			// Read property data stored in parent td tag. Note that booking may have begun before this month
			var Td = Span.parentNode;
			var PropData = Td.id.split( "_" );
			for( var i in PropData ) PropData[ i ] = parseInt( PropData[ i ] );

			var propName = Td.previousSibling.firstChild.innerHTML;
			var propNum = PropData[ 0 ];
			var monthClicked = PropData[ 1 ];
			var dayInClicked = parseInt( Span.innerHTML.split( " " )[ 0 ].replace( /^0/, "" ) );
			var yrClicked = PropData[ 2 ];

			var inDateClicked = new Date( yrClicked + 2000, monthClicked - 1, dayInClicked ).getTime();
			var monIn, dayIn, yrIn, CkInDate, monOut, dayOut, yrOut, CkOutDate, bookType = 0, lastEditor, lastEditTime, bookingNum, guest = "", notes = "", CkInDateActual, CkOutDateActual;

			// Scan the data & find this booking
			outer:
			for( var i = 0; i < CalData.length - 1; i++ ) {

				// Found the right property
				if( CalData[ i ][ 0 ] == propName ) {

					var Bookings = CalData[ i ].slice( 1 );
					for( var k = 0; k < Bookings.length; k++ ) {

						var firstDayOfBooking = new Date( Bookings[ k ][ 0 ][ 2 ] + 2000, Bookings[ k ][ 0 ][ 0 ] - 1, Bookings[ k ][ 0 ][ 1 ] ).getTime();
						var lastDayOfBooking  = new Date( Bookings[ k ][ 0 ][ 5 ] + 2000, Bookings[ k ][ 0 ][ 3 ] - 1, Bookings[ k ][ 0 ][ 4 ] ).getTime();

						if( inDateClicked >= firstDayOfBooking && inDateClicked < lastDayOfBooking ) {

							monIn    = Bookings[ k ][ 0 ][ 0 ];
							dayIn    = Bookings[ k ][ 0 ][ 1 ];
							yrIn     = Bookings[ k ][ 0 ][ 2 ];
							CkInDate = new Date( yrIn + 2000, monIn - 1, dayIn );

							monOut    = Bookings[ k ][ 0 ][ 3 ];
							dayOut    = Bookings[ k ][ 0 ][ 4 ];
							yrOut     = Bookings[ k ][ 0 ][ 5 ];
							CkOutDate = new Date( yrOut + 2000, monOut - 1, dayOut );

							if( this.Settings.activateActualDates ) {
								CkInDateActual = new Date( yrIn + 2000, monIn - 1, dayIn + Bookings[ k ][ 0 ][ 6 ] );
								CkOutDateActual = new Date( yrOut + 2000, monOut - 1, dayOut - Bookings[ k ][ 0 ][ 7 ] );
							}

							bookType     = Bookings[ k ][ 1 ];
							lastEditor   = Bookings[ k ][ 2 ];
							lastEditTime = Bookings[ k ][ 3 ];
							guest = Bookings[ k ][ 4 ];
							notes = Bookings[ k ][ 5 ].toText();

							bookingNum = k;

							break outer;

						}
					}
				}
			}

			var nNights = this.getNumNights( CkInDate, CkOutDate );

			var dwTitle = "";

			var gui =

			"<form name='editRes' style='margin:0px;' onSubmit='return Cal.editReservation( this );'>" +
				"<table align='center' border='0' cellspacing='0' cellpadding='0'>" +
					"<tr>" +
						"<td>" +
							"<table align='center' border='0' cellspacing='0' cellpadding='0' class='calPopUps'>" +

								// Read-only dates & nNights
								"<tr>" +
									"<td align='center' colspan='2' style='padding:4px 0px 4px 0px; white-space:nowrap;'>" +
										 "Display Dates: " + this.getDayOfWeek( CkInDate.getDay(), 3 ) + " " + this.getMonthName( monIn, 0 ) + " " + dayIn + ", " + ( ( yrIn < 10 ) ? "0" + yrIn : yrIn ) + " to " + this.getDayOfWeek( CkOutDate.getDay(), 3 ) + " " + this.getMonthName( monOut, 0 ) + " " + dayOut + ", " + ( ( yrOut < 10 ) ? "0" + yrOut : yrOut ) + ";&nbsp; " + nNights + " nights" +

										 "<div class='calLastEditedBy'>Last modified by " + lastEditor + " on " + ( new Date( lastEditTime ).toLocaleString() ) + "</div>" +
									"</td>" +
								"</tr>" +

								// Delete Res
								"<tr>" +
									"<td align='left' colspan='2' style='padding:8px 0px 4px 0px; white-space:nowrap;'>" +
										 "<input type='checkbox' name='delBooking' title='" + this.Msg.del + "' /> I'd like to Delete this Reservation" +
									"</td>" +
								"</tr>" +

								// Change booking status
								"<tr>" +
									"<td align='left' colspan='2' style='padding:0px 0px 0px 0px; white-space:nowrap;'>" +
										"<div style='margin:6px 0px 2px 0px;'>I'd like to change the booking type to: </div>";

											var rbBooked = "&nbsp; <input type='radio' name='BookType' value='1' title='I&#39;m changing to " + this.Msg.bkTypeConf + "' />Confirmed; &nbsp;";

											var rbPending = "&nbsp; <input type='radio' name='BookType' value='2' title='I&#39;m changing to " + this.Msg.bkTypePend + "' />Pending; &nbsp;";

											var rbNoChange = "&nbsp; <input type='radio' name='BookType' value='0' checked title='" + this.Msg.bkTypeNC + "' />No change; &nbsp;";

											var rbSpecial = ( this.Settings.activateSpecials ) ? "&nbsp; <input type='radio' name='BookType' value='3' title='" + this.Msg.bkTypeSpc + "' />Special; &nbsp;" : "";

											switch( bookType ) {

												case 1:
													gui += rbPending + rbSpecial;
													dwTitle = Cal.getBookingType( 1 );
													break;

												case 2:
													gui += rbBooked + rbSpecial;
													dwTitle = Cal.getBookingType( 2 );
													break;

												case 3:
													gui += rbBooked + rbPending;
													dwTitle = Cal.getBookingType( 3 );
													break;

												default:
													alert( "Switch/Case Error at Cal.getEditResGUI while writing BookType radio buttons" );

											}

										gui += rbNoChange +
									"</td>" +
								"</tr>" +

								// Check-in to Check-out Dates
								"<tr>" +
									"<td style='padding:12px 4px 0px 4px; white-space:nowrap;'>" +
										"Display Dates" +
									"</td>" +
									"<td style='padding:12px 4px 0px 4px; white-space:nowrap;'>" +
										"<input type='text' name='Checkin_Date' id='Checkin_Date' onBlur='return Cal.changeDate( this, \"Checkout_Date\", 1, 0, 0, 1 );' value='" + monIn + "/" + dayIn + "/" + yrIn + "' class='dwDate' title='Display check-in date' />" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling, \"Checkout_Date\", 0, 1, 0, 1 );' class='calArrow' style='margin:0px 0px 0px 2px;' title='Increase display check-in date' tabindex='-1'>&uarr;</a>" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling.previousSibling, \"Checkout_Date\", 0, 0, 1, 1 );' class='calArrow' style='margin:0px 6px 0px 0px;' title='Decrease display check-in date' tabindex='-1'>&darr;</a>" +

										" to " +

										"<input type='text' name='Checkout_Date' id='Checkout_Date' onBlur='return Cal.changeDate( this, \"Checkin_Date\", 1, 0, 0, 1 );' value='" + monOut + "/" + dayOut + "/" + yrOut + "' class='dwDate' style='margin:0px 0px 0px 6px;' title='Display check-out date' />" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling, \"Checkin_Date\", 0, 1, 0, 1 );' class='calArrow' style='margin:0px 0px 0px 2px;' title='Increase display check-out date' tabindex='-1'>&uarr;</a>" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling.previousSibling, \"Checkin_Date\", 0, 0, 1, 1 );' class='calArrow' style='margin:0px 4px 0px 0px;' title='Decrease display check-out date' tabindex='-1'>&darr;</a>" +

										"<span id='nNightsDisplayID'>" + nNights + "</span> nights" +
									"</td>" +
								"</tr>";

								// Actual Check-in to Check-out Dates
								if( this.Settings.activateActualDates )

									gui +=
									"<tr>" +
										"<td style='padding:12px 4px 0px 4px; white-space:nowrap;'>" +
											"Actual Dates" +
										"</td>" +
										"<td style='padding:12px 4px 0px 4px; white-space:nowrap;'>" +
											"<input type='text' name='Checkin_Date_Actual' id='Checkin_Date_Actual' onBlur='return Cal.changeDate( this, \"Checkout_Date_Actual\", 1, 0, 0, 0 );' value='" + ( CkInDateActual.getMonth() + 1 ) + "/" + CkInDateActual.getDate() + "/" + ( CkInDateActual.getFullYear() - 2000 ) + "' class='dwDate' title='Actual check-in date' />" +

											"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling, \"Checkout_Date_Actual\", 0, 1, 0, 0 );' class='calArrow' style='margin:0px 0px 0px 2px;' title='Increase actual check-in date' tabindex='-1'>&uarr;</a>" +

											"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling.previousSibling, \"Checkout_Date_Actual\", 0, 0, 1, 0 );' class='calArrow' style='margin:0px 6px 0px 0px;' title='Decrease actual check-in date' tabindex='-1'>&darr;</a>" +

											" to " +

											"<input type='text' name='Checkout_Date_Actual' id='Checkout_Date_Actual' onBlur='return Cal.changeDate( this, \"Checkin_Date_Actual\", 1, 0, 0, 0 );' value='" + ( CkOutDateActual.getMonth() + 1 ) + "/" + CkOutDateActual.getDate() + "/" + ( CkOutDateActual.getFullYear() - 2000 ) + "' class='dwDate' style='margin:0px 0px 0px 6px;' title='Actual check-out date' />" +

											"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling, \"Checkin_Date_Actual\", 0, 1, 0, 0 );' class='calArrow' style='margin:0px 0px 0px 2px;' title='Increase actual check-out date' tabindex='-1'>&uarr;</a>" +

											"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling.previousSibling, \"Checkin_Date_Actual\", 0, 0, 1, 0 );' class='calArrow' style='margin:0px 4px 0px 0px;' title='Decrease actual check-out date' tabindex='-1'>&darr;</a>" +

											"<span id='nNightsActualID'>" + parseInt( ( CkOutDateActual.getTime() - CkInDateActual.getTime() ) / 86400000 ) + "</span> nights" +
										"</td>" +
									"</tr>";


								// Client
								gui +=
								"<tr>" +
									"<td style='padding:10px 4px 0px 4px; white-space:nowrap;'>" +
										"Client" +
									"</td>" +
									"<td style='padding:10px 4px 0px 4px; white-space:nowrap;'>" +
										"<input type='text' name='Client' class='calText' value='" + guest + "' title='" + this.Msg.client + "' />" +
									"</td>" +
								"</tr>" +

								// Notes
								"<tr>" +
									"<td style='padding:10px 4px 0px 4px; white-space:nowrap;'>" +
										"Notes" +
									"</td>" +
									"<td style='padding:10px 4px 0px 4px; white-space:nowrap;'>" +
										"<textarea name='Notes' rows='5' wrap='true' class='dwNotes' title='" + this.Msg.notes + "'>" + notes + "</textarea>" +
									"</td>" +
								"</tr>" +

								// OK/Cancel Buttons
								"<tr>" +
									"<td align='center' colspan='2' style='padding:10px 0px 0px 0px; white-space:nowrap;'>" +
										"<input type='submit' name='subBut' value='OK' style='margin:0px 4px 0px 0px;' title='" + this.Msg.butEditOK + "' />" +
										"<input type='button' value='Cancel' onClick='DW.removeWin();' style='margin:0px 0px 0px 4px;' title='" + this.Msg.butCancel + "' />" +
									"</td>" +
								"</tr>" +

								// Hidden Info
								"<tr style='display:none;'>" +
									"<td align='center' colspan='2' style='padding:10px 0px 0px 0px;'>" +
										"<input type='text' name='Property_Number' value='" + propNum + "' style='width:60px;' /> " +
										"<input type='text' name='Booking_Number' value='" + bookingNum + "' style='width:60px;' /> " +
									"</td>" +
								"</tr>" +

							"</table>" +
						"</td>" +
					"</tr>" +
				"</table>" +
			"</form>";

			DW.createWindow( [ "Edit " + dwTitle + "<span class='calProp'>: " + propName + "</span>", gui ], [0,460,0], null, evt, 6 );
		}

		// While calendar was armed, user clicked an existing booking: Set a back-to-back
		else {

			var TdOld = this.SpanOld.parentNode;
			var propNameCkIn  = TdOld.previousSibling.innerHTML;
			var propNameCkOut = Span.parentNode.previousSibling.innerHTML;

				if( propNameCkIn == propNameCkOut ) {

					var PropData = TdOld.id.split( "_" );
					for( var i in PropData ) PropData[ i ] = parseInt( PropData[ i ] );

					var propNum = PropData[ 0 ];
					var ckInMon = PropData[ 1 ];
					var ckInYr  = PropData[ 2 ];

					this.nextMon = ckInMon;
					this.nextYr  = ckInYr;

					// Travel the document tree to make sure user clicked span immediately following check-in data
					var ThisSpan = null;
					if( this.SpanOld.nextSibling && this.SpanOld.nextSibling.tagName )
						ThisSpan = this.SpanOld.nextSibling;
					else if( this.SpanOld.nextSibling && this.SpanOld.nextSibling.nextSibling && this.SpanOld.nextSibling.nextSibling.tagName )
						ThisSpan = this.SpanOld.nextSibling.nextSibling;
					else // Last day of month so jump to next td cell
						ThisSpan = this.getNextSpan( propNum, ckInMon, ckInYr );

					while( ThisSpan && ThisSpan != Span ) {
						if( ThisSpan.className == "calBooked" || ThisSpan.className == "calPending" || ThisSpan.className == "calSpecial" )
							break;
						if( ThisSpan.nextSibling && ThisSpan.nextSibling.tagName )
							ThisSpan = ThisSpan.nextSibling;
						else if( ThisSpan.nextSibling && ThisSpan.nextSibling.nextSibling && ThisSpan.nextSibling.nextSibling.tagName )
							ThisSpan = ThisSpan.nextSibling.nextSibling;
						else // Last day of month so jump to next td cell
							ThisSpan = this.getNextSpan( propNum, ckInMon, ckInYr );
					}

					if( Span == ThisSpan ) {
						this.SpanOld.className = "calOpen";
						this.getNewResGUI( Span, evt );
						this.SpanIn = this.SpanOld;
						this.SpanOut = Span;
						this.SpanOld = null;
					}
					else {
						cancelEvt( evt );
						alert( "You clicked an existing reservation after setting a check-in date. It appears you may be attempting to set a new back-to-back reservation???\n\nIf so, you are allowed to add a new back-to-back in this manner, but you must click the existing reservation IMMEDIATELY FOLLOWING your check-in date!" );
					}
			}
			else {
				cancelEvt( evt );
				alert( "You clicked an existing reservation after setting a check-in date for a different property.\n\nTIP: Need to reset & start over? Click the background reset..." );
			}
		}

	}
	//------------------------------ Method: Cal ------------------------------
	// This method uses Range object to update only that portion of display that changes. Lightening fast compared to updating entire display

	function updateDisplay( propNum, ckInMon, ckInDay, ckInYr, ckOutDay, bookClass ) {

		// sub function
		function subAddEvtHandlers( NewSpan ) {

			if( useDOM ) { // W3C
				NewSpan.onclick = function( event ) { if( window.Cal ) Cal.getEditResGUI( this, event ); }
				NewSpan.oncontextmenu = function( event ) { if( window.Cal ) { return Cal.getReadAllWin( this, event ); } }
				NewSpan.onmouseover = function() {
					if( window.Cal ) {
						this.title = ( Cal.SpanOld ) ? Cal.Msg.backToBack : Cal.Msg.edit;
						this.style.cursor = "pointer";
						return true;
					}
				}
			}
			else { // IE
				return "onClick='if( window.Cal ) Cal.getEditResGUI( this, event );' oncontextmenu='if( window.Cal ) { return Cal.getReadAllWin( this, event ); }' onMouseover='if( window.Cal ) { this.title = ( ( Cal.SpanOld ) ? Cal.Msg.backToBack : Cal.Msg.edit ); this.style.cursor = \"pointer\"; return true; }'";
			}
		}

		var ThisSpan = null;

		// ThisSpan will become span tag immediately following check-in span
		if( this.SpanIn.nextSibling && this.SpanIn.nextSibling.tagName )
			ThisSpan = this.SpanIn.nextSibling;
		else if( this.SpanIn.nextSibling && this.SpanIn.nextSibling.nextSibling && this.SpanIn.nextSibling.nextSibling.tagName )
			ThisSpan = this.SpanIn.nextSibling.nextSibling;
		else // Last day of month so jump to next td cell
			ThisSpan = this.getNextSpan( propNum, ckInMon, ckInYr );

		var LastSpan = this.SpanIn;
		var useDOM = ( document.createRange ) ? true : false;
		var Range = ( useDOM ) ? document.createRange() : document.body.createTextRange();

		( useDOM ) ? Range.setStartBefore( this.SpanIn ) : Range.moveToElementText( this.SpanIn );

 		if( !ThisSpan ) ThisSpan = this.SpanOut;
		// Deal with situation where check-in is the final day of month: surround final day w/ span tag;
		var userClickedLastDayOfMon = ( ThisSpan && ThisSpan.innerHTML == "01" );

		if( userClickedLastDayOfMon ) {

			if( useDOM ) {
				// Add span tags around final day of month Range
				Range.setEndAfter( this.SpanIn );
				var NewSpan = document.createElement( "span" );
				subAddEvtHandlers( NewSpan );
				NewSpan.className = bookClass;
				Range.surroundContents( NewSpan );
				NewSpan.innerHTML = Range.toString();

				Range = document.createRange();
				Range.setStartBefore( ThisSpan );
			}
			else {

				// Add span tags around final day of month Range
				var NewRange = document.body.createTextRange();
				NewRange.moveToElementText( this.SpanIn );

				Range.setEndPoint( "EndToEnd", NewRange );
				Range.pasteHTML( "<span class='" + bookClass + "' " + subAddEvtHandlers( null ) + ">" + Range.text + "</span>" );

				Range = document.body.createTextRange();
				Range.moveToElementText( ThisSpan );

			}
		}

		while( ThisSpan && ThisSpan != this.SpanOut ) {
			LastSpan = ThisSpan;

			if( ThisSpan.nextSibling && ThisSpan.nextSibling.tagName ) {
				ThisSpan = ThisSpan.nextSibling;
			}

			else if( ThisSpan.nextSibling && ThisSpan.nextSibling.nextSibling && ThisSpan.nextSibling.nextSibling.tagName ) {
				ThisSpan = ThisSpan.nextSibling.nextSibling;
			}

			else { // Last day of month so jump forward to next td cell

				if( useDOM ) {

					// Add span tags around Range
					Range.setEndAfter( ThisSpan );
					var NewSpan = document.createElement( "span" );
					subAddEvtHandlers( NewSpan );
					NewSpan.className = bookClass;
					Range.surroundContents( NewSpan );
					NewSpan.innerHTML = Range.toString();

					// Now get first span tag of next td
					ThisSpan = this.getNextSpan( propNum, ckInMon, ckInYr );
					LastSpan = ThisSpan;

					// If not checking out first day of month then add span before 01 (first day of this month)
					Range = document.createRange();
					Range.setStartBefore( ThisSpan );
				}

				else { // Not DOM

					// Add span tags around Range
					var NewRange = document.body.createTextRange();
					NewRange.moveToElementText( ThisSpan );

					Range.setEndPoint( "EndToEnd", NewRange );
					Range.pasteHTML( "<span class='" + bookClass + "' " + subAddEvtHandlers( null ) + ">" + Range.text + "</span>" );

					// Now get first span tag of next td
					ThisSpan = this.getNextSpan( propNum, ckInMon, ckInYr );
					LastSpan = ThisSpan;

					// If not checking out first day of month then add span before 01 (first day of this month)
					Range = document.body.createTextRange();
					Range.moveToElementText( ThisSpan );

				}
			}
		}

		// If checking out after first day of month then close add span
		if( ckOutDay > 1 ) {
			if( useDOM ) {

				var NewSpan = document.createElement( "span" );
				subAddEvtHandlers( NewSpan );
				NewSpan.className = bookClass;

				Range.setEndAfter( LastSpan );

				Range.surroundContents( NewSpan );
				NewSpan.innerHTML = Range.toString();
			}
			else { // Not DOM

				var NewRange = document.body.createTextRange();
				NewRange.moveToElementText( LastSpan );
				Range.setEndPoint( "EndToEnd", NewRange );
				Range.pasteHTML( "<span class='" + bookClass + "' " + subAddEvtHandlers( null ) + ">" + Range.text + "</span>" );
			}
		}
	}

	//------------------------------ Method: Cal ------------------------------
	// Called when user clicks OK in Add-Reservation pop-up GUI. This method writes new data to hidden textbox which may ultimately be publshed to web as a js data file.

	function addReservation( Form ) {

		var Now = new Date();

		// Read hidden data in pop-up
		var propName = Form.Property_Name.value;

		var Checkin_Date = Form.Checkin_Date.value.split( "/" );
		for( var i in Checkin_Date ) Checkin_Date[ i ] = parseInt( Checkin_Date[ i ] );

		var Checkout_Date = Form.Checkout_Date.value.split( "/" );
		for( var i in Checkout_Date ) Checkout_Date[ i ] = parseInt( Checkout_Date[ i ] );
		var CkInDate = new Date( Checkin_Date[ 2 ] + 2000, Checkin_Date[ 0 ] - 1, Checkin_Date[ 1 ] );
		var newCkInDate = CkInDate.getTime();

		var CkOutDate = new Date( Checkout_Date[ 2 ] + 2000, Checkout_Date[ 0 ] - 1, Checkout_Date[ 1 ] );
		var newCkOutDate = CkOutDate.getTime();

		// Get booking type: Booked/Pending or Special
		var BookType = Form.BookType, bookType = "0", bookClass = "";
		for( var i = 0; i < BookType.length; i++ ) {
			if( BookType[ i ].checked ) bookType = BookType[ i ].value;

		}

		// Assign CSS class for new booking booking
		switch( bookType ) {
			case "1": bookClass = "calBooked";  break;
			case "2": bookClass = "calPending";  break;
			case "3": bookClass = "calSpecial"; break;
			default: alert( "Switch/Case Error at Cal.addReservation while setting bookClass" );
		}

		var Client = Form.Client;
		var guest = Client.value.toHTM();


		var Notes = Form.Notes;
		var notes = Notes.value.toHTM();

		var ckInActualOffset = 0, ckOutActualOffset = 0;

		// Read actual Check-in/out date offsets
		if( this.Settings.activateActualDates ) {

			var ActualDates = this.setActualDates( Form, newCkInDate, newCkOutDate );
			if( ActualDates ) {
				ckInActualOffset  = ActualDates[ 0 ];
				ckOutActualOffset = ActualDates[ 1 ];
			}
			else return false;
		}

		var br = ( this.Settings.compressData ) ? "" : "\n";
		var newCalData = "";

		newCalData += "CalData=[" + br + br;

		var delBookingsEndingBeforeMS = new Date( Now.getFullYear(), Now.getMonth() - this.Settings.pastMonthsAdmin, 1 ).getTime();

		// Loop thru each property in CalData
		outer:
		for( var j = 0; j < CalData.length - 1; j++ ) {

			newCalData +=  "[\"" + CalData[ j ][ 0 ] + "\",";
			var ExistingDates = CalData[ j ].slice( 1 );

			// Next for loop never entered because this property has no bookings at all: Add very first booking
			if( ExistingDates.length == 0 && propName == CalData[ j ][ 0 ] ) {

				var thisBooking = "[[" + Checkin_Date[ 0 ] + "," + Checkin_Date[ 1 ] + "," + Checkin_Date[ 2 ] + "," + Checkout_Date[ 0 ] + "," + Checkout_Date[ 1 ] + "," + Checkout_Date[ 2 ] + "," + ckInActualOffset + "," + ckOutActualOffset + "]," + bookType + ",\"" + this.userWithWritePrivileges + "\"," + Now.getTime() + "," + "\"" + guest + "\",\"" + notes + "\"," + Now.getTime() + "]";

				newCalData += thisBooking + ",";

			}

			// Loop thru each individual existing booking of this property
			for( var k = 0; k < ExistingDates.length; k++ ) {

				var endDateMS = new Date( ExistingDates[ k ][ 0 ][ 5 ] + 2000, ExistingDates[ k ][ 0 ][ 3 ] - 1, ExistingDates[ k ][ 0 ][ 4 ] ).getTime();

				var existingCalData = ( endDateMS >= delBookingsEndingBeforeMS ) ? "[[" + ExistingDates[ k ][ 0 ][ 0 ] + "," + ExistingDates[ k ][ 0 ][ 1 ] + "," + ExistingDates[ k ][ 0 ][ 2 ] + "," + ExistingDates[ k ][ 0 ][ 3 ] + "," + ExistingDates[ k ][ 0 ][ 4 ] + "," + ExistingDates[ k ][ 0 ][ 5 ] + "," + ExistingDates[ k ][ 0 ][ 6 ] + "," + ExistingDates[ k ][ 0 ][ 7 ] + "]," + ExistingDates[ k ][ 1 ] + ",\"" + ExistingDates[ k ][ 2 ] + "\"," + ExistingDates[ k ][ 3 ] + "," + "\"" + ExistingDates[ k ][ 4 ] + "\",\"" + ExistingDates[ k ][ 5 ] + "\"," + ExistingDates[ k ][ 6 ] + "]," : "";

				// Found the property that new booking shall be added to
				if( propName == CalData[ j ][ 0 ] ) {

					var existingCkInDate = new Date( ExistingDates[ k ][ 0 ][ 2 ] + 2000, ExistingDates[ k ][ 0 ][ 0 ] - 1, ExistingDates[ k ][ 0 ][ 1 ] ).getTime();

					var nextExistingCkInDate = ( k < ExistingDates.length - 1 ) ? new Date( ExistingDates[ k + 1 ][ 0 ][ 2 ] + 2000, ExistingDates[ k + 1 ][ 0 ][ 0 ] - 1, ExistingDates[ k + 1 ][ 0 ][ 1 ] ).getTime() : Number.POSITIVE_INFINITY;

					var thisBooking = "[[" + Checkin_Date[ 0 ] + "," + Checkin_Date[ 1 ] + "," + Checkin_Date[ 2 ] + "," + Checkout_Date[ 0 ] + "," + Checkout_Date[ 1 ] + "," + Checkout_Date[ 2 ] + "," + ckInActualOffset + "," + ckOutActualOffset + "]," + bookType + ",\"" + this.userWithWritePrivileges + "\"," + Now.getTime() + "," + "\"" + guest + "\",\"" + notes + "\"," + Now.getTime() + "]";

					var newBooking = thisBooking + ",";

					// New booking is to be inserted at beginning
					if( k == 0 && newCkInDate < existingCkInDate ) {
						newCalData += newBooking;
						newCalData += existingCalData;
					}

					// New booking is to be inserted between 2 existing bookings or at end
					else if( newCkInDate > existingCkInDate && newCkInDate < nextExistingCkInDate ) {
						newCalData += existingCalData;
						newCalData += newBooking;
					}

					// Add back old existing booking
					else
						newCalData += existingCalData;

				} // End found property

				else // Other property, so just maintain existing bookings
					newCalData += existingCalData;

			} // End Loop thru each individual existing booking of this property

			newCalData = newCalData.replace( /,$/, "" );
			newCalData += "]," + br + br;

		} // End Loop thru each property in CalData

		newCalData += "[\"" + this.userWithWritePrivileges + "\"," + Now.getTime() + "]" + br + br;
		newCalData += "];";

		// Write new data to textarea
		var Form = document.AspForm;
		Form.EditedJS.value = newCalData;

		if( SF ) { // Safari throws range exceptions, so update entire display
			eval( newCalData );
			document.getElementById( "CalID" ).innerHTML = Cal.getCal();
			DW.removeWin();
			Cal.init();
			return false;

		}
		else { // Use Range to update just the portion of display that changes - lightening fast!

			var propNum = parseInt( this.SpanIn.parentNode.id.split( "_" )[ 0 ] );
			var ckInMon = Checkin_Date[ 0 ];
			var ckInDay = Checkin_Date[ 1 ];
			var ckInYr  = Checkin_Date[ 2 ];
			var ckOutDay   = Checkout_Date[ 1 ];

			this.nextMon = ckInMon;
			this.nextYr  = ckInYr;
			this.updateDisplay( propNum, ckInMon, ckInDay, ckInYr, ckOutDay, bookClass );

			// Initialize new data into memory
			eval( newCalData );
			document.getElementById( "calLastUpdateUserID" ).innerHTML = CalData[ CalData.length - 1 ][ 0 ];
			document.getElementById( "calLastUpdateTimeID" ).innerHTML = new Date( CalData[ CalData.length - 1 ][ 1 ] ).toLocaleString();
			DW.removeWin();

			return false;
		}
	}

	//------------------------------ Method: Cal ------------------------------
	// This method launches Add-Reservation pop-up GUI

	function getNewResGUI( Span, evt ) {

		var TdOut   = Span.parentNode;
		var tdOutID = TdOut.id;

		var tdInID = this.SpanOld.parentNode.id;

		var propName = TdOut.previousSibling.firstChild.innerHTML;
		var propNum  = parseInt( tdInID.split( "_" )[ 0 ] );

		var monIn  = parseInt( tdInID.split( "_" )[ 1 ] );
		var dayIn  = parseInt( this.SpanOld.innerHTML.replace( /^0/, "" ) );
		var yrIn   = parseInt( tdInID.split( "_" )[ 2 ] );
		var CkInDate = new Date( yrIn + 2000, monIn - 1, dayIn );

		var monOut  = parseInt( tdOutID.split( "_" )[ 1 ] );
		var dayOut  = parseInt( Span.innerHTML.replace( /^0/, "" ) );
		var yrOut   = parseInt( tdOutID.split( "_" )[ 2 ] );
		var CkOutDate = new Date( yrOut + 2000, monOut - 1, dayOut );

		var nNights = this.getNumNights( CkInDate, CkOutDate );
		var gui =

		"<form name='addRes' style='margin:0px;' onSubmit='return Cal.addReservation( this );'>" +
			"<table align='center' border='0' cellspacing='0' cellpadding='0'>" +
				"<tr>" +
					"<td>" +
						"<table align='center' border='0' cellspacing='0' cellpadding='0' class='calPopUps'>" +

							// Read-only in to out dates & nNights
							"<tr>" +
								"<td align='center' colspan='2' style='padding:4px 0px 0px 0px; cursor:default;' title='" + this.Msg.dtVis + "'>" +
									 "Display Dates: " + this.getDayOfWeek( CkInDate.getDay(), 3 ) + " " + this.getMonthName( monIn, 0 ) + " " + dayIn + ", " + ( ( yrIn < 10 ) ? "0" + yrIn : yrIn ) + " to " + this.getDayOfWeek( CkOutDate.getDay(), 3 ) + " " + this.getMonthName( monOut, 0 ) + " " + dayOut + ", " + ( ( yrOut < 10 ) ? "0" + yrOut : yrOut ) + ";&nbsp; " + nNights + " nights" +
								"</td>" +
							"</tr>" +

							// Add res type
							"<tr>" +
								"<td align='center' colspan='2' style='padding:8px 0px 0px 0px;'>" +
									"I'd like to add the following reservation type:" +
								"</td>" +
							"</tr>" +
							"<tr>" +
								"<td align='center' colspan='2' style='padding:0px 0px 0px 0px;'>" +
									"<input type='radio' name='BookType' value='1' checked title='I&#39;m adding " + this.Msg.bkTypeConf + "' />Confirmed; &nbsp;" +
									"<input type='radio' name='BookType' value='2' title='I&#39;m adding " + this.Msg.bkTypePend + "' />Pending; &nbsp;";

									if( this.Settings.activateSpecials )
										gui += "<input type='radio' name='BookType' value='3' title='" + this.Msg.bkTypeSpc + "' />Special";

									gui +=
								"</td>" +
							"</tr>";

							// Actual Check-in to Check-out Dates
							if( this.Settings.activateActualDates )
								gui +=
								"<tr>" +
									"<td style='padding:12px 4px 0px 4px; white-space:nowrap;'>" +
										"Actual Dates" +
									"</td>" +
									"<td style='padding:12px 4px 0px 4px; white-space:nowrap;'>" +
										"<input type='text' name='Checkin_Date_Actual' id='Checkin_Date_Actual' onBlur='return Cal.changeDate( this, \"Checkout_Date_Actual\", 1, 0, 0, 0 );' value='" + monIn + "/" + dayIn + "/" + yrIn + "' class='dwDate' title='Actual check-in date' />" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling, \"Checkout_Date_Actual\", 0, 1, 0, 0 );' class='calArrow' style='margin:0px 0px 0px 2px;' title='Increase actual check-in date' tabindex='-1'>&uarr;</a>" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling.previousSibling, \"Checkout_Date_Actual\", 0, 0, 1, 0 );' class='calArrow' style='margin:0px 6px 0px 0px;' title='Decrease actual check-in date' tabindex='-1'>&darr;</a>" +

										" to " +

										"<input type='text' name='Checkout_Date_Actual' id='Checkout_Date_Actual' onBlur='return Cal.changeDate( this, \"Checkin_Date_Actual\", 1, 0, 0, 0 );' value='" + monOut + "/" + dayOut + "/" + yrOut + "' class='dwDate' style='margin:0px 0px 0px 6px;' title='Actual check-out date' />" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling, \"Checkin_Date_Actual\", 0, 1, 0, 0 );' class='calArrow' style='margin:0px 0px 0px 2px;' title='Increase actual check-out date' tabindex='-1'>&uarr;</a>" +

										"<a href='javascript:void(0)' onClick='return Cal.changeDate( this.previousSibling.previousSibling, \"Checkin_Date_Actual\", 0, 0, 1, 0 );' class='calArrow' style='margin:0px 4px 0px 0px;' title='Decrease actual check-out date' tabindex='-1'>&darr;</a>" +

										"<span id='nNightsActualID'>" + nNights + "</span> nights" +
									"</td>" +
								"</tr>";


							// Client
							gui +=
							"<tr>" +
								"<td class='calFieldForm'>" +
									"Client" +
								"</td>" +
								"<td class='calValueForm'>" +
									"<input type='text' name='Client' class='calText' title='" + this.Msg.client + "' />" +
								"</td>" +
							"</tr>" +

							// Notes
							"<tr>" +
								"<td class='calFieldForm'>" +
									"Notes" +
								"</td>" +
								"<td class='calValueForm'>" +
									"<textarea name='Notes' rows='5' wrap='true' class='dwNotes' title='" + this.Msg.notes + "'></textarea>" +
								"</td>" +
							"</tr>" +

							// OK/Cancel Buttons
							"<tr>" +
								"<td align='center' colspan='2' style='padding:10px 0px 0px 0px;'>" +
									"<input type='submit' value='OK' style='margin:0px 4px 0px 0px;' title='" + this.Msg.butAddOK + "' />" +
									"<input type='button' value='Cancel' onClick='DW.removeWin();' style='margin:0px 0px 0px 4px;' title='" + this.Msg.butCancel + "' />" +
								"</td>" +
							"</tr>" +

							// Hidden Info
							"<tr style='display:none;'>" +
								"<td align='center' colspan='2' style='padding:10px 0px 0px 0px;'>" +
									"<input type='text' name='Property_Name' value='" + propName + "' style='width:150px;' /> " +
									"<input type='text' name='Checkin_Date' value='" + monIn + "/" + dayIn + "/" + yrIn + "' style='width:60px;' /> " +
									"<input type='text' name='Checkout_Date' value='" + monOut + "/" + dayOut + "/" + yrOut + "' style='width:60px;' />" +
								"</td>" +
							"</tr>" +

						"</table>" +
					"</td>" +
				"</tr>" +
			"</table>" +
		"</form>";

		DW.createWindow( [ "Add New Booking<span class='calProp'>: " + propName + "</span>", gui ], [0,450,0], null, evt, 6 );

		setTimeout( "document.addRes.Client.focus();", 100 );

	}

	//------------------------------ Method: Cal ------------------------------
	// This method takes raw calendar data, which is stored as multidimensional array, and writes visible bookings (as strike-throughs) to web page calendar.

	function getCal() {

		self.status = this.Msg.write;

		// Set hashtable key as property name and set it's value to false (0)
		for( var i = 0; i < CalData.length - 1; i++ )
			this.CarryBookingForward[ CalData[ i ][ 0 ] ] = [ 0, "" ];

		var Today = new Date();
		var thisYear = Today.getFullYear();
		var thisMonth = Today.getMonth() + 1;
		var thisDay = Today.getDate();

		var pastMonths = ( this.publicUser ) ? 0 : this.Settings.pastMonthsAdmin;
		var numMonths = ( this.publicUser ) ? this.Settings.futureMonthsPublic : this.Settings.futureMonthsAdmin + this.Settings.pastMonthsAdmin;

		var firstDayOfFirstMonth = new Date( thisYear, thisMonth - 1 - pastMonths, 1 ).getTime();

		var htm = "";
		var nProps = CalData.length - 1;

		var winWid = this.getWinWid();

		var fSizeCls = ( this.getWinWid() >= 1250 ) ? "calHiRes" : "calLoRes";

		var todayIs = this.getDayOfWeek( Today.getDay() ) + ", " + this.getMonthName( thisMonth, 1 ) + " " + thisDay + ", " + thisYear;

		var greeting = this.Settings.greeting + ", it's " + todayIs;
		if( this.userWithWritePrivileges )
			greeting = this.Settings.greeting + " " + this.userWithWritePrivileges + ", you are logged in as Administrator. It's " + todayIs;
		else if( this.userHasReadAllPrivileges )
			greeting = this.Settings.greeting + ", you have read-all access; click reservations for booking info. It's " + todayIs;

		htm += "<table align='center' border='0' cellspacing='5' cellpadding='0'>";

		htm += "<caption class='calGreeting'>" + greeting + "</caption>";

		htm += "<tr><td colspan='2'><div class='pubCalInstructions' id='PubCalInstructions'><br><br><br><br></div></td></tr>";

		if( this.userWithWritePrivileges ) {
			htm += "<tr><td colspan='2'><div id='AdminCalInstructions'><ul class='calInstructions' style='visibility:hidden;'><li><br></li><li><br></li><li><br></li><li><br></li><li><br></li></ul></div></td></tr>";
			htm += "<tr><td colspan='2' class='calButtons'><input type='button' id='PublishCalendarTop' value='Publish' />&nbsp;&nbsp;<input type='button' id='LogOffCalendarTop' value='Log Off' /></td></tr>";
		}

		///////////////////////// Loop Months /////////////////////////
		for( var monCounter = 0; monCounter < numMonths; monCounter++ ) {

			var htmRow = "";

			self.status = "Writing month " + ( monCounter + 1 ) + " of " + numMonths + "...";

			// These 4 lines of code ensure that months are never over 11 as it breaks SF
			// EX: new Date( 2007, 14, 1 ) must be expressed as new Date( 2008, 2, 1 )
			var nMonthThisRow = thisMonth + monCounter - pastMonths - 1;
			var factor = Math.floor( nMonthThisRow / 12 );
			var nMonth = nMonthThisRow - ( factor * 12 );
			var nYear = thisYear + factor;

			var FirstDayOfThisMonth = new Date( nYear, nMonth, 1 );
			var theYear = FirstDayOfThisMonth.getFullYear();
			var theMonth = FirstDayOfThisMonth.getMonth() + 1;
			var theDay = FirstDayOfThisMonth.getDay();

			var nDaysThisMonth = this.getNumDaysInMonth( theMonth, theYear );

			htmRow +=

			"<tr><td colspan='2' class='calSpacer'>&nbsp;</td></tr>";

			if( monCounter - pastMonths == 0 && pastMonths > 0 )
				htmRow += "<tr><td colspan='2' align='center'><div class='calDivider'><!-- x --></div></td></tr>";

			htmRow +=
			"<tr>" +
				"<td class='calMon " + fSizeCls + "'>" +
					this.getMonthName( theMonth, 1 ) + " " + theYear.toString().substring( 2, 4 ) +
				"</td>" +

				// Write days of week: Su Mo Tu etc.
				"<td class='calDaysWeek " + fSizeCls + "'>&nbsp;";

				var nDay = theDay;

					for( var i = 1; i <= nDaysThisMonth; i++ ) {

						var dayOfWeek = this.getDayOfWeek( nDay, 2 );

						nDay = ( nDay < 6 ) ? nDay + 1 : 0;

						var today = ( thisYear == theYear && thisMonth == theMonth && thisDay == i );

						htmRow += ( today ) ? "<span class='calToday' title='" + ( ( window.Cal ) ? this.Msg.today : "" ) + "'>" + dayOfWeek + "</span> " : dayOfWeek + " ";

					}

			htmRow +=
				"&nbsp;</td>" +
			"</tr>";

			///////////////////////// Loop Properties /////////////////////////
			for( var propNum = 0; propNum < nProps; propNum++ ) {

				var propName = CalData[ propNum ][ 0 ];
				var Bookings = CalData[ propNum ].slice( 1 );
				var openedSpans = 0, closedSpans = 0;

				htmRow +=

				"<tr>" +
					"<td class='calProp " + fSizeCls + "'>" +
						"<span class='calProp'>" +
							propName +
						"</span>" +
					"</td>" +

				"<td class='calDays " + fSizeCls + "' id='" + ( propNum + 1 ) + "_" + theMonth + "_" + ( theYear - 2000 ) + "'>&nbsp;";

				///////////////////////// Loop Days of Month /////////////////////////
				for( var dayOfMon = 1; dayOfMon <= nDaysThisMonth; dayOfMon++ ) {

					var output = ( ( dayOfMon < 10 ) ? "0" + dayOfMon : dayOfMon ) + "";

					if( this.CarryBookingForward[ propName ][ 0 ] ) {
						openedSpans++;
						output = this.CarryBookingForward[ propName ][ 1 ] + output;
						this.CarryBookingForward[ propName ][ 0 ] = 0;
					}


					///////////////////////// Loop Property Bookings /////////////////////////
					for( var bookingNum = 0; bookingNum < Bookings.length; bookingNum++ ) {

						var ckInMon  = Bookings[ bookingNum ][ 0 ][ 0 ];
						var ckInDay  = Bookings[ bookingNum ][ 0 ][ 1 ];
						var ckInYr   = Bookings[ bookingNum ][ 0 ][ 2 ];

						var ckOutMon = Bookings[ bookingNum ][ 0 ][ 3 ];
						var ckOutDay = Bookings[ bookingNum ][ 0 ][ 4 ];
						var ckOutYr  = Bookings[ bookingNum ][ 0 ][ 5 ];

						// If we are carrying over a booking that started before the first day of first month of first year that shows on calendar then let's change it's check-in date to the first day of first month of first year that shows on calendar
						if( monCounter == 0 ) {

							var ckInDateMS  = new Date( ckInYr + 2000, ckInMon - 1, ckInDay ).getTime();
							var ckOutDateMS = new Date( ckOutYr + 2000, ckOutMon - 1, ckOutDay ).getTime();

							if( ckInDateMS < firstDayOfFirstMonth && ckOutDateMS > firstDayOfFirstMonth ) {
								ckInDay = 1;
								ckInMon = theMonth;
								ckInYr = theYear - 2000;
							}
						}

						var begStrikeThrough = ( theMonth == ckInMon && dayOfMon == ckInDay && theYear - 2000 == ckInYr );

						if( ckOutDay - 1 == 0 ) {
							ckOutMon--;
							if( ckOutMon == 0 ) {
								ckOutMon = 12;
								ckOutYr--;
							}
							ckOutDay = getNumDaysInMonth( ckOutMon, ckOutYr + 2000 ) + 1;
						}

						if( begStrikeThrough ) {

							var bookType = Bookings[ bookingNum ][ 1 ];

							switch( bookType ) {


								case 1:
									openedSpans++;
									output = "<span class='calBooked'>" + output;
									this.CarryBookingForward[ propName ][ 1 ] = "<span class='calBooked'>";
									break;

								case 2:
									openedSpans++;
									output = "<span class='calPending'>" + output;
									this.CarryBookingForward[ propName ][ 1 ] = "<span class='calPending'>";
									this.calPending = 1;
									break;

								case 3:
									openedSpans++;
									output = "<span class='calSpecial'>" + output;
									this.CarryBookingForward[ propName ][ 1 ] = "<span class='calSpecial'>";
									this.calSpecial = 1;
									break;

								default:
									alert( "Switch/Case Error at Cal.getCal: begStrikeThrough" );

							}
						}

						var endStrikeThrough = ( theMonth == ckOutMon && dayOfMon == ckOutDay - 1 && theYear - 2000 == ckOutYr );

						if( endStrikeThrough ) {
							closedSpans++;
							output += "</span>";

						}


					} // Loop Property Bookings

					htmRow += output + " ";

				} // Loop Days of Month

				if( openedSpans > closedSpans ) {
					htmRow += "</span>";
					this.CarryBookingForward[ propName ][ 0 ] = 1;
				}

				htmRow +=
					"&nbsp;</td>" +
				"</tr>";

			} // Loop Properties

		htm += htmRow;

		} // Loop Months

		htm +=	"<tr><td colspan='2' class='calLastUpdate'>Calendar last updated by <span id='calLastUpdateUserID'>" + CalData[ CalData.length - 1 ][ 0 ] + "</span> on <span id='calLastUpdateTimeID'>" + new Date( CalData[ CalData.length - 1 ][ 1 ] ).toLocaleString() + "</span>&nbsp; &#149; &nbsp;<a href='javascript:PopUp.printerFriendly();' title='" + Cal.Msg.pf + "'>Printer Friendly</a></td></tr>";

		if( this.userWithWritePrivileges ) {
			htm += "<tr><td colspan='2' class='calButtons'><input type='button' id='PublishCalendarBot' value='Publish' />&nbsp;&nbsp;<input type='button' id='LogOffCalendarBot' value='Log Off' /></td></tr>";
		}

		htm +=	"</table>";

		htm = htm.replace( /\s<\/span>/g, "</span> " );

		htm += "";

		self.status = "";

//prompt( "", htm );
		return htm;
	}

	//------------------------------ Method: Cal ------------------------------
	// This method launches Read-Only pop-up GUI that shows all booking info in non-editable format.

	function getReadAllWin( Span, evt ) {

		// Read property data stored in parent td tag. Note that booking may have begun before this month
		var Td = Span.parentNode;
		var PropData = Td.id.split( "_" );
		for( var i in PropData ) PropData[ i ] = parseInt( PropData[ i ] );

		var propName = Td.previousSibling.firstChild.innerHTML;
		var propNum = PropData[ 0 ];
		var monthClicked = PropData[ 1 ];
		var dayInClicked = parseInt( Span.innerHTML.split( " " )[ 0 ].replace( /^0/, "" ) );
		var yrClicked = PropData[ 2 ];

		var inDateClicked = new Date( yrClicked + 2000, monthClicked - 1, dayInClicked ).getTime();
		var monIn, dayIn, yrIn, CkInDate, monOut, dayOut, yrOut, CkOutDate, bookType = 0, lastEditor, lastEditTime, bookingNum, guest = "", notes = "", creationTime, CkInDateActual, CkOutDateActual;

		// Scan the data & find this booking
		outer:
		for( var i = 0; i < CalData.length - 1; i++ ) {

			// Found the right property
			if( CalData[ i ][ 0 ] == propName ) {

				var Bookings = CalData[ i ].slice( 1 );
				for( var k = 0; k < Bookings.length; k++ ) {

					var firstDayOfBooking = new Date( Bookings[ k ][ 0 ][ 2 ] + 2000, Bookings[ k ][ 0 ][ 0 ] - 1, Bookings[ k ][ 0 ][ 1 ] ).getTime();
					var lastDayOfBooking  = new Date( Bookings[ k ][ 0 ][ 5 ] + 2000, Bookings[ k ][ 0 ][ 3 ] - 1, Bookings[ k ][ 0 ][ 4 ] ).getTime();

					if( inDateClicked >= firstDayOfBooking && inDateClicked < lastDayOfBooking ) {

						monIn    = Bookings[ k ][ 0 ][ 0 ];
						dayIn    = Bookings[ k ][ 0 ][ 1 ];
						yrIn     = Bookings[ k ][ 0 ][ 2 ];
						CkInDate = new Date( yrIn + 2000, monIn - 1, dayIn );

						monOut    = Bookings[ k ][ 0 ][ 3 ];
						dayOut    = Bookings[ k ][ 0 ][ 4 ];
						yrOut     = Bookings[ k ][ 0 ][ 5 ];
						CkOutDate = new Date( yrOut + 2000, monOut - 1, dayOut );

						if( this.Settings.activateActualDates ) {
							CkInDateActual = new Date( yrIn + 2000, monIn - 1, dayIn + Bookings[ k ][ 0 ][ 6 ] );
							CkOutDateActual = new Date( yrOut + 2000, monOut - 1, dayOut - Bookings[ k ][ 0 ][ 7 ] );
						}

						bookType     = Bookings[ k ][ 1 ];
						lastEditor   = Bookings[ k ][ 2 ];
						lastEditTime = Bookings[ k ][ 3 ];
						guest = Bookings[ k ][ 4 ].toHTM();
						notes = Bookings[ k ][ 5 ].toHTM();
						creationTime = Bookings[ k ][ 6 ];

						bookingNum = k;

						break outer;

					}
				}
			}
		}
		var nNights = this.getNumNights( CkInDate, CkOutDate );
		var booking = this.getBookingType( bookType );

		var gui =

		"<table align='center' border='0' cellspacing='0' cellpadding='0'>" +
			"<tr>" +
				"<td>" +
					"<table align='center' border='0' cellspacing='0' cellpadding='0' class='calPopUps'>" +

						// Status
						"<tr>" +
							"<td class='calField'>" +
								"Status" +
							"</td>" +
							"<td class='calValue' id='tdBookingID'>" +
								booking +
							"</td>" +
						"</tr>" +

						// Display Dates
						"<tr style='cursor:default;' title='Dates that are showing on the calendar'>" +
							"<td class='calField'>" +
								"Display Dates" +
							"</td>" +
							"<td class='calValue' id='tdDatesID'>" +
								this.getDayOfWeek( CkInDate.getDay(), 3 ) + " " + this.getMonthName( monIn, 0 ) + " " + dayIn + ", " + ( yrIn + 2000 ) + " to " + this.getDayOfWeek( CkOutDate.getDay(), 3 ) + " " + this.getMonthName( monOut, 0 ) + " " + dayOut + ", " + ( yrOut + 2000 ) + ";&nbsp; " + nNights + " nights" +
							"</td>" +
						"</tr>";

						// Actual Dates
						if( this.Settings.activateActualDates )
							gui +=
							"<tr style='cursor:default;' title='Actual \"real\" check-in & check-out dates'>" +
								"<td class='calField'>" +
									"Actual Dates" +
								"</td>" +
								"<td class='calValue' id='tdDatesID'>" +
									this.getDayOfWeek( CkInDateActual.getDay(), 3 ) + " " + this.getMonthName( CkInDateActual.getMonth() + 1, 0 ) + " " + CkInDateActual.getDate() + ", " + CkInDateActual.getFullYear() + " to " + this.getDayOfWeek( CkOutDateActual.getDay(), 3 ) + " " + this.getMonthName( CkOutDateActual.getMonth() + 1, 0 ) + " " + CkOutDateActual.getDate() + ", " + CkOutDateActual.getFullYear() + ";&nbsp; " + parseInt( ( CkOutDateActual.getTime() - CkInDateActual.getTime() ) / 86400000 ) + " nights" +
								"</td>" +
							"</tr>";


						// Client
						gui +=
						"<tr>" +
							"<td class='calField'>" +
								"Client" +
							"</td>" +
							"<td class='calValue' id='tdGuestID'>" +
								guest +
							"</td>" +
						"</tr>" +

						// Notes
						"<tr>" +
							"<td valign='top' class='calField'>" +
								"Notes" +
							"</td>" +
							"<td class='calValue' id='tdNotesID'>" +
								notes +
							"</td>" +
						"</tr>";

						// Created
						gui +=
						"<tr>" +
							"<td class='calField'>" +
								"Created" +
							"</td>" +
							"<td class='calValue' id='tdLastEditorID'>" +
								new Date( creationTime ).toLocaleString() +
							"</td>" +
						"</tr>" +

						// Last Modified
						"<tr>" +
							"<td class='calField'>" +
								"Last Modified" +
							"</td>" +
							"<td class='calValue' id='tdLastEditorID'>" +
								new Date( lastEditTime ).toLocaleString() + " by " + lastEditor +
							"</td>" +
						"</tr>";

						// Send E-Mail To
						gui +=
						"<tr>" +
							"<td class='calField'>" +
								"<a href='javascript:Cal.sendMail();' title='" + this.Msg.sendMail + "' class='dwLink'>Send Mail To</a>" +
							"</td>" +
							"<td class='calValue'>";

								var counter = 0;
								for( var person in DB.Administrators ) {

									if( person != "David Regier" ) {
										gui += "<input type='checkbox' id='email" + counter + "' value='" + DB.Administrators[ person ] + "' onMouseover='this.title=\"" + DB.Administrators[ person ] + "\";' /> " + person + "<br>";
										counter++;
									}
								}
								gui +=
							"</td>" +
						"</tr>" +

					"</table>" +
				"</td>" +
			"</tr>" +
		"</table>";

		DW.createWindow( [ "Reservation Information<span class='calProp'>: " + propName + "</span>", gui ], [0,600,0], null, evt, 6 );

		try { if( counter == 1 ) document.getElementById( "email0" ).checked = true; } catch( Err ) { }

		return false;
	}

	//------------------------------ Method: Cal ------------------------------
	// Allows calendar administrators to easily write back and forth regarding details of bookings.

	function sendMail() {

		var counter = 0, eMail = "";
		while( document.getElementById( "email" + counter ) ) {

			var Checkbox = document.getElementById( "email" + counter );
			if( Checkbox.checked ) eMail += Checkbox.value + ",";
			counter++;
		}

		eMail = eMail.replace( /,$/, "" );

		var output = "";

		var Cells = document.getElementsByTagName( "td" );
		for ( var i = 0; i < Cells.length - 2; i++ ) {
			if( Cells[ i ].className == "calField" )
				output += Cells[ i ].innerHTML.toText() + ": ";
			if( Cells[ i ].className == "calValue" )
				output += Cells[ i ].innerHTML.toText() + "\r\n";
		}
		var propName = document.getElementById( "dwTitleBarID" ).innerHTML.replace( /<.*?>/g, "" );
		var dates = document.getElementById( "tdDatesID" ).innerHTML.replace( /&nbsp;/g, " " );


		output = "\r\n\r\n" + output + "\r\nRead-All URL: " + this.readAllURL;

		if( SF ) // SF Bug: Escaping causes Mac-Mail to lock-up so don't do it
			document.location.href = "mailto:" + eMail + "?subject=" + propName + "&body=" + output;
		else
			document.location.href = "mailto:" + eMail + "?subject=" + escape( propName ) + "&body=" + escape( output );
	}

	//------------------------------ Method: Cal ------------------------------
	// Called just before onLoad fires. It inserts span tags w/ event handlers that would otherwise drastically slow down calendar rendering to page.

	function init() {

		try {

			if( this.userWithWritePrivileges ) {

				// Insert span tags around all open dates
				var Cells = document.getElementsByTagName( "td" );
				for ( var i = 0; i < Cells.length; i++ ) {
					if( Cells[ i ].className.indexOf( "calDays " ) == 0 ) {
						var data = Cells[ i ].innerHTML;

						var newData = data;
						for( k = 1; k <= 31; k++ ) {
							var day = ( k < 10 ) ? "0" + k : "" + k;

							var Days = data.split( day );
							Days[ 0 ] = Days[ 0 ].toLowerCase();

							var dateOpen = ( Days[ 0 ].split( "span" ).length % 2 ) ? true : false;
							if( dateOpen ) {
								newData = newData.split( day ).join( "<span onClick='Cal.setDates( this, event );' onMouseOver='if( window.Cal ) return Cal.highlight( this, 1 );' onMouseOut='if( window.Cal ) return Cal.highlight( this, 0 );' class='calOpen'>" + day + "</span>" );
							}
						}
						Cells[ i ].innerHTML = newData;
					}
				}

				document.body.onclick = Cal.clear;

				// Add event handlers to existing bookings
				var Spans = document.getElementsByTagName( "span" );
				for ( var i = 0; i < Spans.length; i++ ) {
					if( Spans[ i ].className == "calBooked" || Spans[ i ].className == "calPending" || Spans[ i ].className == "calSpecial" ) {

						Spans[ i ].onclick = function( event ) { if( window.Cal ) Cal.getEditResGUI( this, event ); }
						Spans[ i ].oncontextmenu = function( event ) { if( window.Cal ) { return Cal.getReadAllWin( this, event ); } }
						Spans[ i ].onmouseover = function() {
							if( window.Cal ) {
								this.title = ( Cal.SpanOld ) ? Cal.Msg.backToBack : Cal.Msg.edit;
								this.style.cursor = "pointer";
								return true;
							}
						}
					}
				}

				// Add event handlers to publish calendar buttons (if any)
				var AdminCalInstructions = document.getElementById( "AdminCalInstructions" );
				if( AdminCalInstructions ) {
					// Search calInstructions to find initial hidden ul
					var htm =
					"<table align='center' border='0' cellspacing='0' cellpadding='0'>" +
						"<tr>" +
							"<td>" +
								"<ul class='calInstructions'>" +
									"<li>Click an open date to add a new booking</li>" +
									"<li>Click an existing booking to edit or delete it</li>" +
									"<li>Press Publish when you are finished editing</li>" +
									"<li>Remember to Log Off when you are all done</li>" +
									"<li>For more info read these <a href='calendar-help.aspx' onclick='PopUp.openWin( this.href ); return false;'>instructions & tips</a></li>" +
								"</ul>" +
							"</td>" +
						"</tr>" +
					"</table>";
					AdminCalInstructions.innerHTML = htm;
				}

				var PublishCalendarTop = document.getElementById( "PublishCalendarTop" );
				PublishCalendarTop.onclick = Cal.publish;
				PublishCalendarTop.oncontextmenu = Cal.publishRightClick;
				PublishCalendarTop.title = this.Msg.publish;

				var LogOffCalendarTop = document.getElementById( "LogOffCalendarTop" );
				LogOffCalendarTop.onclick = Cal.logOff;
				LogOffCalendarTop.title = this.Msg.logOff;

				var PublishCalendarBot = document.getElementById( "PublishCalendarBot" );
				PublishCalendarBot.onclick = Cal.publish;
				PublishCalendarBot.oncontextmenu = Cal.publishRightClick;
				PublishCalendarBot.title = this.Msg.publish;

				var LogOffCalendarBot = document.getElementById( "LogOffCalendarBot" );
				LogOffCalendarBot.onclick = Cal.logOff;
				LogOffCalendarBot.title = this.Msg.logOff;

			}

			// Calendar Designations
			var PubCalInstructions = document.getElementById( "PubCalInstructions" );
			if( PubCalInstructions ) {
				// Search calInstructions to find initial hidden ul
				var htm =
				"<table align='center' border='0' cellspacing='0' cellpadding='0'><tr><td><fieldset class='calDesignation'><legend class='calDesignation' align='center' onClick='FW.getLogInGUI( event );'>&nbsp;Calendar Designations</span></legend><table align='center' border='0' cellspacing='0' cellpadding='10'><tr><td><table align='center' border='0' cellspacing='0' cellpadding='0' class='calInstructions'>" +
					"<tr>" +

						"<td align='right' style='padding:0px 4px 0px 0px;'>Available:</td>" +
						"<td class='calDays calHiRes'>&nbsp;01 02 03&nbsp;</td>" +

						"<td align='right' style='padding:0px 4px 0px 20px;'>Reserved:</td>" +
						"<td class='calDays calHiRes'>&nbsp;<span class='calBooked'>01 02 03</span>&nbsp;</td>";

						if( this.calPending ) htm +=
							"<td align='right' style='padding:0px 4px 0px 20px;'>Pending:</td>" +
							"<td class='calDays calHiRes'>&nbsp;<span class='calPending'>01 02 03</span>&nbsp;</td>";

						if( this.calSpecial ) htm +=
							"<td align='right' style='padding:0px 4px 0px 20px;'>Available for Discount:</td>" +
							"<td class='calDays calHiRes'>&nbsp;<span class='calSpecial'>01 02 03</span>&nbsp;</td>";

					htm +=
					"</tr>" +
				"</table></td></tr></table></fieldset></td></tr></table>";
				PubCalInstructions.innerHTML = htm;
			}
			self.status = "";

			if( ( this.publicUser || this.userHasReadAllPrivileges ) && !this.userWithWritePrivileges ) {

				// Insert span tags around all open dates
				var Cells = document.getElementsByTagName( "td" );
				for ( var i = 0; i < Cells.length; i++ ) {
					if( Cells[ i ].className.indexOf( "calDays " ) == 0 ) {
						var data = Cells[ i ].innerHTML;

						var newData = data;
						for( k = 1; k <= 31; k++ ) {
							var day = ( k < 10 ) ? "0" + k : "" + k;

							var Days = data.split( day );
							Days[ 0 ] = Days[ 0 ].toLowerCase();

							var dateOpen = ( Days[ 0 ].split( "span" ).length % 2 ) ? true : false;
							if( dateOpen ) {
								newData = newData.split( day ).join( "<span class='calOpenPub' title='" + this.Msg.open + "'>" + day + "</span>" );
							}
						}
						Cells[ i ].innerHTML = newData;
					}
				}

				// Add tool tips to existing bookings
				var Spans = document.getElementsByTagName( "span" );
				for ( var i = 0; i < Spans.length; i++ ) {
					if( Spans[ i ].className == "calBooked" || Spans[ i ].className == "calPending" || Spans[ i ].className == "calSpecial" ) {

						switch( Spans[ i ].className ) {

							case "calBooked":
								if( this.userHasReadAllPrivileges && Spans[ i ].parentNode.id ) {
									Spans[ i ].onclick = function( event ) { if( window.Cal ) { return Cal.getReadAllWin( this, event ); } }
									Spans[ i ].onmouseover = function() { if( window.Cal ) { this.title = Cal.Msg.confirmed; this.style.cursor = "pointer"; return true; } }
								}
								else
									Spans[ i ].onmouseover = function() { if( window.Cal ) { this.title = Cal.Msg.confirmed; this.style.cursor = "default"; return true; } }
								break;

							case "calPending":
								if( this.userHasReadAllPrivileges && Spans[ i ].parentNode.id ) {
									Spans[ i ].onclick = function( event ) { if( window.Cal ) { return Cal.getReadAllWin( this, event ); } }
									Spans[ i ].onmouseover = function() { if( window.Cal ) { this.title = Cal.Msg.pending; this.style.cursor = "pointer"; return true; } }
								}
								else
									Spans[ i ].onmouseover = function() { if( window.Cal ) { this.title = Cal.Msg.pending; this.style.cursor = "default"; return true; } }
								break;

							case "calSpecial":
								if( this.userHasReadAllPrivileges && Spans[ i ].parentNode.id ) {
									Spans[ i ].onclick = function( event ) { if( window.Cal ) { return Cal.getReadAllWin( this, event ); } }
									Spans[ i ].onmouseover = function() { if( window.Cal ) { this.title = Cal.Msg.special; this.style.cursor = "pointer"; return true; } }
								}
								else
									Spans[ i ].onmouseover = function() { if( window.Cal ) { this.title = Cal.Msg.special; this.style.cursor = "default"; return true; } }
								break;

							default: alert( "Switch/Case Error at Cal.init()" );

						}
					}
				}
			}


		}
		catch( Err ) {
			self.status = "Initializing Cal.init() method, one moment please...";
			setTimeout( "Cal.init();", 250 );
		}

	}
	//------------------------------ Method: Cal ------------------------------
	// Jumps accross table rows to find & return the next span tag as an object

	function getNextSpan( propNum, ckInMon, ckInYr ) {

		this.nextMon++;
		if( this.nextMon > 12 ) {
			this.nextMon = 1;
			this.nextYr++;
		}
		var NextTd = document.getElementById( propNum + "_" + this.nextMon + "_" + this.nextYr );
		if( NextTd ) {
			if( NextTd.firstChild && NextTd.firstChild.tagName )
				ThisSpan = NextTd.firstChild;
			else if( NextTd.firstChild && NextTd.firstChild.nextSibling && NextTd.firstChild.nextSibling.tagName )
				ThisSpan = NextTd.firstChild.nextSibling;
		}
		else
			var ThisSpan = null;

		return ThisSpan;

	}

	//------------------------------ Method: Cal ------------------------------
	// This method highlights check-in and/or check-out date as user interacts with it

	function highlight( Span, on ) {

		// sub function
		function subDisable() {
			Span.className = "calOff";
			Span.title = "";
		}

		var SpanOld = this.SpanOld;

		var settingCkOut = ( SpanOld );

		if( settingCkOut ) {

			if( on ) {
				if( Span.className == "calOpen" || Span.className == "calOff" ) {

					var pNameCkIn = parseInt( SpanOld.parentNode.id.split( "_" )[ 0 ] );
					var ckInMon   = parseInt( SpanOld.parentNode.id.split( "_" )[ 1 ] );
					var ckInDay   = parseInt( SpanOld.innerHTML.replace( /^0/, "" ) );
					var ckInYr    = parseInt( SpanOld.parentNode.id.split( "_" )[ 2 ] );

					var pNameCkOut = parseInt( Span.parentNode.id.split( "_" )[ 0 ] );
					var ckOutMon   = parseInt( Span.parentNode.id.split( "_" )[ 1 ] );
					var ckOutDay   = parseInt( Span.innerHTML.replace( /^0/, "" ) );
					var ckOutYr    = parseInt( Span.parentNode.id.split( "_" )[ 2 ] );

					var ckInDate  = new Date( ckInYr + 2000,  ckInMon - 1,  ckInDay ).getTime();
					var ckOutDate = new Date( ckOutYr + 2000, ckOutMon - 1, ckOutDay ).getTime();

					// If user hovering over correct property
					if( pNameCkIn == pNameCkOut ) {

						// Travel document tree from ck-in to ck-out date. If existing booking found, don't highlight ck-out date
						var foundBooking = false;

						this.nextMon = ckInMon;
						this.nextYr  = ckInYr;

						var ThisSpan = null;
						if( SpanOld.nextSibling && SpanOld.nextSibling.tagName )
							ThisSpan = SpanOld.nextSibling;
						else if( SpanOld.nextSibling && SpanOld.nextSibling.nextSibling && SpanOld.nextSibling.nextSibling.tagName )
							ThisSpan = SpanOld.nextSibling.nextSibling;
						else // Last day of month so jump to next td cell
							ThisSpan = this.getNextSpan( pNameCkIn, ckInMon, ckInYr );

						while( ThisSpan && ThisSpan != Span ) {

							if( ThisSpan.className == "calBooked" || ThisSpan.className == "calPending" || ThisSpan.className == "calSpecial" ) {
								foundBooking = true;
								break;
							}
							if( ThisSpan.nextSibling && ThisSpan.nextSibling.tagName )
								ThisSpan = ThisSpan.nextSibling;
							else if( ThisSpan.nextSibling && ThisSpan.nextSibling.nextSibling && ThisSpan.nextSibling.nextSibling.tagName )
								ThisSpan = ThisSpan.nextSibling.nextSibling;
							else // Last day of month so jump to next td cell
								ThisSpan = this.getNextSpan( pNameCkIn, ckInMon, ckInYr );
						}

						// Mouse over date after check-in
						if( ckOutDate > ckInDate && !foundBooking ) {
							Span.className = "calActive";
							Span.title = this.Msg.ckOut;
						}
						// Mouse over dates prior to check-in
						else
							subDisable();
					}
					else
						subDisable();
				}
			}
			else {
				if( Span.className == "calActive" ) {
					Span.className = "calOpen";
					Span.title = "";
				}
			}
		}
		else { // Setting Check-in date

			Span.className = "calOpen";

			if( on )
				Span.title = this.Msg.ckIn;
			else
				Span.title = "";

		}
		return true;
	}

	//------------------------------ Method: Cal ------------------------------
	// Called on-click of check-in/out dates for new reservation; launches Add-Booking pop-up

	function setDates( Span, evt ) {

		cancelEvt( evt );

		if( Span.className != "calOff" ) {
			// Clicking checkout date
			if( this.SpanOld && Span.className == "calActive" ) {
			Cal.SpanOld.className = "calOpen";
			Span.className = "calOpen";
			Cal.getNewResGUI( Span, evt );
			Cal.SpanIn = Cal.SpanOld;
			Cal.SpanOut = Span;
			Cal.SpanOld = null;
		}

			// Clicking check-in date or re-clicking it to shut it off
			else {

				// User clicks check-in date
				if( Span.className == "calOpen" ) {
					Span.className = "calCkIn";
					this.SpanOld = Span;
					var propName = Span.parentNode.previousSibling.firstChild.innerHTML;
					Span.title = this.Msg.reset;
				}

				// User re-clicks active check-in date, so shut it off
				else {
					Span.className = "calOpen";
					this.SpanOld = null;
					Span.title = this.Msg.ckIn;
				}
			}
		}
		else if( this.SpanOld ) {
			var propName = this.SpanOld.parentNode.previousSibling.firstChild.innerHTML;
			alert( "To set the check-out date, you must click a " + propName + " date that is past the check-in date that you've already established. In addition, there must be no other bookings between the check-in and check-out dates.\n\nTIP: Need to reset & start over? Click the background reset..." );
		}

	}
	//------------------------------ Method: Cal ------------------------------

	// Returns

	function setActualDates( Form, newCkInDate, newCkOutDate ) {

		var CkInActualArr = this.getValidDates( Form.Checkin_Date_Actual, "Actual Checkin" );
		if( CkInActualArr == null ) return false;

		var CkOutActualArr = this.getValidDates( Form.Checkout_Date_Actual, "Actual Checkout" );
		if( CkOutActualArr == null ) return false;

		var CkInDateActual = new Date( CkInActualArr[ 2 ] + 2000, CkInActualArr[ 0 ] - 1, CkInActualArr[ 1 ] );
		var newCkInDateActual = CkInDateActual.getTime();
		ckInActualOffset = parseInt( ( newCkInDateActual - newCkInDate ) / 86400000 );

		var CkOutDateActual = new Date( CkOutActualArr[ 2 ] + 2000, CkOutActualArr[ 0 ] - 1, CkOutActualArr[ 1 ] );
		var newCkOutDateActual = CkOutDateActual.getTime();
		ckOutActualOffset = parseInt( ( newCkOutDate - newCkOutDateActual ) / 86400000 );

		if( ckInActualOffset < 0 ) {
			alert( "Sorry, the actual check-in date \"" + Form.Checkin_Date_Actual.value + "\" is before the display check-in date. " + this.Msg.actual );
			return false;
		}
		else if( ckOutActualOffset < 0 ) {
			alert( "Sorry, the actual check-out date \"" + Form.Checkout_Date_Actual.value + "\" is after the display check-out date. " + this.Msg.actual );
			return false;
		}
		else if( newCkInDateActual > newCkOutDateActual ) {
			alert( "Sorry, but the actual check-in date \"" + Form.Checkin_Date_Actual.value + "\" is after than the actual check-out date \"" + Form.Checkout_Date_Actual.value + "\"." );
			return false;
		}

		return [ ckInActualOffset, ckOutActualOffset ];

	}

	//------------------------------ Method: Cal ------------------------------

	// Validates & returns a 3-member array of dates as integers: [ mon, day, yr ]

	function getValidDates( DateField, description ) {

		var goodDates = 1;
		var dateRE = /^\d{1,2}\/{1}\d{1,2}\/{1}\d{1,2}$/;

		var date = DateField.value;

		if( !dateRE.test( date ) ) {
			//alert( description + " date \"" + date + "\" is invalid: It must be in the mm/dd/yy format, and mm, dd & yy must be digits." );
			//DateField.focus();
			goodDates = 0;
		}

		if( goodDates ) {
			var Dates = date.split( "/" );
			for( var i in Dates ) Dates[ i ] = parseInt( Dates[ i ].replace( /^0/, "" ) );
		}
		else
			var Dates = null;

		return Dates;
	}

	//--------------------------------------------------------------------------------------
	// Called when: (1) onBlur of date field OR; (2) calendar administrator clicks up/down arrows next to days. Allows for fast changing of dates w/ no typing

	function changeDate( ThisField, otherFieldID, blurEvt, increment, decrement, displayDates ) {

		if( !increment ) increment = 0;
		if( !decrement ) decrement = 0;

		if( increment || decrement || blurEvt ) {

			var dateRE = /^\d{1,2}\/{1}\d{1,2}\/{1}\d{1,2}$/;
			if( !dateRE.test( ThisField.value ) ) {
				alert( "Unable to change date \"" + ThisField.value + "\". It must be in the mm/dd/yy format, and mm, dd & yy must be digits." );
				ThisField.value =  ThisField.defaultValue;
				ThisField.focus();
				return false;
			}

			var ThisDate = ThisField.value.split( "/" );
			for( var i = 0; i < ThisDate.length; i++ ) ThisDate[ i ] = parseInt( ThisDate[ i ].replace( /^0/, "" ) );

			if( increment ) ThisDate[ 1 ] += 1;
			else if( decrement ) ThisDate[ 1 ] += -1;

			var NewDate = new Date( ThisDate[ 2 ] + 2000, ThisDate[ 0 ] - 1, ThisDate[ 1 ] );
			ThisField.value = ( NewDate.getMonth() + 1 ) + "/" + NewDate.getDate() + "/" + ( NewDate.getFullYear() - 2000 );

			var OtherDate = document.getElementById( otherFieldID ).value.split( "/" );
			for( var i = 0; i < OtherDate.length; i++ ) OtherDate[ i ] = parseInt( OtherDate[ i ].replace( /^0/, "" ) );
			var otherDate = new Date( OtherDate[ 2 ] + 2000, OtherDate[ 0 ] - 1, OtherDate[ 1 ] ).getTime();

			var spread = ( ThisField.name.indexOf( "Checkin_" ) == 0 ) ? otherDate - NewDate.getTime() : NewDate.getTime() - otherDate;

			var nNights = parseInt( spread ) / 86400000;

			document.getElementById( ( ( displayDates ) ? "nNightsDisplayID" : "nNightsActualID" ) ).innerHTML = nNights;

			return true;

		}
	}
	//------------------------------ Method: Cal ------------------------------
	// This method returns working width of window so that calendar size can be optimized for display

	function getWinWid() {

		var winWid;

		try { winWid = ( IE ) ? document.body.clientWidth : window.innerWidth; }
		catch( Err ) { winWid = 0; }

		return winWid;

	}

	//------------------------------ Method: Cal ------------------------------
	// Returns number of nights as integer from Start & End Date Objects
	function getNumNights( StartDate, EndDate ) {

		var dateDiffMS = EndDate.getTime() - StartDate.getTime();
		return parseInt( dateDiffMS / 86400000 );

	}
	//------------------------------ Method: Cal ------------------------------

	function getDayOfWeek( index, nChars ) {
//alert( "index: " + index + "\nnChars: " + nChars );
		var arrWeekDay = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
		var theDay = arrWeekDay[ index ];
		return ( nChars ) ? theDay.substring( 0, nChars ) : theDay;
	}

	//------------------------------ Method: Cal ------------------------------

	function getMonthName( index, fullName ) {

		var arrMonth = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
		var month = arrMonth[ index - 1 ];
		return( fullName ) ? month : month.substring( 0, 3 );

	}

	//------------------------------ Method: Cal ------------------------------

	function getNumDaysInMonth( month, year ) {

		// Leap years are every 4 years, next one in 2008
		var leapYear = false;

		if( year % 4 != 0 ) leapYear = false;
		else if( year % 400 == 0 ) leapYear = true;
		else if ( year % 100 == 0 ) leapYear = false;
		else leapYear = true;

		var nDays = 31;
		if( month == 4 || month == 6 || month == 9 || month == 11 ) nDays = 30;
		else if( month == 2 ) nDays = ( leapYear ) ? 29 : 28;

		return nDays;

	}
	//------------------------------ Method: Cal ------------------------------
	// Add new method to string object that allows for conversion of ascii text to HTML

	function toHTM() {

		var str = this.toString();
		str = str.replace( /^\s*|\s*$/g, "" );
		str = str.replace( /^\n*|\n*$/g, "" );
		str = str.replace( /\r\n/g, "<br>" );
		str = str.replace( /\r/g, "<br>" );
		str = str.replace( /\n/g, "<br>" );
		str = str.replace( /\"/g, "&#34;" );
		str = str.replace( /\'/g, "&#39;" );
		return str;

	}

	String.prototype.toHTM = toHTM;

	//------------------------------ Method: Cal ------------------------------
	// Add new method to string object that allows for conversion of HTML to ascii text

	function toText() {

		var str = this.toString();
		str = str.replace( /<br>/g, "\r\n" );
		str = str.replace( /&#34;/g, "\"" );
		str = str.replace( /&nbsp;/g, " " );
		str = str.replace( /&amp;/g, "&" );
		return str;

	}

	String.prototype.toText = toText;

	//------------------------------ Method: Cal ------------------------------
	// Stops event from propogating which could eventually bubble up and reset calendar

	function cancelEvt( evt ) {

		if( window.event && window.event.cancelBubble != null )
			window.event.cancelBubble = true;
		else
			evt.stopPropagation();

	}

	//------------------------------ Method: Cal ------------------------------
	// Record modifications for e-mailing

	function recordModifications( Form ) {

		var Now = new Date();

		eval( Form.EditedJS.defaultValue );
		var CalDataInitial = CalData;
		var CalDataInitialHT = new Array();

		eval( Form.EditedJS.value );
		var CalDataFinal = CalData;
		var CalDataFinalHT = new Array();

		var htmNew = "", htmEdited = "", htmDeleted = "";

		// Step 1
		// Build CalDataInitialHT Hash-Tables from Initial cal-data.js.
		// Look-up key is 2-dim array: [ property-name ][ creation-data ]
		// Loop each property, typically just 1
		for( var i = 0; i < CalDataInitial.length - 1; i++ ) {
			var PropertyInitial = CalDataInitial[ i ];
			var propertyInitialName = CalDataInitial[ i ][ 0 ];
			CalDataInitialHT[ propertyInitialName ] = new Array();

			// Loop individal bookings in PropertyInitial
			for( var k = 1; k < PropertyInitial.length; k++ ) {
				var creationDate = PropertyInitial[ k ][ 6 ].toString();
				CalDataInitialHT[ propertyInitialName ][ creationDate ] = PropertyInitial[ k ];
				//alert( "CalDataInitialHT[ \"" + propertyInitialName + "\" ][ \"" + creationDate + "\" ]: " + CalDataInitialHT[ propertyInitialName ][ creationDate ] );
			}
		}

		// Step 2
		// Build CalDataFinalHT Hash-Tables from Final cal-data.js
		// Loop each property, typically just 1
		for( var i = 0; i < CalDataFinal.length - 1; i++ ) {
			var PropertyFinal = CalDataFinal[ i ];
			var propertyFinalName = CalDataFinal[ i ][ 0 ];
			CalDataFinalHT[ propertyFinalName ] = new Array();

			// Loop individal bookings in PropertyFinal
			for( var k = 1; k < PropertyFinal.length; k++ ) {
				var creationDate = PropertyFinal[ k ][ 6 ].toString();
				CalDataFinalHT[ propertyFinalName ][ creationDate ] = PropertyFinal[ k ];
				//alert( "CalDataFinalHT[ \"" + propertyFinalName + "\" ][ \"" + creationDate + "\" ]: " + CalDataFinalHT[ propertyFinalName ][ creationDate ] );
			}
		}

		// Step 3
		// Loop back thru CalDataFinalHT and compare each member with CalDataInitialHT
		// This Loop will find all edited & new bookings
		for( var propertyFinalName in CalDataFinalHT ) {
			var PropertyFinal = CalDataFinalHT[ propertyFinalName ];
			for( var creationDate in PropertyFinal ) {

				// If there is an initial match for this final, then compare them for differences
				if( CalDataInitialHT[ propertyFinalName ][ creationDate ] ) {

					// Quickly compare arrays by deflating to a string. If not the same, then record changes
					if( CalDataInitialHT[ propertyFinalName ][ creationDate ].toString() != CalDataFinalHT[ propertyFinalName ][ creationDate ].toString() ) {

						// MODIFIED BOOKING //////////////////////////////////////////////////

						var BookingInitial = CalDataInitialHT[ propertyFinalName ][ creationDate ];
						var BookingFinal = CalDataFinalHT[ propertyFinalName ][ creationDate ];

						// Ck-in Display dates
						var CkInDateInitial = new Date( BookingInitial[ 0 ][ 2 ] + 2000, BookingInitial[ 0 ][ 0 ] - 1, BookingInitial[ 0 ][ 1 ] );
						var ckInDateInitialMS = CkInDateInitial.getTime();
						var ckInDayOfWeekInitial = Cal.getDayOfWeek( CkInDateInitial.getDay(), 3 );

						var CkInDateFinal = new Date( BookingFinal[ 0 ][ 2 ] + 2000, BookingFinal[ 0 ][ 0 ] - 1, BookingFinal[ 0 ][ 1 ] );
						var ckInDateFinalMS = CkInDateFinal.getTime();
						var ckInDayOfWeekFinal = Cal.getDayOfWeek( CkInDateFinal.getDay(), 3 );


						// Ck-out Display dates
						var CkOutDateInitial = new Date( BookingInitial[ 0 ][ 5 ] + 2000, BookingInitial[ 0 ][ 3 ] - 1, BookingInitial[ 0 ][ 4 ] );
						var ckOutDateInitialMS = CkOutDateInitial.getTime();
						var ckOutDayOfWeekInitial = Cal.getDayOfWeek( CkOutDateInitial.getDay(), 3 );

						var CkOutDateFinal = new Date( BookingFinal[ 0 ][ 5 ] + 2000, BookingFinal[ 0 ][ 3 ] - 1, BookingFinal[ 0 ][ 4 ] );
						var ckOutDateFinalMS = CkOutDateFinal.getTime();
						var ckOutDayOfWeekFinal = Cal.getDayOfWeek( CkOutDateFinal.getDay(), 3 );

						var nNightsInitial = Cal.getNumNights( CkInDateInitial, CkOutDateInitial );
						var nNightsFinal = Cal.getNumNights( CkInDateFinal, CkOutDateFinal );


						// Ck-in Actual dates
						var CkInDateInitialActual = new Date( BookingInitial[ 0 ][ 2 ] + 2000, BookingInitial[ 0 ][ 0 ] - 1, BookingInitial[ 0 ][ 1 ] + BookingInitial[ 0 ][ 6 ] );
						var ckInDateInitialActualMS = CkInDateInitialActual.getTime();
						var ckInDayOfWeekInitialActual = Cal.getDayOfWeek( CkInDateInitialActual.getDay(), 3 );

						var CkInDateFinalActual = new Date( BookingFinal[ 0 ][ 2 ] + 2000, BookingFinal[ 0 ][ 0 ] - 1, BookingFinal[ 0 ][ 1 ] + BookingFinal[ 0 ][ 6 ] );
						var ckInDateFinalActualMS = CkInDateFinalActual.getTime();
						var ckInDayOfWeekFinalActual = Cal.getDayOfWeek( CkInDateFinalActual.getDay(), 3 );

						// Ck-out Actual dates
						var CkOutDateInitialActual = new Date( BookingInitial[ 0 ][ 5 ] + 2000, BookingInitial[ 0 ][ 3 ] - 1, BookingInitial[ 0 ][ 4 ] - BookingInitial[ 0 ][ 7 ] );
						var ckOutDateInitialActualMS = CkOutDateInitialActual.getTime();
						var ckOutDayOfWeekInitialActual = Cal.getDayOfWeek( CkOutDateInitialActual.getDay(), 3 );

						var CkOutDateFinalActual = new Date( BookingFinal[ 0 ][ 5 ] + 2000, BookingFinal[ 0 ][ 3 ] - 1, BookingFinal[ 0 ][ 4 ] - BookingFinal[ 0 ][ 7 ] );
						var ckOutDateFinalActualMS = CkOutDateFinalActual.getTime();
						var ckOutDayOfWeekFinalActual = Cal.getDayOfWeek( CkOutDateFinalActual.getDay(), 3 );

						htmEdited +=

						"<br>" +
						"<table border='0' cellspacing='0' cellpadding='0' class='eMailOuter'>" +
							"<tr>" +
								"<td class='eMailOuter'>" +

							"<table border='0' cellspacing='0' cellpadding='0'>";

							// If 2 or more properties show prop name
							if( CalDataInitial.length > 2 ) htmEdited +=
								"<tr>" +
									"<td class='eMailLeftCol'>" +
										"Rental: " +
									"</td>" +
									"<td class='eMailRightCol'>" +
										propertyFinalName +
									"</td>" +
								"</tr>";

								htmEdited +=
								"<tr>" +
									"<td class='eMailLeftCol'>" +
"Status: " +
									"</td>" +
									"<td class='eMailRightCol'>";

										if( BookingInitial[ 1 ] == BookingFinal[ 1 ] ) htmEdited +=
											Cal.getBookingType( BookingFinal[ 1 ] );

										else htmEdited +=
											"<span class='eMailModified'>" +
												"<nobr>" + Cal.getBookingType( BookingInitial[ 1 ] ) + "</nobr>" +
												" &rarr; " +
												"<nobr>" + Cal.getBookingType( BookingFinal[ 1 ] ) + "</nobr>" +
											"</span>";

									htmEdited +=
									"</td>" +
								"</tr>" +

								"<tr>" +
									"<td class='eMailLeftCol'>" +
"Display Dates: " +
									"</td>" +
									"<td class='eMailRightCol'>";

										// No change of display dates
										if( ckInDateInitialMS == ckInDateFinalMS && ckOutDateInitialMS == ckOutDateFinalMS )

											htmEdited +=
											ckInDayOfWeekFinal + " " + BookingFinal[ 0 ][ 0 ] + "/" + BookingFinal[ 0 ][ 1 ] + "/" + BookingFinal[ 0 ][ 2 ] + " to " + ckOutDayOfWeekFinal + " " + BookingFinal[ 0 ][ 3 ] + "/" + BookingFinal[ 0 ][ 4 ] + "/" + BookingFinal[ 0 ][ 5 ] + "; " + nNightsFinal + " nights";

										else htmEdited +=
											"<span class='eMailModified'>" +

												"<nobr>" +
													ckInDayOfWeekInitial + " " + BookingInitial[ 0 ][ 0 ] + "/" + BookingInitial[ 0 ][ 1 ] + "/" + BookingInitial[ 0 ][ 2 ] + " to " + ckOutDayOfWeekInitial + " " + BookingInitial[ 0 ][ 3 ] + "/" + BookingInitial[ 0 ][ 4 ] + "/" + BookingInitial[ 0 ][ 5 ] + "; " + nNightsInitial + " nights" +
												"</nobr>" +

												"<br>&darr;<br>" +

												"<nobr>" +
													ckInDayOfWeekFinal + " " + BookingFinal[ 0 ][ 0 ] + "/" + BookingFinal[ 0 ][ 1 ] + "/" + BookingFinal[ 0 ][ 2 ] + " to " + ckOutDayOfWeekFinal + " " + BookingFinal[ 0 ][ 3 ] + "/" + BookingFinal[ 0 ][ 4 ] + "/" + BookingFinal[ 0 ][ 5 ] + "; " + nNightsFinal + " nights" +
												"</nobr>" +

											"</span>";

									htmEdited +=
									"</td>" +
								"</tr>" +

								"<tr>" +
									"<td class='eMailLeftCol'>" +
"Actual Dates: " +
									"</td>" +
									"<td class='eMailRightCol'>";

										// No change of actual dates
										if( ckInDateInitialActualMS == ckInDateFinalActualMS && ckOutDateInitialActualMS == ckOutDateFinalActualMS )

										htmEdited +=
											ckInDayOfWeekInitialActual + " " + ( CkInDateInitialActual.getMonth() + 1 ) + "/" + CkInDateInitialActual.getDate() + "/" + ( CkInDateInitialActual.getFullYear() - 2000 ) + " to " + ckOutDayOfWeekInitialActual + " " + ( CkOutDateInitialActual.getMonth() + 1 ) + "/" + CkOutDateInitialActual.getDate() + "/" + ( CkOutDateInitialActual.getFullYear() - 2000 ) + "; " + ( nNightsInitial - BookingInitial[ 0 ][ 6 ] - BookingInitial[ 0 ][ 7 ] ) + " nights";

										else htmEdited +=
											"<span class='eMailModified'>" +

												"<nobr>" +
													ckInDayOfWeekInitialActual + " " + ( CkInDateInitialActual.getMonth() + 1 ) + "/" + CkInDateInitialActual.getDate() + "/" + ( CkInDateInitialActual.getFullYear() - 2000 ) + " to " + ckOutDayOfWeekInitialActual + " " + ( CkOutDateInitialActual.getMonth() + 1 ) + "/" + CkOutDateInitialActual.getDate() + "/" + ( CkOutDateInitialActual.getFullYear() - 2000 ) + "; " + ( nNightsInitial - BookingInitial[ 0 ][ 6 ] - BookingInitial[ 0 ][ 7 ] ) + " nights" +
												"</nobr>" +

												"<br>&darr;<br>" +

												"<nobr>" +
													ckInDayOfWeekFinalActual + " " + ( CkInDateFinalActual.getMonth() + 1 ) + "/" + CkInDateFinalActual.getDate() + "/" + ( CkInDateFinalActual.getFullYear() - 2000 ) + " to " + ckOutDayOfWeekFinalActual + " " + ( CkOutDateFinalActual.getMonth() + 1 ) + "/" + CkOutDateFinalActual.getDate() + "/" + ( CkOutDateFinalActual.getFullYear() - 2000 ) + "; " + ( nNightsFinal - BookingFinal[ 0 ][ 6 ] - BookingFinal[ 0 ][ 7 ] ) + " nights" +
												"</nobr>" +

											"</span>";

									htmEdited +=
									"</td>" +
								"</tr>" +

								"<tr>" +
									"<td class='eMailLeftCol'>" +
"Client: " +
									"</td>" +
									"<td class='eMailRightCol'>";

										if( BookingInitial[ 4 ] == BookingFinal[ 4 ] ) htmEdited +=
											BookingInitial[ 4 ];

										else htmEdited +=
											"<span class='eMailModified'>" +
												"<nobr>" + ( ( BookingInitial[ 4 ] ) ? BookingInitial[ 4 ] : "No Name" ) + "</nobr>" +
												" &rarr; " +
												"<nobr>" + ( ( BookingFinal[ 4 ] ) ?  BookingFinal[ 4 ] : "No Name" ) + "</nobr>" +
											"</span>";

									htmEdited +=
									"</td>" +
								"</tr>" +

								"<tr>" +
									"<td class='eMailLeftCol'>" +
"Notes: " +
									"</td>" +
									"<td class='eMailRightCol'>";

										if( BookingInitial[ 5 ] == BookingFinal[ 5 ] ) htmEdited +=
											BookingInitial[ 5 ];

										else htmEdited +=
											"<span class='eMailModified'>" +
												( ( BookingInitial[ 5 ] ) ? BookingInitial[ 5 ] : "No Notes" )  +
												"<br>&darr;<br>" +
												( ( BookingFinal[ 5 ] ) ? BookingFinal[ 5 ] : "No Notes" )  +
											"</span>";

									htmEdited +=
									"</td>" +
								"</tr>" +

								"<tr>" +
									"<td class='eMailLeftCol'>" +
"Created: " +
									"</td>" +
									"<td class='eMailRightCol'>" +
										new Date( BookingFinal[ 6 ] ).toLocaleString() +
									"</td>" +
								"</tr>" +

								"<tr>" +
									"<td class='eMailLeftCol'>" +
										"Modified: " +
									"</td>" +
									"<td class='eMailRightCol'>" +
										new Date( BookingFinal[ 3 ] ).toLocaleString() +
									"</td>" +
								"</tr>" +

							"</table>" +

								"</td>" +
							"</tr>" +
						"</table>";

					}
				}


				// NEW BOOKING //////////////////////////////////////////////////
				// No match found so this is a new booking
				else {

					var Booking = CalDataFinalHT[ propertyFinalName ][ creationDate ];

					// Display dates
					var CkInDate = new Date( Booking[ 0 ][ 2 ] + 2000, Booking[ 0 ][ 0 ] - 1, Booking[ 0 ][ 1 ] );
					var ckInDayOfWeek = Cal.getDayOfWeek( CkInDate.getDay(), 3 );

					var CkOutDate = new Date( Booking[ 0 ][ 5 ] + 2000, Booking[ 0 ][ 3 ] - 1, Booking[ 0 ][ 4 ] );
					var ckOutDayOfWeek = Cal.getDayOfWeek( CkOutDate.getDay(), 3 );

					var nNights = Cal.getNumNights( CkInDate, CkOutDate );

					// Actual dates
					var CkInDateActual = new Date( Booking[ 0 ][ 2 ] + 2000, Booking[ 0 ][ 0 ] - 1, Booking[ 0 ][ 1 ] + Booking[ 0 ][ 6 ] );
					var ckInDayOfWeekActual = Cal.getDayOfWeek( CkInDateActual.getDay(), 3 );

					var CkOutDateActual = new Date( Booking[ 0 ][ 5 ] + 2000, Booking[ 0 ][ 3 ] - 1, Booking[ 0 ][ 4 ] - Booking[ 0 ][ 7 ] );
					var ckOutDayOfWeekActual = Cal.getDayOfWeek( CkOutDateActual.getDay(), 3 );

					htmNew +=

					"<br>" +
					"<table border='0' cellspacing='0' cellpadding='0' class='eMailOuter'>" +
						"<tr>" +
							"<td class='eMailOuter'>" +

						"<table border='0' cellspacing='0' cellpadding='0'>";

						// If 2 or more properties show prop name
						if( CalDataInitial.length > 2 ) htmNew +=
							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Rental: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									propertyFinalName +
								"</td>" +
							"</tr>";

							htmNew +=
							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Status: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									Cal.getBookingType( Booking[ 1 ] ) +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Display Dates: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									ckInDayOfWeek + " " + Booking[ 0 ][ 0 ] + "/" + Booking[ 0 ][ 1 ] + "/" + Booking[ 0 ][ 2 ] + " to " + ckOutDayOfWeek + " " + Booking[ 0 ][ 3 ] + "/" + Booking[ 0 ][ 4 ] + "/" + Booking[ 0 ][ 5 ] + "; " + nNights + " nights" +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Actual Dates: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									ckInDayOfWeekActual + " " + ( CkInDateActual.getMonth() + 1 ) + "/" + CkInDateActual.getDate() + "/" + ( CkInDateActual.getFullYear() - 2000 ) + " to " + ckOutDayOfWeekActual + "/" + ( CkOutDateActual.getMonth() + 1 ) + "/" + CkOutDateActual.getDate() + "/" + ( CkOutDateActual.getFullYear() - 2000 ) + "; " + ( nNights - Booking[ 0 ][ 6 ] - Booking[ 0 ][ 7 ] ) + " nights" +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Client: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									Booking[ 4 ] +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Notes: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									Booking[ 5 ] +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Created: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									new Date( Booking[ 6 ] ).toLocaleString() +
								"</td>" +
							"</tr>" +

						"</table>" +

							"</td>" +
						"</tr>" +
					"</table>";
				}
			}
		}

		// Step 4 (reverse of step 3)
		// Loop back thru CalDataInitialHT and compare each member with CalDataFinalHT
		// This Loop will find all deleted bookings but no need to find edited bookings - already done in #3
		for( var propertyInitialName in CalDataInitialHT ) {
			var PropertyInitial = CalDataInitialHT[ propertyInitialName ];
			for( var creationDate in PropertyInitial ) {

				// If there is not a final match for this initial then it has been deleted
				if( !CalDataFinalHT[ propertyInitialName ][ creationDate ] ) {

					// DELETED BOOKING //////////////////////////////////////////////////

					var Booking = CalDataInitialHT[ propertyInitialName ][ creationDate ];

					// Display dates
					var CkInDate = new Date( Booking[ 0 ][ 2 ] + 2000, Booking[ 0 ][ 0 ] - 1, Booking[ 0 ][ 1 ] );
					var ckInDayOfWeek = Cal.getDayOfWeek( CkInDate.getDay(), 3 );

					var CkOutDate = new Date( Booking[ 0 ][ 5 ] + 2000, Booking[ 0 ][ 3 ] - 1, Booking[ 0 ][ 4 ] );
					var ckOutDayOfWeek = Cal.getDayOfWeek( CkOutDate.getDay(), 3 );

					var autoDeletedMS = new Date( Now.getFullYear(), Now.getMonth() - this.Settings.pastMonthsAdmin, 1 ).getTime();

					// If booking expired and was automatically deleted don't record it
					if( CkOutDate.getTime() < autoDeletedMS )
						continue;

					var nNights = Cal.getNumNights( CkInDate, CkOutDate );

					// Actual dates
					var CkInDateActual = new Date( Booking[ 0 ][ 2 ] + 2000, Booking[ 0 ][ 0 ] - 1, Booking[ 0 ][ 1 ] + Booking[ 0 ][ 6 ] );
					var ckInDayOfWeekActual = Cal.getDayOfWeek( CkInDateActual.getDay(), 3 );

					var CkOutDateActual = new Date( Booking[ 0 ][ 5 ] + 2000, Booking[ 0 ][ 3 ] - 1, Booking[ 0 ][ 4 ] - Booking[ 0 ][ 7 ] );
					var ckOutDayOfWeekActual = Cal.getDayOfWeek( CkOutDateActual.getDay(), 3 );

					htmDeleted +=

					"<br>" +
					"<table border='0' cellspacing='0' cellpadding='0' class='eMailOuter'>" +
						"<tr>" +
							"<td class='eMailOuter'>" +

						"<table border='0' cellspacing='0' cellpadding='0'>";

						// If 2 or more properties show prop name
						if( CalDataInitial.length > 2 ) htmDeleted +=
							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Rental: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									propertyInitialName +
								"</td>" +
							"</tr>";

							htmDeleted +=
							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Status: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									Cal.getBookingType( Booking[ 1 ] ) +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Display Dates: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									ckInDayOfWeek + " " + Booking[ 0 ][ 0 ] + "/" + Booking[ 0 ][ 1 ] + "/" + Booking[ 0 ][ 2 ] + " to " + ckOutDayOfWeek + " " + Booking[ 0 ][ 3 ] + "/" + Booking[ 0 ][ 4 ] + "/" + Booking[ 0 ][ 5 ] + "; " + nNights + " nights" +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Actual Dates: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									ckInDayOfWeekActual + " " + ( CkInDateActual.getMonth() + 1 ) + "/" + CkInDateActual.getDate() + "/" + ( CkInDateActual.getFullYear() - 2000 ) + " to " + ckOutDayOfWeekActual + "/" + ( CkOutDateActual.getMonth() + 1 ) + "/" + CkOutDateActual.getDate() + "/" + ( CkOutDateActual.getFullYear() - 2000 ) + "; " + ( nNights - Booking[ 0 ][ 6 ] - Booking[ 0 ][ 7 ] ) + " nights" +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Client: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									Booking[ 4 ] +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Notes: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									Booking[ 5 ] +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Created: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									new Date( Booking[ 6 ] ).toLocaleString() +
								"</td>" +
							"</tr>" +

							"<tr>" +
								"<td class='eMailLeftCol'>" +
									"Last Modified: " +
								"</td>" +
								"<td class='eMailRightCol'>" +
									new Date( Booking[ 3 ] ).toLocaleString() +
								"</td>" +
							"</tr>" +

						"</table>" +

							"</td>" +
						"</tr>" +
					"</table>";

				}

			}
		}

		var output = ( ( htmNew ) ? "<div class='eMailSectionTitle'>New Bookings:</div>" + htmNew + "<br><br>" : "" ) + ( ( htmEdited ) ? "<div class='eMailSectionTitle'>Modified Bookings:</div>" + htmEdited + "<br><br>" : "" ) + ( ( htmDeleted ) ? "<div class='eMailSectionTitle'>Deleted Bookings:</div>" + htmDeleted : "" );

		output +=
			"<div class='eMailSectionTitle' style='margin:30px 0px 0px 0px;'>Read-All URL:</div>" +
			"<div style='margin:5px 0px 0px 20px;'><a href='" + Cal.readAllURL + "'>" + Cal.readAllURL + "</a></div>";

		Form.Calendar_Modifications.value = output;
		Form.Calendar_Modification_Time.value = Now.toLocaleString() + "<br>(" + Cal.userWithWritePrivileges + "'s Time Zone)";

		// Save for debugging
		// document.getElementById( "emailSimulator" ).innerHTML = output;
	}

	//------------------------------ Method: Cal ------------------------------
	// Allows for calendar data to be published w/o any modification of data & w/o server site backup

		function publishRightClick() {
			Cal.publish( 1 );
			return false;
		}

	//------------------------------ Method: Cal ------------------------------
	// Allows for calendar-administrator to publish data to web. Upon submission, processing is taken over by server-side c# (code.cs)

		function publish( rightClick ) {

			var leftClick = ( rightClick == 1 ) ? false : true;
			rightClick = !leftClick;

			var Form = document.AspForm;

			eval( Form.EditedJS.defaultValue );
			var CalDataFinal = CalData.slice( 0, CalData.length - 1 );
			var calDataFinal = CalDataFinal.toString();

			eval( Form.EditedJS.value );
			var CalDataInitial = CalData.slice( 0, CalData.length - 1 );
			var calDataInitial = CalDataInitial.toString();

			// Remove last-mod dates
			calDataInitial = calDataInitial.replace( /,\d{13,},/g, "" );
			calDataFinal = calDataFinal.replace( /,\d{13,},/g, "" );

			// Compare before & after CalData data
			if( ( leftClick && calDataInitial != calDataFinal ) || rightClick ) {
				if( Cal.userWithWritePrivileges != "Demo User" ) {
					Form.ASP_Job.value = "File_Writer";
					Form.Which_Button.value = ( leftClick ) ? "js" : "jsRightClick";
					var PublishCalendarBot = document.getElementById( "PublishCalendarBot" );
						if( PublishCalendarBot ) document.getElementById( "PublishCalendarBot" ).disabled = true;
					var PublishCalendarTop = document.getElementById( "PublishCalendarTop" );
						if( PublishCalendarTop ) document.getElementById( "PublishCalendarTop" ).disabled = true;

					Cal.recordModifications( Form );

					Form.submit();
					DW.removeWin();
				}
				else
					alert( "Sorry, but Publishing has been disabled for the demo..." );
			}
			else
				alert( "You have not edited the calendar, edit the calendar then press Publish" );

	}

	//------------------------------ Method: Cal ------------------------------
	function logOff() {

		var logOff = 1;
		var Form = document.AspForm;

		if( live && Form.EditedJS.value != Form.EditedJS.defaultValue ) {
			logOff = ( confirm( "You have edited the calendar without publishing. Your unpublished edits will be lost upon logging out.\n\nDo you still want to log off & lose your unpublished edits?" ) ) ? 1 : 0;
			if( logOff ) Form.EditedJS.value = Form.EditedJS.defaultValue;
		}
		if( logOff ) {
			document.getElementById( "LogOffCalendarTop" ).disabled = true;
			document.getElementById( "LogOffCalendarBot" ).disabled = true;
			document.location.replace( fileName + "?logoff=yes" );
		}
	}

	//------------------------------ Method: Cal ------------------------------
	function getBookingType( nBooking ) {

		switch( nBooking ) {
			case 1:  return "Confirmed Reservation";
			case 2:  return "Pending Reservation";
			case 3:  return "Available for Discount";
			default: alert( "Switch/Case Error at Cal.getBookingType" ); return "";
		}
	}

	//------------------------------ Method: Cal ------------------------------
	// set by document.body.onclick in init method
	function clear() {

		if( window.Cal && Cal.SpanOld ) {
			Cal.SpanOld.className = "calOpen";
			Cal.SpanOld.title = "";
			Cal.SpanOld = null;
		}

	}

}

///////////////////////////////////////// End Calendar: Cal ////////////////////////////////////////

// Initialize new Calendar Object
Cal = new Calendar();