var inputType='';
function setInputType(rtSt) {
	inputType=rtSt;
}
function doIt(show){
	var hide = document.getElementById('openTab').value;
	document.getElementById(hide+"Div").style.display = "none";
	document.getElementById(hide+"Tab").className = "tab";
	document.getElementById(show+"Div").style.display = "block";
	document.getElementById(show+"Tab").className = "tabActive";
	document.getElementById('openTab').value = show;
	var expDate=new Date();
	expDate.setDate(+9999);
	document.cookie="runnerMapMenuTab="+show+";expires="+expDate;
}
function enableDisable(what){
	var Nabled='n';
	if ($("cbx"+what).checked){
		$("cbx"+what).checked==true;
		Nabled='y';
	}else{
		$("cbx"+what).checked==false;
	}
	var expDate=new Date();
	expDate.setDate(+9999);
	document.cookie="runnerMap"+what+"="+Nabled+";expires="+expDate;
	if (what=='DblclkZoom'){
		if (Nabled=='y'){
			map.enableDoubleClickZoom();
		}else{
			map.disableDoubleClickZoom();
		}
	}else{
		if (what=='ScrollZoom'){
			if (Nabled=='y'){
				map.enableScrollWheelZoom();
			}else{
				map.disableScrollWheelZoom();
			}
		}
	}
}
function enableIt(){$('ctlRedo').className='ctlEnabled';}
function showSidebar(showIt){
//	setDivWidths(showIt); // showIt will be "true" or "false"
	if (showIt==false){
		$('leftColumn').style.display='none';
		$('divSidebarHide').className='sidebarHide';
		$('divSidebarShow').className='sidebarShow';
		$('mainContent').style.marginLeft='5px';
	}else{
		$('leftColumn').style.display='block';
		$('divSidebarShow').className='sidebarHide';
		$('divSidebarHide').className='sidebarShow';
		$('mainContent').style.marginLeft='195px';
	}
	if (initLoadDone)map.checkResize();
	var expDate=new Date();
	expDate.setDate(+9999);
	sidebarCookie='n';
	if (showIt==true)sidebarCookie='y';
	document.cookie="runnerMapSidebar="+sidebarCookie+";expires="+expDate;
}
function setDivWidths(sidebar){
	var divHeight,divWidth;
	var winSize=new getWindowSize();
	divHeight=((winSize.height)-30).toString();
	// following is necessary because of no practical cross-browser means of determining "left" when div is "right" pos'd
	if( ! $("inputTypeMsg").style.left ){
		$("inputTypeMsg").style.left=(winSize.width-150).toString()+"px";
	}
	if (sidebar==true) divWidth=((winSize.width)-230).toString();//divWidth=((winSize.width)-245).toString();
	else divWidth=((winSize.width)-50).toString();
	$("mainContent").style.width=divWidth+"px";
	$("mainContent").style.height=divHeight+"px";
	var numCols;
	if (divHeight<560) numCols=2;else numCols=1;
	buildActionBar(numCols);
	$("map").style.width=(divWidth-(numCols*50)).toString()+"px";
	$("map").style.height=divHeight+"px";
	moveInputHelpDiv();
	showSidebar(sidebar);
}

function moveInputHelpDiv(){
	var winSize=new getWindowSize();
	var inputTypeLeft=parseFloat($("inputTypeMsg").style.left,10);
//	var helpWid = parseFloat($("inputTypeHelp").style.width,10) + (2 * parseFloat($("inputTypeHelp").style.padding,10)) + (2 * parseFloat($("inputTypeHelp").style.border,10));
//  I hate making exceptions for IE (and Safari-on-Windows), but neither of them recognize "style.border" properly, so I'll just substitute a fixed amount
	var helpWid = parseFloat($("inputTypeHelp").style.width,10) + (2 * parseFloat($("inputTypeHelp").style.padding,10)) + 6;
	if(inputTypeLeft > helpWid){
		$("inputTypeHelp").style.left=(inputTypeLeft - helpWid).toString()+"px";
	}else{
//		var inputTypeWid = parseFloat($("inputTypeMsg").style.width,10) + (2 * parseFloat($("inputTypeMsg").style.padding,10)) + (2 * parseFloat($("inputTypeMsg").style.border,10));
//		See comment above
		var inputTypeWid = parseFloat($("inputTypeMsg").style.width,10) + (2 * parseFloat($("inputTypeMsg").style.padding,10)) + 6;
		$("inputTypeHelp").style.left=(inputTypeLeft + inputTypeWid).toString()+"px";
	}
}
function spot(point, distUnit, distTotal, elev, marker, lineSegment, distMarks, type, poly) {
	this.point=point;
	this.distUnit=distUnit;
	this.distTotal=distTotal;
	this.elev=elev ? elev : 0;
	this.marker=marker;
	this.lineSegment=lineSegment;
	this.distMarks=distMarks;
	this.type=type;
	this.poly=poly;
}

var userUserName;
var userNewUser;
var newUserL;
var newUserF;
var newUserPW;

function processLoginForm() {
	userUserName = document.forms.userInfoForm.userUserName.value;
	userNewUser = document.forms.userInfoForm.cbxNewUser.checked;
	if (userNewUser) {
		addNewUser();
		return;
	}
	var expDate=new Date();
	expDate.setDate(+9999);
	document.cookie="runnerMapUserName="+escape(userUserName)+";expires="+expDate;
	doMapOnLoad();
	showLogin();
}

