﻿
window.onerror = null;

// OT JS Library
// Includes functions from common93.js, validation93.js, SearchScripts02.js, DateControlFuncs93.js, clockCheck110.js

//FUNCTION IMAGE SWAP
function swap(imgname, imgB) {
	document[imgname].src = imgB;
	}
	
//FUNCTION IMAGE Print Page  
function printPage() {
	if (window.print) window.print()
	}
	
//set a cookie value
function setCookie(name, value) {
	var curCookie = name + " = " + escape(value);
	document.cookie = curCookie;
	}
	
//set a cookie value and assign it to a domain.
function setCookieForDomain(name, value, domain) {
	var curCookie = name + " = " + escape(value);
	if(domain && domain.length > 0) curCookie = curCookie + ";domain=" + domain;
	document.cookie = curCookie;
	}
	
//set a cookie value and assign it to a domain.
function setCookieForDomainWithExpiry(name, value, domain, nExpiryYears) {
	var dtExpiry = new Date();
	dtExpiry.setFullYear(dtExpiry.getFullYear() + nExpiryYears);
	var curCookie = name + " = " + escape(value);
	if(domain && domain.length > 0) curCookie = curCookie + ";domain=" + domain + ';expires=' + dtExpiry + ';';
	document.cookie = curCookie;
	}
	
//get cookie value
function getCookie(name) {
	var dc = document.cookie;
	var prefix = name + "=";
	var begin = dc.indexOf("; " + prefix);
	if (begin == - 1) {
		begin = dc.indexOf(prefix);
		if (begin != 0) return null;
		}
	else begin += 2;
	var end = document.cookie.indexOf(";", begin);
	if (end == - 1) end = dc.length;
	return unescape(dc.substring(begin + prefix.length, end));
	}

// Open New Pop Up Window Function
function openWindow(url, width, height, name, resize, scroll, addlocaltime, returnWindow) {
	if(addlocaltime == undefined || addlocaltime == null) addlocaltime = true;
	if(returnWindow == undefined || returnWindow == null) returnWindow = false;
	winStats = 'toolbar=no,location=no,directories=no,menubar=no,';
	winStats += 'width=' + width + ',height=' + height + ',';
	if (resize == 1) {
		winStats += 'resizable=yes,' }
	else {
		winStats += 'resizable=no,' }
	if (scroll == 1) {
		winStats += 'scrollbars=yes' }
	else {
		winStats += 'scrollbars=no' }
	if (name == "interim") {
		windowleft = 10;
		 windowtop = 25 }
	else {
		windowleft = 10;
		 windowtop = 25 }
	if (navigator.appName.indexOf("Microsoft") >= 0) {
		winStats += ',left=' + windowleft + ',top=' + windowtop }
	else {
		winStats += ',screenX=' + windowleft + ',screenY=' + windowtop }
	// tack on local time and local timezone offset as well..
	var sURLUpdate = "";
	if(addlocaltime) {
		var theDt = new Date();
		var sURLUpdate = "ltms=" + theDt.getTime() + "&ltzo=" + theDt.getTimezoneOffset();
		var sUrl = new String(url);
		if(sUrl.indexOf("?") >= 0) {
			sURLUpdate = "&" + sURLUpdate;
			}
		else {
			sURLUpdate = "?" + sURLUpdate;
			}
		}
	// update URL with time data..
	url = url + sURLUpdate;
	floater = window.open(url, name, winStats);
	if(returnWindow) return floater;
	}
	
	
// more generic popup window
function openMyWindow(URL) {
	day = new Date();
	id = day.getTime();
	eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=1,scrollbars=1,location=1,statusbar=1,menubar=1,resizable=1,width=800,height=600,left = 240,top = 180');");
	}

// get data from the querystring..
function getParameter ( queryString, parameterName ) {
	// Add "=" to the parameter name (i.e. parameterName=value)
	var parameterName = parameterName + "=";
	if ( queryString.length > 0 ) {
		// Find the beginning of the string
		begin = queryString.indexOf ( parameterName );
		// If the parameter name is not found, skip it, otherwise return the value
		if ( begin != - 1 ) {
			// Add the length (integer) to the beginning
			begin += parameterName.length;
			// Multiple parameters are separated by the "&" sign
			end = queryString.indexOf ( "&" , begin );
			if ( end == - 1 ) {
				end = queryString.length }
			// Return the string
			return unescape ( queryString.substring ( begin, end ) );
			}
		}
	// Return "null" if no parameter has been found
	return "null";
	}