var newUserAdded=0;
function addNewUser() {
	var fetch = new google.maps.XmlHttp.create();
	if (fetch) {
		var newUser = document.forms.userInfoForm.userUserName.value;
		var newUserF = document.forms.userInfoForm.newUserF.value;
		var newUserL = document.forms.userInfoForm.newUserL.value;
		var newUserPW = document.forms.userInfoForm.newUserPW.value;
		document.forms.userInfoForm.cbxNewUser.checked=false;
		showHideNew();
		fetch.open("GET", "addNewUser.php?rtUID="+newUser+"&newUserF="+newUserF+"&newUserL="+newUserL+"&newUserPW="+newUserPW, true);
		fetch.onreadystatechange = 		function () {
					if (fetch.readyState == 4) {
						var xmlDoc = fetch.responseXML;
						var responses = xmlDoc.documentElement.getElementsByTagName("newuser");
						newUserAdded = responses[0].getAttribute("success");
						if(newUserAdded){
							var expDate=new Date();
							expDate.setDate(+9999);
							document.cookie="runnerMapUserName="+escape(newUser)+";expires="+expDate;
						}else{
							
						}
					}
		}
		fetch.send(null);
		setTimeout("if (newUserAdded==1)doMapOnLoad(); else alert('That user name already exists');",1000);
		return;
	}
}