// HTML Encode a string
function HtmlEncode(sender)
{
	 // less-thans (<)
	 sender.value = sender.value.replace(/\</g, '');
	 // greater-thans (>)
	 sender.value = sender.value.replace(/\>/g, '');
	 }

function RecordSCforTTRestProfile() {
	try {
		var queryStr = window.top.location.search;
		//verify if this is a top ten restaurant and profile is viewed from DC Start or landing.
		var sTopTenVal = getParameter(queryStr, "ttr");
		if(sTopTenVal == "1") {
			var oSCObj = s_gi(s_account);
			if(oSCObj) {
				oSCObj.linkTrackVars = 'None';
				oSCObj.linkTrackEvents = 'None';
				//verify if referring page name is startpage, and record event25.
				var sPageName = document.referrer;
				if(sPageName != null && sPageName.length > 0) {
					sPageName = sPageName.toLowerCase();
					if(sPageName.indexOf("start.aspx") > - 1) {
						oSCObj.linkTrackVars = 'events';
						oSCObj.linkTrackEvents = 'event25';
						oSCObj.events = 'event25';
						}
					}
				oSCObj.tl(true, 'o', 'DCprofilelink');
				}
			}
		}
	catch(e) {
		}
	}
	
function ottrack(smsg, scode) {
	try {
		var http_request = null;
		var sPage = document.location.pathname;
		var sQueryString = document.location.search;
		if(scode == null || scode == undefined) scode = '';
		smsg = encodeURI(smsg);
		scode = encodeURI(scode);
		sPage = encodeURI(sPage);
		sUrl = '/httphandlers/jl.ashx?msg=' + smsg + '&fc=' + scode + '&rp=' + sPage + sQueryString;
		// branch for native XMLHttpRequest object
		if (window.XMLHttpRequest) {
			http_request = new XMLHttpRequest();
			}
		else if (window.ActiveXObject) // branch for IE/Windows ActiveX version
		{
			http_request = new ActiveXObject("Microsoft.XMLHTTP");
			}
		if (http_request != null) {
			http_request.open("GET", sUrl, true);
			http_request.send(null);
			}
		}
	catch(ex) {
		}
	}
	
// Is valid Credit Card
function isValidCreditCard(type, ccnum) {
	// akash: do a case insensitive match..
	type = type.toLowerCase();
	if (type == "visa") {
		// Visa: length 16, prefix 4, dashes optional.
		var re = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
		}
	else if (type == "mastercard") {
		// MasterCard: length 16, prefix 51-55, dashes optional.
		var re = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
		//alert("here");
		}
	else if (type == "discover") {
		// Discover: length 16, prefix 6011, dashes optional.
		var re = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
		}
	else if (type == "american express" || type == "amex") {
		// American Express: length 15, prefix 34 or 37.
		var re = /^3[4,7]\d{13}$/;
		}
	else if (type == "diners club") {
		// Diners: length 14, prefix 30, 36, or 38.
		var re = /^3[0,6,8]\d{12}$/;
		}
	else if (type == "carte blanche") {
		// Carte Blanche: Same as Diners Club.
		var re = /^3[0,6,8]\d{12}$/;
		}
	else if (type == "jcb") {
		// JCB: length 16, prefix 3, dashes optional.
		var re = /^3\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
		}
	else {
		// other cards, just do mod 10 check
		var re = null;
		}
	// other cards, just skip this check
	if (re != null) {
		if (!re.test(ccnum)) return false;
		}
	// Checksum ("Mod 10")
	// Add even digits in even length strings or odd digits in odd length strings.
	var checksum = 0;
	for (var i = (2 - (ccnum.length % 2)); i <= ccnum.length; i += 2) {
		checksum += parseInt(ccnum.charAt(i - 1));
		}
	// Analyze odd digits in even length strings or even digits in odd length strings.
	for (var i = (ccnum.length % 2) + 1; i < ccnum.length; i += 2) {
		var digit = parseInt(ccnum.charAt(i - 1)) * 2;
		if (digit < 10) {
			checksum += digit;
			}
		else {
			checksum += (digit - 9);
			}
		}
	if ((checksum % 10) == 0) return true;
	else return false;
	}