function saveRoute() {
	var sending = new google.maps.XmlHttp.create();
	if(sending) {
		document.getElementById("spanOut").innerHTML = "Sending Information...";
		sending.open("POST", "saveRoute.php", true);
		sending.onreadystatechange = 
						function() {
							if(sending.readyState == 4)	{
								if(sending.status == 200)	{
								 var strText = sending.responseText;
								 document.getElementById("spanOut").innerHTML = strText;  
								} else	{
								 alert("There was a problem retrieving the XML data:\n" + sending.statusText);
								}		
							}
						}
		sending.setRequestHeader("Content-Type", "text/xml");
		var routeUID = document.getElementById("loggedInAs").innerHTML;//alert (routeUID);
		ae_prompt('Enter Route Name', 'My New Route', function(routeName){
									var xmlBody = "<markers rtUID='"+routeUID+"' rtName='"+routeName+"'>\n";
									for (var i=0; i<xx; i++) {
										xmlBody += "<marker mid=\"" + i + "\" lat=\"" + pointArray[i].point.lat() + "\" lng=\"" + pointArray[i].point.lng() + "\" elev=\"" + pointArray[i].elev + "\" type=\"" + pointArray[i].type + "\" poly=\"" + pointArray[i].poly + "\"  />";
									}
									xmlBody += "</markers>";//alert(xmlBody);return;
									sending.send("<?xml version='1.0' encoding='UTF-8'?>" + xmlBody);
									setTimeout("fetchMyRoutes()",500);
																													 }
																													 );
	}
}
function cancelKML(){
	var cancelKML = new google.maps.XmlHttp.create();
	if(cancelKML) {
		var fName=$('exportKmlFileName').value;
		cancelKML.open("GET", "deleteKML.php?fName="+fName, true);
		cancelKML.onreadystatechange = 
						function() {
							if(cancelKML.readyState == 4)	{
								if(cancelKML.status == 200)	{
								 alert(cancelKML.responseText);
								} else	{
								 alert("There was a problem.\n\n" + cancelKML.statusText);
								}		
							}
						}
		cancelKML.send(null);
	}
}
function exportKML() {
	var exportKML = new google.maps.XmlHttp.create();
	if(exportKML) {
		exportKML.open("POST", "exportKML.php", true);
		exportKML.onreadystatechange = 
						function() {
							if(exportKML.readyState == 4)	{
								if(exportKML.status == 200)	{
								 $('exportKmlFileName').value=exportKML.responseText;
								 $('exportKmlDiv').style.zIndex='110';
								 fade('exportKmlDiv','in');
								} else	{
								 alert("There was a problem retrieving the XML data:\n" + exportKML.statusText);
								}		
							}
						}
						var xmlBody="";
						xmlBody+="<kml xmlns=\"http://earth.google.com/kml/2.0\">\n";
						xmlBody+=" <Document>\n";
						xmlBody+="  <Style id=\"startPoint\">\n";
						xmlBody+="   <IconStyle>\n";
						xmlBody+="    <scale>.33</scale>\n";
						xmlBody+="    <hotSpot x=\"0.5\" y=\".09\" xunits=\"fraction\" yunits=\"fraction\" />\n";
						xmlBody+="    <Icon>\n";
						xmlBody+="     <href>http://www.webtonix.com/maps/ico/iconStart.png</href>\n";
						xmlBody+="    </Icon>\n";
						xmlBody+="   </IconStyle>\n";
						xmlBody+="   <LabelStyle>\n";
						xmlBody+="    <color>ffffffff</color>\n";
						xmlBody+="    <scale>0.7</scale>\n";
						xmlBody+="   </LabelStyle>\n";
						xmlBody+="  </Style>\n";
						xmlBody+="  <Style id=\"finishPoint\">\n";
						xmlBody+="   <IconStyle>\n";
						xmlBody+="    <scale>.33</scale>\n";
						xmlBody+="    <hotSpot x=\"0.5\" y=\".09\" xunits=\"fraction\" yunits=\"fraction\" />\n";
						xmlBody+="    <Icon>\n";
						xmlBody+="     <href>http://www.webtonix.com/maps/ico/iconStop.png</href>\n";
						xmlBody+="    </Icon>\n";
						xmlBody+="   </IconStyle>\n";
						xmlBody+="   <LabelStyle>\n";
						xmlBody+="    <color>ffffffff</color>\n";
						xmlBody+="    <scale>0.7</scale>\n";
						xmlBody+="   </LabelStyle>\n";
						xmlBody+="  </Style>\n";
						xmlBody+="  <Style id=\"mileMarker\">\n";
						xmlBody+="   <IconStyle>\n";
						xmlBody+="    <scale>.5</scale>\n";
						xmlBody+="    <hotSpot x=\"0.5\" y=\".09\" xunits=\"fraction\" yunits=\"fraction\" />\n";
						xmlBody+="    <Icon>\n";
						xmlBody+="     <href>http://chart.apis.google.com/chart?cht=mm&amp;chs=16x16&amp;chco=ffffffcc,00ff00cc,333333cc&amp;ext=.png</href>\n";
						xmlBody+="    </Icon>\n";
						xmlBody+="   </IconStyle>\n";
						xmlBody+="   <LabelStyle>\n";
						xmlBody+="    <color>ffffffff</color>\n";
						xmlBody+="    <scale>0.7</scale>\n";
						xmlBody+="   </LabelStyle>\n";
						xmlBody+="  </Style>\n";
						xmlBody+="  <Style id=\"kmMarker\">\n";
						xmlBody+="   <IconStyle>\n";
						xmlBody+="    <scale>.5</scale>\n";
						xmlBody+="    <hotSpot x=\"0.5\" y=\".09\" xunits=\"fraction\" yunits=\"fraction\" />\n";
						xmlBody+="    <Icon>\n";
						xmlBody+="     <href>http://chart.apis.google.com/chart?cht=mm&amp;chs=16x16&amp;chco=ffffffcc,ffff00cc,333333cc&amp;ext=.png</href>\n";
						xmlBody+="    </Icon>\n";
						xmlBody+="   </IconStyle>\n";
						xmlBody+="   <LabelStyle>\n";
						xmlBody+="    <color>ffffffff</color>\n";
						xmlBody+="    <scale>0.7</scale>\n";
						xmlBody+="   </LabelStyle>\n";
						xmlBody+="  </Style>\n";
						xmlBody+="  <name>WebtonixDotComRunnerMap</name>\n";
						xmlBody+="  <Folder>\n";
						xmlBody+="   <visibility>0</visibility>\n";
						xmlBody+="   <name>\n";
						xmlBody+="    <![CDATA[]]>\n";
						xmlBody+="   </name>\n";
						xmlBody+="   <description>\n";
						xmlBody+="    <![CDATA[]]>\n";
						xmlBody+="   </description>\n";
						xmlBody+="   <Placemark>\n";
						xmlBody+="    <name>Route</name>\n";
						xmlBody+="    <visibility>1</visibility>\n";
						xmlBody+="    <open>1</open>\n";
						xmlBody+="    <flyToView>1</flyToView>\n";
						xmlBody+="    <Style>\n";
						xmlBody+="     <LineStyle>\n";
						xmlBody+="      <color>ff0000cc</color>\n";
						xmlBody+="      <width>6</width>\n";
						xmlBody+="     </LineStyle>\n";
						xmlBody+="    </Style>\n";
						xmlBody+="    <LineString>\n";
						xmlBody+="     <extrude>1</extrude>\n";
						xmlBody+="     <tessellate>1</tessellate>\n";
						xmlBody+="     <altitudeMode>clampedToGround</altitudeMode>\n";
						xmlBody+="     <coordinates>\n";

									var distMarks=[];
									for (var i=0; i<xx; i++) {
										var poly=pointArray[i].poly;
										if(poly==null){}else{
											for (var j=0; j<poly.length; j++){
												xmlBody += poly[j].lng()+","+poly[j].lat() + "\n";
											}
											if(pointArray[i].distMarks[0]){
												var tmp=pointArray[i].distMarks;//alert(tmp.length);
												for (var dmk=0; dmk < tmp.length; dmk++){//alert(tmp[dmk].toSource());
													distMarks.push(tmp[dmk]);
												}
											}
										}
									}

						xmlBody+="     </coordinates>\n";
						xmlBody+="   </LineString>\n";
						xmlBody+="  </Placemark>\n";
						xmlBody+="  <Folder>\n";
						xmlBody+="   <visibility>0</visibility>\n";
						xmlBody+="   <name>Distance Markers</name>\n";

									var markerTitle, markerType;
									var expMile=new RegExp("Mile");
									var expKM=new RegExp("Kilometer");
									for (var k=0; k<distMarks.length; k++) {
										xmlBody+="   <Placemark>\n";
										markerTitle=distMarks[k].getTitle();
										if (expMile.test(markerTitle))markerType="mile";
										if (expKM.test(markerTitle))markerType="km";
										xmlBody+="    <name>"+distMarks[k].getTitle()+"</name>\n";
										xmlBody+="     <styleUrl>#"+markerType+"Marker</styleUrl>\n";
										xmlBody+="     <Point>\n";
										var p=distMarks[k].getPoint();
										xmlBody+="      <coordinates>"+roundDec(p.lng(),5).toString()+","+roundDec(p.lat(),5).toString()+",0</coordinates>\n";
										xmlBody+="     </Point>\n";
										xmlBody+="    </Placemark>\n";
									}

						xmlBody+="   </Folder>\n";

						xmlBody+="  <Folder>\n";
						xmlBody+="   <visibility>0</visibility>\n";
						xmlBody+="   <name>Start/Finish Markers</name>\n";

						xmlBody+="   <Placemark>\n";
						xmlBody+="    <name>Start</name>\n";
						xmlBody+="     <styleUrl>#startPoint</styleUrl>\n";
						xmlBody+="     <Point>\n";
						var startPt=pointArray[0].point;
						xmlBody+="      <coordinates>"+startPt.lng().toString()+","+startPt.lat().toString()+",0</coordinates>\n";
						xmlBody+="     </Point>\n";
						xmlBody+="    </Placemark>\n";

						xmlBody+="   <Placemark>\n";
						xmlBody+="    <name>Finish</name>\n";
						xmlBody+="     <styleUrl>#finishPoint</styleUrl>\n";
						xmlBody+="     <Point>\n";
						var finish=pointArray.length - 1;
						var finishPt=pointArray[finish].point;
						xmlBody+="      <coordinates>"+finishPt.lng().toString()+","+finishPt.lat().toString()+",0</coordinates>\n";
						xmlBody+="     </Point>\n";
						xmlBody+="    </Placemark>\n";

						xmlBody+="   </Folder>\n";

						xmlBody+="  </Folder>\n";
						xmlBody+=" </Document>\n";
						xmlBody+="</kml>\n";
									exportKML.send(xmlBody);
	}
} 

//following script code is from http://www.anyexample.com/webdev/javascript/ie7_javascript_prompt()_alternative.xml
// This is variable for storing callback function
var ae_cb = null;

// This is a main ae_prompt function
// it saves function callback 
// and sets up dialog
function ae_prompt(q, a, cb) {
	ae_cb = cb;
	$('aep_t').innerHTML = document.domain + ' question:';
	$('aep_prompt').innerHTML = q;
	$('aep_text').value = a;
	$('aep_ovrl').style.display = $('aep_ww').style.display = '';
	$('aep_text').focus();
	$('aep_text').select();
}
 
// This function is called when user presses OK(m=0) or Cancel(m=1) button
// in the dialog. You should not call this function directly.
function ae_clk(m) {
	// hide dialog layers 
	$('aep_ovrl').style.display = $('aep_ww').style.display = 'none';
	if (!m)  
		ae_cb(null);  // user pressed cancel, call callback with null
	else
		ae_cb($('aep_text').value); // user pressed OK 
}
// preceding script code is from http://www.anyexample.com/webdev/javascript/ie7_javascript_prompt()_alternative.xml ...
// now on to more of my own

function fetchOneRoute(parmRoute) {
	var fetch = new google.maps.XmlHttp.create();
	if (fetch) {
		pointArray=[];
		document.getElementById('plzWait').style.display="block";
		document.getElementById('plzWait').style.zIndex=1000;
		if (parmRoute)	fetch.open("GET", "getRoute.php?rtNum="+parmRoute, true);
		else {
			var routeUID = $("loggedInAs").innerHTML;
			var routeName = $("routeSelector").value;
			fetch.open("GET", "getRoute.php?rtUID="+routeUID+"&rtName="+routeName, true);
		}
		fetch.onreadystatechange = function() {
						if (fetch.readyState == 4) {
							var xmlDoc = fetch.responseXML;
							var route=xmlDoc.documentElement.getElementsByTagName("route");
							var routeNumber=route[0].getAttribute("routeNumber");
							var routeName=route[0].getAttribute("routeName");
							var markers = xmlDoc.documentElement.getElementsByTagName("marker");
							for (var i=0; i<markers.length; i++) {
								var point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")),
																				parseFloat(markers[i].getAttribute("lng")));
								var elev = markers[i].getAttribute("elev");
								var poly;
								if (i==0) poly=null;
								else poly = parsePoly(markers[i].getAttribute("poly"));
								var type = markers[i].getAttribute("type");
								pointArray[i]=new spot();
								pointArray[i].point=point;
								pointArray[i].poly=poly;
								pointArray[i].type=type;
								pointArray[i].elev=elev;
								if (i==0){
									pointArray[i].distUnit=0;
									pointArray[i].distTotal=0;
								}else{
									var wkPolyLine=new google.maps.Polyline(pointArray[i].poly);
									var wkPolyLen=wkPolyLine.getLength();
									pointArray[i].distUnit=wkPolyLen;
									pointArray[i].distTotal=pointArray[i-1].distTotal+pointArray[i].distUnit;
								}
							}
							xx=i;
							rebuildMap();
							document.getElementById('plzWait').style.display="none";
							document.getElementById('plzWait').style.zIndex=-10;
							if (routeName){
								dltAncr=document.createElement('a');
								dltAncr.setAttribute('href','javascript:deleteRoute('+routeNumber+',"'+escape(routeName)+'")');
								dltAncrText=document.createTextNode('Delete "'+routeName+'"');
								dltAncr.appendChild(dltAncrText);
								var rdDiv=$('routeDelete');
								while (rdDiv.hasChildNodes()){
									rdDiv.removeChild(rdDiv.childNodes[0]);
								}
								$('routeDelete').appendChild(dltAncr);
							}
							else $('routeDelete').innerHTML="&nbsp;";
						}
					}
		fetch.send(null);
	}
}

function deleteRoute(rtNum, rtName) {
	if (confirm("Are you sure you want to delete \""+rtName+"\"?")) {
		var dlet = new google.maps.XmlHttp.create();
		if (dlet) {
			dlet.open("GET", "deleteRoute.php?rtNumber="+rtNum+"&rtName="+rtName, true);
			dlet.onreadystatechange = function() {
													if (dlet.readyState == 4) {
														var resp = dlet.responseText;//alert(resp);
														$('routeDelete').innerHTML=resp;
														setTimeout("fetchMyRoutes()",500);
													}
			}
			dlet.send(null);
		}
	}
}