/* ================================================================
FUNCTION: isCreditCard(st)

INPUT: st - a string representing a credit card number

RETURNS: true, if the credit card number passes the Luhn Mod-10
test.
false, otherwise
================================================================ */
function isCreditCard(source, arguments) {
	// Encoding only works on cards with less than 19 digits
	st = arguments.Value;
	if (st.length > 19) arguments.IsValid = false;
	sum = 0;
	mul = 1;
	l = st.length;
	var othernumber = "";
	for (i = 0; i < l - 1; i++) {
		digit = st.substring(i, i + 1);
		othernumber = othernumber + digit }
	for (i = 0; i < l; i++) {
		digit = st.substring(l - i - 1, l - i);
		tproduct = parseInt(digit , 10) * mul;
		if (tproduct >= 10) sum += (tproduct % 10) + 1;
		else sum += tproduct;
		if (mul == 1) mul++;
		else mul--;
		}
	// Uncomment the following line to help create credit card numbers
	// 1. Create a dummy number with a 0 as the last digit
	// 2. Examine the sum written out
	// 3. Replace the last digit with the difference between the sum and
	// the next multiple of 10.
	// document.writeln("<BR>Sum = ",sum,"<BR>");
	lastdigit = 10 - (sum % 10);
	othernumber = othernumber + "" + lastdigit //othernumber = left(othernumber,l-1)
	//othernumber.substring(l-1,l) = 0;
	if (lastdigit != "10") {
		document.f1.anothernumber.value = othernumber;
		}
	//alert("Sum = " + sum + ":" + othernumber.substring(l-1,l));
	if ((sum % 10) == 0) arguments.IsValid = true;
	else arguments.IsValid = false;
	}
// END FUNCTION isCreditCard()


function AutoTabForward(oFromTextBox, nTriggerLen, oToTextBox) {
	if (oFromTextBox.value.length >= nTriggerLen) {
		//alert(oFromTextBox.value.length);
		oToTextBox.focus();
		}
	}
	
function PasswordLengthValid(source, arguments) {
	var sPassword = arguments.Value;
	if (sPassword.length >= 6) arguments.IsValid = true;
	else arguments.IsValid = false;
	}
function Phone3NumLengthValid(source, arguments) {
	var sValue = arguments.Value;
	if (sValue.length >= 3) if (isNumber(sValue)) arguments.IsValid = true;
	else arguments.IsValid = false;
	else arguments.IsValid = false;
	}
	
function Phone4NumLengthValid(source, arguments) {
	var sValue = arguments.Value;
	if (sValue.length >= 4) if (isNumber(sValue)) arguments.IsValid = true;
	else arguments.IsValid = false;
	else arguments.IsValid = false;
	}
	
function isNumber(nValue) {
	nValue = jsTrim(nValue);
	var anum = /(^\d+$)|(^\d+\.\d+$)/;
	if (anum.test(nValue)) {
		testresult = true }
	else {
		testresult = false }
	return (testresult)}
function jsTrim(strInput) {
	var strResult;
	var objRegex = new RegExp("(^\\s+)|(\\s+$)");
	strResult = strInput.replace(objRegex, "");
	return(strResult);
	}
	
function VerifyDate(nMonth, nDay, nYear) {
	var sDate = nMonth + "/" + nDay + "/" + nYear;
	var dDate = new Date(sDate);
	var nMonth2 = dDate.getMonth() + 1;
	if (nMonth2 == nMonth) return true;
	else return false;
	}

/* ================================================================
BEGIN START PAGE SEARCH MODULE FUNCTIONS
=================================================================*/

function check_boxes(state) {
	for (i = 0; i < document.SearchForm.elements.length; i++) {
		if (document.SearchForm.elements[i].type == 'checkbox') document.SearchForm.elements[i].checked = state;
		};
	}
	
function clearRestList() {
	var rbox = document.SearchForm.SearchNav_cboRestaurantList;
	var ftxt = document.SearchForm.SearchNav_theRestFinder;
	var hdnAutoFillDefault = document.getElementById("SearchNav_hdnAutoFillDefaultValue");
	if(rbox != null) rbox.selectedIndex = 0;
	if(ftxt != null) ftxt.value = hdnAutoFillDefault.value;
	}
	
function clearRegionList() {
	var ctlCuisine = document.getElementById("SearchNav_cboNeighborhoods");
	var ctlNHoods = document.getElementById("SearchNav_cboCuisine");
	if(ctlCuisine != null) ctlCuisine.selectedIndex = 0;
	if(ctlNHoods != null) ctlNHoods.selectedIndex = 0;
	}
	