function parsePoly(str){
	var wkArray=[];
	var tmp=0;
	var totLen=str.length;
	var aa=0, ab=0, ba=0, bb=0;
	while(aa<totLen){
		aa=str.indexOf("(",bb)+1;
		if (aa>0){
			ab=str.indexOf(",",aa);
			ba=str.indexOf(",",ab)+1;
			bb=str.indexOf(")",ba);
			wkArray[tmp]=new google.maps.LatLng(parseFloat(str.substr(aa,ab-aa)),parseFloat(str.substr(ba,bb-ba)));
			tmp++;
		}else{
			return wkArray;
		}
	}
}

function setStart(yn) {
	if (yn==1){
		var newStart = map.getCenter();
		var newStartLat = roundDec(newStart.lat(),5);
		var newStartLng = roundDec(newStart.lng(),5);
		var newStartElev = pointArray[0].elev;
		var zoomLvl = map.getZoom();
		var expDate=new Date();
		expDate.setDate(+9999);
		var sending = new google.maps.XmlHttp.create();
		if(sending)
		{
			sending.open("POST", "saveStart.php", true);
			sending.onreadystatechange = 
								function(){
									if(sending.readyState == 4)	{
										if(sending.status == 200)	{
										 var strText = sending.responseText;
										 document.getElementById("spanOut").innerHTML = strText;  
										} else {
										 alert("There was a problem retrieving the XML data:\n" + sending.statusText);
										}		
									}
								}
			sending.setRequestHeader("Content-Type", "text/xml");
			var UID = document.getElementById("loggedInAs").innerHTML;
			var xmlBody = "<markers UID='"+UID+"'>\n";
			xmlBody += "<marker lat=\"" + newStartLat + "\" lng=\"" + newStartLng + "\" elev=\"0.0\"  />";
			xmlBody += "</markers>";
			sending.send("<?xml version='1.0' encoding='UTF-8'?>" + xmlBody);
		}
		document.cookie="runnerMapUserName="+escape(userUserName)+";expires="+expDate;
	}
	fade('startPtMsg','out');
	return;
}

function getCookie(c_name) {
	if (document.cookie.length>0) 	{ 
		c_start=document.cookie.indexOf(c_name + "=");
		if (c_start!=-1) { 
			c_start=c_start + c_name.length+1 ;
			c_end=document.cookie.indexOf(";",c_start);
			if (c_end==-1) c_end=document.cookie.length;
			return unescape(document.cookie.substring(c_start,c_end));
		} 
	}
	return null;
}

function buildPointsList() {
	var pointTable="";
	pointTable+="<a href='javascript:rmvPointsList()'>Remove Points List</a>";
	pointTable+="<table id='pointTbl' border='1' cellpadding='1' cellspacing='0'><tbody>";
	pointTable+="<tr><th valign='top'>Pt#</th>";
	pointTable+="<td>lat</td>";
	pointTable+="<td>lng</td>";
	pointTable+="<td>uDst</td>";
	pointTable+="<td>tDst</td>";
	pointTable+="<td>Typ</td>";
	pointTable+="<td>Vrtxs</td></tr>";
	for (var i=0; i<xx; i++) {
		pointTable+="<tr><th valign='top'>";
		pointTable+=i.toString();
		pointTable+="</th><td valign='top'>";
		pointTable+=roundDec(pointArray[i].point.lat(),5).toString();
		pointTable+="</td><td valign='top'>";
		pointTable+=roundDec(pointArray[i].point.lng(),5).toString();
		pointTable+="</td><td valign='top'>";
		pointTable+=roundDec(pointArray[i].distUnit,5).toString();
		pointTable+="</td><td valign='top'>";
		pointTable+=roundDec(pointArray[i].distTotal,5).toString();
		pointTable+="</td><td valign='top'>";
		pointTable+=pointArray[i].type;
		pointTable+="</td><td valign='top'>";
		pointTable+=pointArray[i].poly;
		pointTable+="</td></tr>";
	}
	pointTable+="</tbody></table>";
	document.getElementById("msgPoints").innerHTML=pointTable;
	$("msgPoints").style.display="block";
}

function rmvPointsList() {
	document.getElementById("msgPoints").innerHTML="";
	$("msgPoints").style.display="none";
}

function updDistanceInfo(ptX){
	document.getElementById("msgNum").innerHTML = "Point # <span class='pointNum'>" + ptX +"</span>";
	document.getElementById("msgDistMiles").innerHTML = (distMiles == 0) ? '-' : roundDec(distMiles,3);
	document.getElementById("msgDistKMeters").innerHTML = (distKMeters == 0) ? '-' : roundDec(distKMeters,3);
	document.getElementById("msgTotalMiles").innerHTML = (totalDistMiles == 0) ? '-' : roundDec(totalDistMiles,3);
	document.getElementById("msgTotalKMeters").innerHTML = (totalDistMeters == 0) ? '-' : roundDec((totalDistMeters / 1000),3);
}

function undo() {
	xx--;
	var ptX=xx-1;
	distMiles=pointArray[ptX].distUnit/metersPerMile;
	distKMeters=pointArray[ptX].distUnit / 1000;
	totalDistMiles=pointArray[ptX].distTotal/metersPerMile;
	totalDistMeters=pointArray[ptX].distTotal ;
	updDistanceInfo(ptX);
	map.removeOverlay(pointArray[xx].marker);
	map.removeOverlay(pointArray[xx].lineSegment);
	var distMarks=[];distMarks=pointArray[xx].distMarks;
	for (var i=0;i<distMarks.length;i++){
		map.removeOverlay(distMarks[i]);
	}
	pointArray.pop();
	if (xx<2) disableBtn('Undo');
//	if($('divRedo').className=='ctlDisabled')enableBtn('Redo');
}