function setAllRests(state) {
	if (state == true) document.SearchForm.SearchNav_cboRestaurantList.selectedIndex = 0;
	else {
		if (document.SearchForm.SearchNav_cboRestaurantList.selectedIndex == 0) document.SearchForm.SearchNav_cboRestaurantList.selectedIndex = 0;
		};
	}
	
function popr(name, id) {
	var rbox = document.SearchForm.SearchNav_cboNeighborhoods;
	rbox.options[rbox.options.length] = new Option(name, id);
	}
function pops(name, id) {
	var sbox = document.SearchForm.SearchNav_cboRestaurantList;
	if(sbox == null) return;
	sbox.options[sbox.options.length] = new Option(name, id);
	}
function popc(name, id) {
	var cbox = document.SearchForm.SearchNav_cboCuisine;
	cbox.options[cbox.options.length] = new Option(name, id);
	}
function ClearAutoFillRestSearch() {
	var txtAutoFill = document.getElementById("SearchNav_theRestFinder");
	var hdnAutoFillDefault = document.getElementById("SearchNav_hdnAutoFillDefaultValue");
	if (txtAutoFill == null) return;
	if(txtAutoFill.value == hdnAutoFillDefault.value) {
		txtAutoFill.value = '';
		}
	//clear cuisine and neighborhood selection.
	clearRegionList();
	}
function ValidateSearch() {
	var ctlCuisine = document.getElementById("SearchNav_cboNeighborhoods");
	var ctlNHoods = document.getElementById("SearchNav_cboCuisine");
	var ctlRestList = document.getElementById("SearchNav_cboRestaurantList");
	var txtAutoFill = document.getElementById("SearchNav_theRestFinder");
	var ctlRegion = document.getElementById("SearchNav_cboRegion");
	var hdnNoSelectError = document.getElementById("SearchNav_hdnJSSelectNoneError");
	var hdnAutoFillDefault = document.getElementById("SearchNav_hdnAutoFillDefaultValue");
	var bValid = true;
	if(ctlRegion.selectedIndex == 0 && ctlCuisine.disabled == true && ctlNHoods.disabled == true) {
		if(ctlRestList != null && txtAutoFill == null) {
			if(ctlRestList.value == "") bValid = false;
			}
		else if (ctlRestList == null && txtAutoFill != null) {
			if(txtAutoFill.value == hdnAutoFillDefault.value || jsTrim(txtAutoFill.value) == "") bValid = false;
			}
		}
	if(!bValid) {
		alert(hdnNoSelectError.value);
		return false;
		}
	return true;
	}
function RemoveNoRegChoice(ctlRegion) {
	//if a valid region is selected then remove "Select a Location" and Divider options,.
	var cboLength = ctlRegion.length;
	for(var i = 0; i < cboLength; i++) {
		if(!isNumber(ctlRegion.options[i].value)) {
			ctlRegion.remove(i);
			//reset region combo length
			cboLength = ctlRegion.length;
			//reset the counter
			i--;
			}
		}
	}
function SetSearchControls() {
	//set region dropdown
	try {
		var cboRegion = document.getElementById("SearchNav_cboRegion");
		var hdnReg = document.getElementById("hdnSelectedRegionID");
		//var sQSMetro = ReadMetroQS();
		//see if the last visited region is available in hidden value
		if (hdnReg.value != "" && hdnReg.value > 0) {
			cboRegion.value = hdnReg.value;
			}
		//reset neighborhood and cuisines
		setOptions("SearchNav_cboRegion");
		//set autofill dropdown to default value.
		var txtAutoFill = document.getElementById("SearchNav_theRestFinder");
		var hdnAutoFillDefault = document.getElementById("SearchNav_hdnAutoFillDefaultValue");
		var ctlRestList = document.getElementById("SearchNav_cboRestaurantList");
		if(ctlRestList != null && txtAutoFill == null) ctlRestList.selectedIndex = 0;
		else if (ctlRestList == null && txtAutoFill != null) txtAutoFill.value = hdnAutoFillDefault.value }
	catch(e) {
		}
	}
/* ================================================================
END START PAGE SEARCH MODULE FUNCTIONS
=================================================================*/

/* ================================================================
BEGIN DATE CONTROL FUNCTIONS
=================================================================*/