// Returns the bearing in degrees between two points.
// North = 0, East = 90, South = 180, West = 270.
function bearing( from, to ) {
	// See T. Vincenty, Survey Review, 23, No 176, p 88-93,1975.
	// Convert to radians.
	var lat1 = from.latRadians();
	var lng1 = from.lngRadians();
	var lat2 = to.latRadians();
	var lng2 = to.lngRadians();

	var degreesPerRadian = 180.00 / Math.PI;
	var radiansPerDegree = Math.PI / 180.00;
	
	// Compute the angle.
	var angle = - Math.atan2( Math.sin( lng1 - lng2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lng1 - lng2 ) );
	if ( angle < 0.0 )
		angle  += Math.PI * 2.0;
	
	// And convert result to degrees.
	angle = angle * degreesPerRadian;
	angle = roundDec(angle,1);
	return angle;
}

function compassBearing(brg) {
	return compassArray[Math.round((brg) / 22.5)];
}

function clearMap() {
	map.clearOverlays();
	xx=0;
	pointArray=[];
	document.getElementById("msgNum").innerHTML = "";
	document.getElementById("msgDistMiles").innerHTML = "";
	document.getElementById("msgTotalMiles").innerHTML = "";
	document.getElementById("msgDistKMeters").innerHTML = "";
	document.getElementById("msgTotalKMeters").innerHTML = "";
}

function getSelectedRadioValue(buttonGroup) {
   // returns the value of the selected radio button or "" if no button is selected
   var i = getSelectedRadio(buttonGroup);
   if (i == -1) {
      return "";
   } else {
      if (buttonGroup[i]) { // Make sure the button group is an array (not just one button)
         return buttonGroup[i].value;
      } else { // The button group is just the one button, and it is checked
         return buttonGroup.value;
      }
   }
} // Ends the "getSelectedRadioValue" function

function getSelectedRadio(buttonGroup) {
   // returns the array number of the selected radio button or -1 if no button is selected
   if (buttonGroup[0]) { // if the button group is an array (one button is not an array)
      for (var i=0; i<buttonGroup.length; i++) {
         if (buttonGroup[i].checked) {
            return i
         }
      }
   } else {
      if (buttonGroup.checked) { return 0; } // if the one button is checked, return zero
   }
   // if we get to this point, no radio button is selected
   return -1;
} // Ends the "getSelectedRadio" function

function roundDec(theNumber, sigDigs){	var tens = Math.pow(10,sigDigs);	return Math.round(theNumber*tens)/tens;	}

function fetchMyRoutes() {
	var fetch = new google.maps.XmlHttp.create();
	if (fetch) {
		var routeUID = document.getElementById("loggedInAs").innerHTML;
		fetch.open("GET", "fetchMyRoutes.php?rtUID="+routeUID, true);
		fetch.onreadystatechange = 
					function() {
						if (fetch.readyState == 4) {
							var xmlDoc = fetch.responseXML;
							var rtDiv=$('routeSelect');
							var routes = xmlDoc.documentElement.getElementsByTagName("route");

	var rtHTML="Saved Routes<br />";
	rtHTML+="<select id=\"routeSelector\" onchange=\"fetchOneRoute()\" disabled=\"disabled\"><br />";
	rtHTML+="<option value=\" \"> </option>";
	var route, i;
	for (i=0;i<routes.length;i++) {
		route = routes[i].getAttribute("name");
		rtHTML+="<option value=\""+route+"\">"+route+"</option>";
	}
	rtHTML+="</select>";
	rtDiv.innerHTML=rtHTML;
/*
			// This is how it's SUPPOSED to work, and it DOES work in all modern browsers
			// except the biggie (MSIE7 on XPSP2). Lowest common denominator is above
*/
/*
							while (rtDiv.hasChildNodes()){rtDiv.removeChild(rtDiv.childNodes[0]);}
//							var routes = xmlDoc.documentElement.getElementsByTagName("route");
							var rtText=document.createTextNode('Saved Routes');
//							$('routeSelect').appendChild(rtText);
							rtDiv.appendChild(rtText);
							var br = document.createElement('br');
//							$('routeSelect').appendChild(br);
							rtDiv.appendChild(br);
							var rtSelect=document.createElement('select');
							rtSelect.setAttribute('id','routeSelector');
							rtSelect.setAttribute('name','routeSelector');
							rtSelect.setAttribute('onchange','fetchOneRoute()');
							rtSelect.setAttribute('disabled','disabled');

							var option = document.createElement('option');
							var route = " ";
							option.setAttribute('value',route);
							var text = document.createTextNode(route);
							option.setAttribute('selected','selected');
							option.appendChild(text);
							rtSelect.appendChild(option);
							for (var i=0;i<routes.length;i++) {
								var option = document.createElement('option');
								var route = routes[i].getAttribute("name");
								option.setAttribute('value',route);
								var text = document.createTextNode(route);
								option.appendChild(text);
								rtSelect.appendChild(option);
							}
*/
							if (i>0) $('routeSelector').disabled='';
						}
					}
		fetch.send(null);
	}else{
		alert("Your browser does not support Ajax");
	}
}