function GetDateString(cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM) {
	var nMonthSelectedIndex = cboMonth.selectedIndex;
	var nDaySelectedIndex = cboDay.selectedIndex;
	var nYearSelectedIndex = cboYear.selectedIndex;
	var nTimeSelectedIndex = cboHour.selectedIndex;
	var nMinuteSelectedIndex = cboMinute.selectedIndex;
	var nAMPMSelectedIndex = cboAMPM.selectedIndex;
	var sMonth = cboMonth.options[nMonthSelectedIndex].value;
	var sDay = cboDay.options[nDaySelectedIndex].value;
	var sYear = cboYear.options[nYearSelectedIndex].value;
	var sTime = cboHour.options[nTimeSelectedIndex].value;
	var sMinute = cboMinute.options[nMinuteSelectedIndex].value;
	var sAMPM = cboAMPM.options[nAMPMSelectedIndex].value;
	var Time_array = sTime.split(":");
	var sHour = Time_array[0];
	if ((sAMPM == "PM") && (sHour != 12)) {
		sHour = parseInt(sHour) + 12;
		}
	if ((sAMPM == "AM") && (sHour == 12)) {
		sHour = parseInt(sHour) - 12;
		}
	var dResoDate = new Date(sYear, nMonthSelectedIndex, sDay, sHour, sMinute);
	return dResoDate;
	}
// The promo page might be hiding its combo values in some cases
// in such an event we want to get the date from the literal that is displaying
function GetDateStringPromo(cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM, dateDisp) {
	var sResoDate = "";
	var sMonth = "";
	var sDay = "";
	var sYear = "";
	if(cboMonth != null) {
		var nMonthSelectedIndex = cboMonth.selectedIndex;
		var nDaySelectedIndex = cboDay.selectedIndex;
		var nYearSelectedIndex = cboYear.selectedIndex;
		sMonth = cboMonth.options[nMonthSelectedIndex].value;
		sDay = cboDay.options[nDaySelectedIndex].value;
		sYear = cboYear.options[nYearSelectedIndex].value;
		}
	else {
		// extract date from literal..
		var theDate = new Date(dateDisp.innerText);
		sMonth = (theDate.getMonth() + 1);
		sDay = theDate.getDate();
		sYear = theDate.getFullYear();
		}
	// tack on the time part..
	var nTimeSelectedIndex = cboHour.selectedIndex;
	var nMinuteSelectedIndex = cboMinute.selectedIndex;
	var nAMPMSelectedIndex = cboAMPM.selectedIndex;
	var sHour = cboHour.options[nTimeSelectedIndex].value;
	var sMinute = cboMinute.options[nMinuteSelectedIndex].value;
	var sAMPM = cboAMPM.options[nAMPMSelectedIndex].value;
	if ((sAMPM == "PM") && (sHour != 12)) {
		sHour += 12 }
	if ((sAMPM == "AM") && (sHour == 12)) {
		sHour -= 12 }
	var dResoDate = new Date(sYear, sMonth, sDay, sHour, sMinute);
	return dResoDate;
	}
function IsTimeInPast(sResoDate, sMetroAreaDateTime) {
	var dResoDate = new Date(sResoDate);
	var dRestaurantDateTime = new Date(sMetroAreaDateTime); 
	if (dResoDate.getTime() > dRestaurantDateTime.getTime()) {
		dResoDate.setMinutes(dResoDate.getMinutes() - 5);
		if (dResoDate.getTime() > dRestaurantDateTime.getTime()) return true;
		else {
			alert('You must make reservations at least 5 minutes in advance!\r\nPlease change your search criteria and submit another request.');
			return false;
			}
		}
	else {
		var agree = confirm('You have entered a date/time that has passed.\r\nDo you wish to continue?');
		if (agree) return true;
		else return false;
		}
	}
function CheckDate ( cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM, sMetroAreaDateTime ) {
	var sResoDate = GetDateString(cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM);
	return IsTimeInPast(sResoDate, sMetroAreaDateTime);
	}
// Called from Promo pages - special case this so that if the combo boxes have
// bogus values - we can extract the date from the literal that displays the date..
function CheckDatePromo(cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM, sMetroAreaDateTime, dateDisp) {
	var sResoDate = GetDateStringPromo(cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM, dateDisp);
	return IsTimeInPast(sResoDate, sMetroAreaDateTime);
	}
function FixDate ( cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM, sMetroAreaDateTime ) {
	var now = new Date();
	var evening = 0;
	var dResoDate = GetDateString(cboMonth, cboDay, cboYear, cboHour, cboMinute, cboAMPM);
	var dRestaurantDateTime = new Date(sMetroAreaDateTime);
	var h = dRestaurantDateTime.getHours();
	var m = dRestaurantDateTime.getMinutes();
	var nearhour = 19;
	var nearminute = 0 // for defaulting to ":30"
	var closestTime = (dRestaurantDateTime.getTime() + (15 * 60000)) //15 minutes in advance...
	var nearest = new Date(closestTime);
	nearhour = nearest.getHours() //alert(nearhour)
	if (dResoDate < dRestaurantDateTime) {
		if (dRestaurantDateTime.getFullYear() > dResoDate.getFullYear()) {
			cboYear.selectedIndex = cboYear.selectedIndex + 1;
			}
		else if (dRestaurantDateTime.getMonth() > dResoDate.getMonth()) {
			cboMonth.selectedIndex = cboMonth.selectedIndex + 1;
			}
		else if (dRestaurantDateTime.getDate() > dResoDate.getDate()) {
			cboDay.selectedIndex = cboDay.selectedIndex + 1;
			}
		else {
			if (nearest.getHours() < 19) {
				nearhour = 19;
				nearminute = 0;
				}
			else {
				nearminute = nearest.getMinutes();
				if (nearminute > 45) {
					nearminute = 0;
					nearhour = nearhour + 1 }
				else if (nearminute > 30) {
					nearminute = 3; }
				else if (nearminute > 15) {
					nearminute = 2; }
				else {
					nearminute = 1; }
				}
			if (nearhour > 12) {
				nearhour = nearhour - 12;
				evening = 1; }
			if (nearhour == 12) {
			    evening = 1; }
			if (nearhour == 0) {
				nearhour = 12;
				evening = 0;
				}
			cboMinute.selectedIndex = nearminute;
			cboHour.selectedIndex = nearhour - 1;
			cboAMPM.selectedIndex = evening;
			}
		}
	}
function clock(txtHidServerDateTime) {
	if (!document.layers && !document.all) return;
	var sStartDateTime = txtHidServerDateTime.value;
	var digital = new Date(sStartDateTime);
	var seconds = digital.getSeconds();
	digital.setSeconds(seconds + 1);
	var sClockCall; 
	if (document.layers) {
		value.txtHidServerDateTime = digital.toString();
		sClockCall = "clock(document.layers." + txtHidServerDateTime.id + ")";
		}
	else if (document.all) {
		txtHidServerDateTime.value = digital.toString();
		sClockCall = "clock(document.all." + txtHidServerDateTime.id + ")";
		}
	//alert(sClockCall);
	setTimeout(sClockCall, 1000);
	}
	
/* ================================================================
END DATE CONTROL FUNCTIONS
=================================================================*/

// Ported from the LatLonCalculator c# class
var LatLonCalculator = {
	DEGREE_LATITUDE_MILES: 69.055,
	EARTH_RADIUS_MILES: 3963.190590429304,
	PI_DIV_BY_180: Math.PI/180,
	MILES_PER_FOOT: 0.000189393939,
	
	CalculateDistanceInMiles: function(dLat1, dLon1, dLat2, dLon2)
	{
		var dLat = this.DegreeToRadian(dLat2 - dLat1);
		var dLon = this.DegreeToRadian(dLon2 - dLon1);
		var dA = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
			Math.cos(this.DegreeToRadian(dLat1)) *
			Math.cos(this.DegreeToRadian(dLat2)) *
			Math.sin(dLon / 2) * Math.sin(dLon / 2);
		var dC = 2 * Math.atan2(Math.sqrt(dA), Math.sqrt(1 - dA));
		var dDistance = this.EARTH_RADIUS_MILES * dC;
		return dDistance;
	},		
	DegreeToRadian: function(nAngle) 
	{
		return Math.PI * nAngle / 180.0;
	},
	RadianToDegree: function(nAngle) 
	{
		return nAngle * (180.0 / Math.PI);
	},
	MilesPerLonDegree: function(nLat1) {
		return this.PI_DIV_BY_180 * this.EARTH_RADIUS_MILES * 
			Math.cos(this.DegreeToRadian(nLat1));
	},
	LonDegreesPerMile: function(nLat1)
	{
		var nMilesPerDegree = this.MilesPerLonDegree(nLat1);

		//check for div by zero
		if(0.0 == nMilesPerDegree)
			return 0.0;

		return 1 / nMilesPerDegree;
	},
	GetLonDegreeSpan: function(nLat1, nMiles)
	{
		return nMiles * this.LonDegreesPerMile(nLat1);
	},
	GetLatDegreeSpan: function(nMiles)
	{
		return (1 / this.DEGREE_LATITUDE_MILES) * nMiles;
	}
}