function getArrow(brg) {
	switch (brg.toLowerCase()) {
		case "n":return nIcon;case"north":	return nIcon;case "nne":return nneIcon;case "ne":return neIcon;case "ene":return eneIcon;case "e":return eIcon;case "east":return eIcon;case "ese":return eseIcon;case "se":return seIcon;case "sse":return sseIcon;case "s":return sIcon;case "south":return sIcon;case "ssw":return sswIcon;case "sw":return swIcon;case "wsw":return wswIcon;case "w":return wIcon;case "west":return westIcon;case "wnw":return wnwIcon;case "nw":return nwIcon;case "nnw":return nnwIcon;case "blackdoticon":return blackDotIcon;
	}
}

function showLogin() {
	var p=($('userInfoFormDiv').style.zIndex);
	if (p < 1){
		fade('userInfoFormDiv','in');
		document.forms.userInfoForm.userUserName.focus();
		document.forms.userInfoForm.userUserName.select();
	}else{
		fade('userInfoFormDiv','out');
	}
}

function showHideNew() {
	document.forms.userInfoForm.newUserF.value="";
	document.forms.userInfoForm.newUserL.value="";
	document.forms.userInfoForm.newUserPW.value="";
	if (document.getElementById('cbxNewUser').checked) {
		document.getElementById('newUserOnly').style.display="block";
	}else{
		document.getElementById('newUserOnly').style.display="none";
	}
}

function showAddress(address) {
	var geocoder = new google.maps.ClientGeocoder();
	address = document.getElementById('inAddr').value;
  geocoder.getLatLng(
    address,
    function(point) {
      if (!point) {
        alert(address + " not found");
				return false;
      }else{
				clearMap();
				$('inAddr').value="";
				document.getElementById("msgNum").innerHTML = "Point # " + xx;
				drawStart(point);
        map.setCenter(point, 15);
				if($('loggedInAs').innerHTML=='AnonymousUser'){
				}else{
					fade('startPtMsg','in');
				}
				return true;
      }
    }
										 );
}

function getWindowSize(width,height) {
  if( typeof( window.innerWidth ) == 'number' ) {//Non-IE
    this.width = window.innerWidth;
    this.height = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {//IE 6+ in 'standards compliant mode'
    this.width = document.documentElement.clientWidth;
    this.height = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {//IE 4 compatible
    this.width = document.body.clientWidth;
    this.height = document.body.clientHeight;
  }
}

function displayInfo(index) {
	var myConnectAndReverseMsg="CONNECT and REVERSE from here";
	var myCloseMsg="CONTINUE from here back to start point";
	var myAddAfterMsg="ADD AFTER this point";
	var myAddBeforeMsg="ADD BEFORE this point";
	var myDeleteOneMsg="DELETE JUST this one";
	var myDeleteFromHereMsg="DELETE ALL from here";
	if (inputType=='straight')var linkDisplay="block";else var linkDisplay="none";
	/*
	var html = [new GInfoWindowTab("Actions", "<div style='font-size:x-small; white-space:nowrap;'>\
								<a href='javascript:closePointsList();'>Close Route To Start</a><br />\
								<a href='javascript:connectAndReverse("+index+","+pointArray[index].point.lat()+","+pointArray[index].point.lng()+")'>Connect To Here And Reverse Back To Start</a><br />\
								<a href='javascript:addAfterThis("+index+")'>Add A Point AFTER This One</a><br />\
								<a href='javascript:addBeforeThis("+index+")'>Add A Point BEFORE This One</a><br />\
								<a href='javascript:deleteThisONE("+index+")'>Delete Just This Point</a><br />\
								<a href='javascript:deleteFromHere("+index+")'>Delete From Here To End</a>\
								</div>"),*/
	var html = [new google.maps.InfoWindowTab("Point Info", "<div style='font-size:x-small; white-space:nowrap;'>\
								Point #"+index+"<br />\
								Lat: "+roundDec(pointArray[index].point.lat(),5)+"<br />\
								Lng: "+roundDec(pointArray[index].point.lng(),5)+"<br />\
								Elev Metres: "+roundDec(pointArray[index].elev,2)+" Feet: "+roundDec((pointArray[index].elev * meters2feet),2)+"<br />\
								Unit Miles: "+roundDec(pointArray[index].distUnit * meters2miles,3)+" kMeters: "+roundDec((pointArray[index].distUnit / 1000),3)+"<br />\
								Total Miles: "+roundDec(pointArray[index].distTotal * meters2miles,3)+" kMeters: "+roundDec((pointArray[index].distTotal / 1000),3)+"<br /></div>")
							];
	pointArray[index].marker.openInfoWindowTabsHtml(html);
}

function connectAndReverse(index, lat, lng) {
	if ((lat=="") || (lat==null) || (lng=="") || (lng==null)) {
		alert("Cannot connect/reverse\nLat="+msgLat+"\nLng="+msgLng);
	}else{
		var endPoint=new google.maps.LatLng(parseFloat(lat),parseFloat(lng));
		if (inputType=='straight'){
			processStraight(xx,endPoint);
			processReturn(index);
		}else{


//unfortunately, the following block is pretty much copied from the "processRoute" function, but 
//it's sort of unavoidable because of the callback function followed by connect/reverse-specific reverse-to-start,
//which here is contained within the callback function.
	var gdir = new google.maps.Directions();
	var loc1=pointArray[xx-1].point.lat()+","+pointArray[xx-1].point.lng();
	var loc2=endPoint.lat()+","+endPoint.lng();
	gdir.load(loc1+" to "+loc2, {getSteps:false, getPolyline:true, preserveViewport:true, locale:"en_US"});
	google.maps.Event.addListener(gdir, "load", function(){
			var myPoly=gdir.getPolyline();
			var wkPoly=tersePoly(myPoly);
				var routeDist=gdir.getDistance().meters;
				routeDrawCalc(xx,wkPoly,routeDist,1);

// and reverse:
				processReturn(index);


											}
										);
		}
	}
}

function mouseStatus(e) {
	var message="";
	if (!e) e=window.event;
	if (e.shiftKey)message+="shift, ";
	if (e.altKey)message+="alt, ";
	if (e.ctrlKey)message+="ctrl, ";
	message+=(e.button<2)?"left":"right";
}

function processReturn(index){
	var wkPoly=[], wkpX=0;
	for (var i=index; i>0; i--) {
		vx=pointArray[i].poly.length;
		for (var j=vx; j>0; j--) {
			wkPoly[wkpX]=pointArray[i].poly[j-1];
			wkpX++;
		}
	}
	wkPoly[wkpX]=pointArray[0].point;
	var returnPoly=new google.maps.Polyline(wkPoly);
	var routeDist=returnPoly.Distance();
	routeDrawCalc(xx,wkPoly,routeDist,1);
}

function updPoint(index,newPoint) {
	pointArray[index].point=new google.maps.LatLng(roundDec(newPoint.lat(),5),roundDec(newPoint.lng(),5));
	var savePoint, delay;
	for (var i=0;i<2;i++){
		if ((index+i)<xx){
			map.removeOverlay(pointArray[index+i].marker);
			map.removeOverlay(pointArray[index+i].lineSegment);
			map.removeOverlay(pointArray[index+i].distMarks);
			savePoint=pointArray[index+i].point;
			pointArray.splice(index+i,1,new spot());
			pointArray[index+i].point=savePoint;
			if (pointArray[index+i].type=='s') {
				processStraight(index+i,pointArray[(index+i)-1]);
			}else{
				delay=10;
				if (i==2)delay=500;
				setTimeout("processRoute("+(index+i)+",pointArray["+(index+i)+"].point);xx--;" ,delay);
			}
		}
	}
		if ((index+1)<xx)	setTimeout("rebuildMap()",500);
}





function buildDrawProfile(){
	var polyDist;

	function drawProfile() {
		var minElev=Infinity, maxElev=0;
		// ==== some Google Chart parameters ====
		var axisInfo="&amp;chxt=x,y,x,y,t,r,t,r&amp;chxl=0:|0";
		var url = "http://chart.apis.google.com/chart?cht=ls&amp;chs=600x150&amp;chco=000000&amp;chm=B,990000,0,0,0&amp;chd=t:"
		for (var i=0; i<maxNodes; i++) {
			// == filter out bogus values ==
			if (altitudes[i] < -10000000000) altitude[i] = 0;
			// == find min and max values ==
			if (altitudes[i]<minElev) minElev=altitudes[i];
			if (altitudes[i]>maxElev) maxElev=altitudes[i];
			// == add to the Chart URL ==
			url += altitudes[i];
			if (i<maxNodes-1) url += ","; 
		}
		// == add min/max values to Chart URL ==
		url += "&amp;chds="+minElev+","+maxElev;
		for (var xi=.2; xi<1.1; xi=xi+.2){
			axisInfo+="|"+(roundDec(((polyDist/1000)*xi),2).toString());
		}
		//				axisInfo+="|"+(roundDec(((polyDist/1000)*1.0),2).toString());
		axisInfo+="|1:|"+minElev+"|"+Math.round((minElev+maxElev)/2)+"|"+maxElev;
		axisInfo+="|2:|KM|3:|Meters";
		axisInfo+="|4:|0"
		for (var ti=.2; ti<1.1; ti+=.2){
			axisInfo+="|"+(roundDec(((polyDist*meters2miles)*ti),2).toString());
		}
		axisInfo+="|5:|"+Math.round(minElev*meters2feet)+"|"+Math.round(((minElev*meters2feet)+(maxElev*meters2feet))/2)+"|"+Math.round(maxElev*meters2feet);
		axisInfo+="|6:|Miles|7:|Feet";
		url+=axisInfo;
		// == create the Google Chart image ==
		$("profile").innerHTML='<img src="' +url+ '" width=600 height=150 />';
		fade('profileDiv','in');
//		document.getElementById("profile").style.display='block';
	}
	
	function getAltitude(poly,i) {
		var point = poly.GetPointAtDistance(i*poly.Distance()/maxNodes);
		google.maps.DownloadUrl('altitude.php?lat=' +point.lat()+ '&lng=' +point.lng(), function(data) {
			var doc = google.maps.Xml.parse(data);
			altitudes[i] = parseInt(google.maps.Xml.value(doc));
			nodes++;
			if (nodes == maxNodes) {
				drawProfile();
			}
		});
	}
	
	function buildOnePoly(){
		var newPolyArray=[];
		for (var i=0; i<xx; i++) {
			var poly=pointArray[i].poly;
			if(poly==null){}else{
				for (var j=0; j<poly.length; j++){
					newPolyArray.push(new google.maps.LatLng(parseFloat(poly[j].lat()) , parseFloat(poly[j].lng()) ) );
				}
			}
		}
		var singlePoly=new google.maps.Polyline(newPolyArray, "#ff0000", 6, 75);
		polyDist=singlePoly.Distance();
		return singlePoly;
	}

	var nodes=0;
	var maxNodes=20;//maxNodes=50;
	var altitudes=[];
	var onePoly=buildOnePoly();
	for (var i=0; i<maxNodes; i++) {
		getAltitude(onePoly,i)
	}


}
