﻿	var map; 
	var bDoubleClickHappened = false;
	var DEFAULT_LAT = 36.98500;
	var DEFAULT_LNG = 26.56494;
	var DEFAULT_ZOOM = 6;
	var DEFAULT_ELEV_PARAM = "0a";
	var IS_LOADING_FROM_QUERYSTRING = true;
	var NOT_LOADING_FROM_QUERYSTRING = false;
	var IS_CREATING_THERE_AND_BACK = true;
	var NOT_CREATING_THERE_AND_BACK = false;
	var NO_GRAPH_MESSAGE = '<span style="font-family:arial;font-size:10pt">Elevation only available on routes with two or more points, and in the U.S. You may also see this message when there is a problem with the remote service that provides the elevation data.</span>';
	var REFRESH_LINK = '<div style="font-family:arial;font-size:10pt;float:left;width:100px"><a href="javascript:refreshGraph();">Refresh graph</a>: One or more of the elevation lookups returned failure (resulting in a "0" in your graph). Click the link to refresh and try again.</div>';
	var elevationArrayIndex = 0;
	var currentElevationGraphHeight = '0';
	var bAllElevationsWereZero = true;
	var mapHeight;
	var performElevationLookup = false;
	var bAllElevationsFound = false;
	var iFoundElevationsSum = 0;
	var bElevationsArrSum = 0;
	var iPercent = 0;
	var bShowRefreshLink = false;
	var rId = '';
	var routeSaved = true;
	var paramString = location.href;
	var routeIdFromQueryString;
	var ptHash = new Object();
	var routeSegmentsCount = 0;
	var polyLineSegmentsHash = new Object();
	var currentLine = new Array(0);
	
	function initializeMap(){

		//route may come entirely from querystring or be saved serverside 
		routeIdFromQueryString = getQuerystringParameter('r', paramString);

		if (routeIdFromQueryString.length > 0) {

			var mapDiv = document.getElementById("map");
			mapDiv.style.fontFamily = "arial";
			mapDiv.style.fontSize = "24pt";
			mapDiv.innerHTML = 'looking up route ' + routeIdFromQueryString + '...';

			//drawMap() and rehydrateMapFromUrl() get called internally by getRoute
			rId =  routeIdFromQueryString;
			getRoute(routeIdFromQueryString);
			
		} else {
			
			drawMap();
			//if parameters have been passed in to prepop location and route, parse them and display correct values
			rehydrateMapFromUrl();

		}

	}
	function drawMap(){		
		
		//intialize the map
		map = new GMap2(document.getElementById("map"), {draggableCursor: 'crosshair'});
		//map.addControl(new GOverviewMapControl())
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.addControl(new GScaleControl());
		map.enableContinuousZoom();
		map.setCenter(new GLatLng(DEFAULT_LAT, DEFAULT_LNG), DEFAULT_ZOOM,G_SATELLITE_MAP);

		var keyHandle = new GKeyboardHandler(map);
	
		//set default value...
		document.getElementById("elevationChart").innerHTML = NO_GRAPH_MESSAGE;

		////set mapheight before call to rehydrateMapFromUrl(), since the height of the elevation graph may be set there.
		mapHeight = document.body.clientHeight - 9 - 2 - 15;
		document.getElementById('map').style.height = mapHeight+'px';

		GEvent.addListener(map, "moveend", function() {
        
			if (bDoubleClickHappened){
				var curCenter = map.getCenter();
				addLeg(curCenter.lng(), curCenter.lat(), NOT_LOADING_FROM_QUERYSTRING, NOT_CREATING_THERE_AND_BACK);
				        
			} 
		
			drawPolyLine(gLatLngArray);
			drawMarkers(gLatLngArray);
			bDoubleClickHappened = false;
        
		});
		//if a zoom happens, we may need to create or destroy the markerArray
		GEvent.addListener(map, "zoomend", function(oldZoom, newZoom) {
			
			prepMarkerArray();
			drawPolyLine(gLatLngArray);			
			drawMarkers(gLatLngArray);
			
		});
	}

	var xArray = new Array(0);
	var yArray = new Array(0);
	var gLatLngArray = new Array(0);
	var elevationArray = new Array(0);
	var legArray = new Array(0);
	var distancesArray = new Array(0);
	var mileMarkersToDraw = new Array(0);
	var routePolyline;
	var distance = 0;
	var bRecordPoints = false;
	var REMOVE = 0;
	var ADD = 1;
	var ENGLISH = 		"0";
	var METRIC = 		"1";
	var DISTANCE = 		"2";
	var SMALLDISTANCE =	"3";
	var WEIGHT = 		"4";
	var SHOW = 			"5";
	var HIDE = 			"6";
	var LEFT = 			"7";
	var RIGHT = 		"8";
	//used as indexes of a hash for the stop and start markers. make sure they remain strings so as not to collide with numeric indexes used for mile markers
	var START = 		"start";
	var STOP = 			"stop";
	
	var currentWeightUnits = getCurrentUnits();
	var bIsIE;
	var showMarkers = true;
	
	distancesArray.push(0);
	
	if (navigator.appName == 'Microsoft Internet Explorer'){
	
		document.ondblclick = handleDblClick;
		bIsIE = true;
		
	} else {
	
		window.ondblclick = handleDblClick;
		bIsIE = false;
		
	}

	function handleDblClick(e) {
	
		bDoubleClickHappened = true;
		
	}
	
	function addLeg(xCoord, yCoord, isLoadFromQueryString, isCreatingThereAndBack) {
			
		if (bRecordPoints) { 
		
			xArray.push(xCoord);
			yArray.push(yCoord);
			gLatLngArray.push(new GLatLng(yCoord, xCoord));
			elevationArray.push(0);
			bElevationsArrSum++;
	        
			//distancesArray is added in UpdateDistances. 
			//getElevation depends on this, so make sure not
			//to change the order of these calls.
			updateDistances(xArray, yArray, ADD);				
			
			//if we're loading from the querystring, don't get all elevation points, 
			//as this takes an excessively long time to load. Elevations will be 
			//loaded when user chooses to view the graph, at which point we can
			//throw a message warning it will take a long time.
			if (isLoadFromQueryString == NOT_LOADING_FROM_QUERYSTRING) {
            
				//only do lookup if we're NOT calling from the "back" part of a there and back --
				//if we are, we'll just add the elevation from the correspoding
				//"there" part and save the AJAX overhead
				if (isCreatingThereAndBack == NOT_CREATING_THERE_AND_BACK) {
	        
					getElevation(gLatLngArray[gLatLngArray.length-1],gLatLngArray.length-1);
				
				}
				
			}
            
			prepMarkersForLeg(distancesArray.length);
			
			markRouteAsUnsaved();

		}
	
	}
	function getBearing(){
	
		var lat1 = yArray[yArray.length-2];
		var lat2 = yArray[yArray.length-1];
		var lon1 = xArray[xArray.length-2];
		var lon2 = xArray[xArray.length-1];
		
		return (Math.atan2(Math.sin(lon2-lon1)*Math.cos(lat2), Math.cos(lat1)*Math.sin(lat2)-Math.sin(lat1)*Math.cos(lat2)*Math.cos(lon2-lon1))) % (2 * Math.PI);
			
	}
	//loops through distancesArry and calls prepMarkersForLeg for each
	//element in the array. Really it's prepMarkersForLeg does all the interesting stuff,
	//but the loop through distancesarray isn't within prepMarkersForLeg, to save
	//the effort of looping through all distances for addLeg. In addLeg we instead perform
	//prepMarkersForLeg only for the newest leg. But prepMarkersArray is called from everywhere else, 
	//including removeLeg.
	function prepMarkerArray(){

		//must be called BEFORE prepMarkerArray, to make sure that we 
		//clear previously existing markers.
		removeAllMileMarkers();

		mileMarkersToDraw = new Array(0);
		
		//there's some stupid bug causing an extra element with value 0 at the top of distancesArry, fix that some day...
		for (var k=3;k<=distancesArray.length;k++){
		
			prepMarkersForLeg(k);
		
		}

	}
	//Looks in the distancesArray at the index submitted and checks to see if the 
	//we have passed a unit marker, so that a new marker should be laid down. If so,
	//calls calcMarkerLatLng 
	function prepMarkersForLeg(distanceIdx){
	
		//if zoomlevel is too high, this feature will probably cause the browser to crash
		if (map.getZoom() > 11) {
			
			var firstDistance;
			var secondDistance = returnDistanceInChosenUnits(distancesArray[distanceIdx-1]);
			
			if (distancesArray.length < 1) {
			
				firstDistance = 0;
			
			} else {
			
				firstDistance = returnDistanceInChosenUnits(distancesArray[distanceIdx-2]);
        	
			}
			
			var firstFloor = Math.floor(firstDistance);
			var secondFloor = Math.floor(secondDistance);
        	
			if (firstFloor < secondFloor){
			
				for (var i=firstFloor+1;i<=secondFloor;i++){
								
					calcMarkerLatLng(parseFloat(i)-firstDistance, distanceIdx-1);
        	
				}
			
			}

		}
	
	}
	function getSlopeOfLeg(gLatLngArray, idx){
	
		var lastPoint = gLatLngArray[idx-1];
		var secondToLastPoint = gLatLngArray[idx-2];
		var denominator;
	
		//little hack to take care of divide by 0 error that can occur when
		//a user chooses a second point exactly north or south of previous point.
		if (secondToLastPoint.lng() == lastPoint.lng()){
		
			denominator = .00000001
		
		} else {
			
			denominator = secondToLastPoint.lng() - lastPoint.lng()
		}

		return ((secondToLastPoint.lat() - lastPoint.lat()) / (denominator));
	
	}
	function getLatLngDistanceOfLeg(idx){
	
		var startPt = idx-2;
		var endPt = idx-1;

		return Math.sqrt(Math.pow(gLatLngArray[startPt].lng()-gLatLngArray[endPt].lng(),2) + Math.pow(gLatLngArray[startPt].lat()-gLatLngArray[endPt].lat(),2))
		
	}
	//calculates the position of a mile marker given a geographical position (represented by
	//the index of a point in the GLatLng array) and the total distance along the route at which the 
	//point should be drawn. this is done by figuring out the slope and distance from the last point.
	function calcMarkerLatLng(distance, idx){
	
		var currentDistPercentOfLastLeg = distance/returnDistanceInChosenUnits(legArray[idx-1]);
		var distanceOfLastLegInLatLng = getLatLngDistanceOfLeg(idx);
		var curDistanceLatLng = currentDistPercentOfLastLeg * distanceOfLastLegInLatLng
        
		var lon1 = gLatLngArray[idx-2].lng();
		var lat1 = gLatLngArray[idx-2].lat();
		var slope = getSlopeOfLeg(gLatLngArray, idx);
        
		var deltaLon = curDistanceLatLng * (1/(Math.sqrt(1 + Math.pow(slope,2))));
		var deltaLat = curDistanceLatLng * (slope/((Math.sqrt(1 + Math.pow(slope,2)))));
        
		var lastPointX = parseFloat(gLatLngArray[idx-1].lng());
		var secondToLastPointX = parseFloat(gLatLngArray[idx-2].lng());
		
		if (secondToLastPointX > lastPointX) {
        
			deltaLon = -deltaLon;
			deltaLat = -deltaLat;
        
		}
        
        var lon2 = parseFloat(lon1)+parseFloat(deltaLon);
        var lat2 = parseFloat(lat1)+parseFloat(deltaLat);
		mileMarkersToDraw.push(new GLatLng(lat2, lon2));
	
	}  	
  	function updateDistances(xArray, yArray, addOrRemove){
	
		if (addOrRemove == ADD){
		//if (distanceToRemove == 0) {
		
			fLastLeg = getLastLegDistance(xArray, yArray);

			distancesArray.push(distancesArray[distancesArray.length-1]+fLastLeg)
	
			//distance += fLastLeg;
			legArray.push(fLastLeg);
		
		//} else if (distanceToRemove > 0) {
		} else if (addOrRemove == REMOVE) {
		
			//distance -= removedLeg;
			distancesArray.pop();
			legArray.pop();
    
		}
		
		updateDistanceBoxes();
		
	}
	function handleWeightChange(distanceInMiles){
	
		currentWeightUnits = getCurrentUnits();
		updateCalorieCounter(distancesArray[distancesArray.length-1]);
	
	}
	
	function updateCalorieCounter(distanceInMiles){
		
		var rawWeightVal = document.controlPanel.weight.value;
		
		if (!isNaN(rawWeightVal)){
					
			var weightInKg;
			
			if (getCurrentUnits() == METRIC) {
			
				weightInKg = parseFloat(rawWeightVal);
			
			} else {

				weightInKg = parseFloat(rawWeightVal);

			}

			var distanceInKm = parseFloat(distanceInMiles);
			document.controlPanel.calories.value = distanceInKm * weightInKg;
		
		}
	
	}
	function updateDistanceBoxes() {
    
		document.controlPanel.mileage.value=parseInt(returnDistanceInChosenUnits(distancesArray[distancesArray.length-1])*10000)/10000;
		
		updateCalorieCounter(distancesArray[distancesArray.length-1]);
        
		var fLastLeg = 0;
        
		if (legArray.length > 0) {
				
			fLastLeg = legArray[legArray.length-1];
				
		}
        
		document.controlPanel.lastLeg.value=parseInt(returnDistanceInChosenUnits(fLastLeg)*10000)/10000;					
    
	}

	function returnDistanceInMiles(point1y, point1x, point2y, point2x) {
		
		var point1 = new GLatLng(point1y, point1x);		
		var point2 = new GLatLng(point2y, point2x);
		var result = point1.distanceFrom(point2) * .000621371192;		

		return (result);
    
	}
	function initializeParameter(nameOfParameter, defaultValue){
	
		var returnVal = '';
		var qstringVal = getQuerystringParameter(nameOfParameter, paramString);
	
		if (qstringVal.length > 0) {
		
			returnVal = qstringVal;
			
		} else {
		
			returnVal = defaultValue;
	
		}
		
		return returnVal;
		
	}
	function completeThereAndBackCourse(){
	
		var mid = gLatLngArray.length - 1;
		
		if (gLatLngArray.length > 1) {
		
			//skipping first element, that's the midpoint of the course
			for (var i= mid-1; i >= 0; i--) {

				//alert(i);
				//alert(pointsSoFar.length);
				addLeg(gLatLngArray[i].lng(), gLatLngArray[i].lat(), NOT_LOADING_FROM_QUERYSTRING, IS_CREATING_THERE_AND_BACK);

				addPreviouslyQueriedElevation(elevationArray[i],elevationArray.length-1)


			}		
			
			//drawElevationGraph normally called within addElevation, but we want to 
			//do so once at the end rather than each time we add a point
			drawElevationGraph();

			drawPolyLine(gLatLngArray);
			drawMarkers(gLatLngArray);

		}
	
	}
	function rehydrateMapFromUrl() {
			
		//get units,map type, and calorie counter options
		var featureList = getQuerystringParameter('fl', paramString);
		
		if (featureList.length > 0) {
		
			var featureListArr = featureList.split('-');
			
			var mapType = featureListArr[0];
			var englishOrMetric = featureListArr[1];
			var calorieCounterShowing = featureListArr[2];
			var weight = featureListArr[3];
			var markers = featureListArr[4];
		
			if (mapType=='s') {
			
				map.setMapType(G_SATELLITE_MAP);
			
			} else if (mapType=='m') {
			
				map.setMapType(G_NORMAL_MAP); 
			
			} else if (mapType=='h') {		
			
				map.setMapType(G_HYBRID_MAP);
			
			}

			(englishOrMetric=='m') ? setUnits(METRIC) : setUnits(ENGLISH);
			
			(calorieCounterShowing =='s') ? toggleCalorieCounter(SHOW) : toggleCalorieCounter(HIDE)
			
			document.controlPanel.weight.value = unescape(weight);
			currentWeightUnits = getCurrentUnits();

			(markers=='0') ? toggleMarkers(HIDE) : toggleMarkers(SHOW);

		}

		//recenter and zoom...
		var curCenterX = parseFloat(initializeParameter('centerX', DEFAULT_LNG));
		var curCenterY = parseFloat(initializeParameter('centerY', DEFAULT_LAT));
		
		//code here is in effect overriding what happens in drawmap, since
		//initializeParameter ensures that a value is always returned 
		var rawZlFromQuerystring = getQuerystringParameter('zl', paramString)
		var zoomLevel;

		//an actual zoomlevel was passed in querystring, check the zv parameter to see
		//whether is was a pre- or post-api v2 zoomlevel
		if (rawZlFromQuerystring.length != 0) {

			var zoomVersion = getQuerystringParameter('zv', paramString);
			zoomLevel = parseInt(initializeParameter('zl',DEFAULT_ZOOM));

			//for now, presence of zoomversion can only mean version 2
			if (zoomVersion.length == 0){
			
				zoomLevel = 17 - zoomLevel;
			
			}		

		} else {

			zoomLevel = DEFAULT_ZOOM;

		}
		

		map.setCenter(new GLatLng(curCenterY, curCenterX), zoomLevel);				
    
		//redraw polyline
		var polyline = getQuerystringParameter('polyline', paramString);
    
		if (polyline.length > 0) {
		
			arrPoints = decodePolyline(polyline);
		
			//currently the only way it is possible for the URL to have a polyline is if the user was 
			//recording at the time they permalinked. Thus, we set recording mode back on now.
			bRecordPoints = true;
			document.controlPanel.startRecording.value='Καταγραφή...';
		
			var j = 0;
			while(j < arrPoints.length) {
				
				if (rId.length == 0) {

					var yCoord = contractNumber(arrPoints[j++]);
					var xCoord = contractNumber(arrPoints[j++]);
					
				} else {

					var yCoord = arrPoints[j++];
					var xCoord = arrPoints[j++];
					
				}
	    
				addLeg(xCoord, yCoord, IS_LOADING_FROM_QUERYSTRING, NOT_CREATING_THERE_AND_BACK);
				
			}
			
			//addleg sets route to be unsaved, mark it as saved in case of new route
			if (rId.length != 0) {
				
				//set rId to null -- if a new change is made, we want to create a new route rather than slam the existing one.
				rId = '';

				//route is one saved from an old permalink or tinyurl -- mark it unsaved to remind the user to save it serverside
				if (routeIdFromQueryString.length == 0) {
		
					markRouteAsUnsaved();
					
				//route is a serverside route, mark as saved already
				}else{

					markRouteAsSaved();
					
				}
				
			}

			//route will have been set to unsaved by addleg calls, reset it here
			//routeSaved = true;
			
			//gLatLngArray should have been fully repopulated during 
			//recursive calls to addLeg
			drawPolyLine(gLatLngArray);
			drawMarkers(gLatLngArray);
			
			//elevation paramter contains both chosen height of graph and the elevations
			var elevParameter = initializeParameter('elev', DEFAULT_ELEV_PARAM);
			
			if (elevParameter != DEFAULT_ELEV_PARAM) {
				
				var elevParamArr = elevParameter.split('a');
				
				var ElevGraphHeightFromUrl = elevParamArr[0];
				performElevationLookup = (elevParamArr[1]=='1');
				
				if (performElevationLookup) {

					var rawElevArrFromUrl = elevParamArr[2].split('b');
					
					for (var i = 0; i<rawElevArrFromUrl.length;i++){
										
						addPreviouslyQueriedElevation(rawElevArrFromUrl[i]/100, i)
					
					}				
					
					//drawElevationGraph normally called within addElevation, but we want to 
					//do so once at the end rather than each time we add a point
					drawElevationGraph();

					elevationSwitch(ElevGraphHeightFromUrl);
					
				}
				
			}

		}
	    	
	}
	function charFill(string, length, charToFillWith, leftOrRight){
		
		var initStringLength = string.length;
		
		for (k=0; k<(length-initStringLength); k++){
			
			if (leftOrRight == LEFT) {
				
				string = charToFillWith + string;
				
			} else if (leftOrRight == RIGHT) {
            
				string = string + charToFillWith;
            
			}
		
		}
		
		return string;
	
	}
	function expandNumber(num) {
	
		var isNegative;
		//remove minus sign for calculation of sig digits
		if (num.charAt(0)=="-") {
        
			isNegative = true;
			num = num.replace('-','');
        
		} else {
        
			isNegative = false;
        
		}
		
		var expandedNumFloat = parseFloat(num) * 100000;
		var stringExpandedNum = expandedNumFloat.toString();
		
		if (stringExpandedNum.indexOf(".") > 0) {
	
			stringExpandedNum = stringExpandedNum.substr(0,stringExpandedNum.indexOf("."))
			
		}
					
		if (stringExpandedNum.length < 5) {
		
			stringExpandedNum = charFill(stringExpandedNum, 5, "0", LEFT);
		
		}
		
		if (isNegative) {
		
			stringExpandedNum = '-' + stringExpandedNum;
		
		}
		
		return stringExpandedNum;

	}
	function fixNumber(num){
	
		if (num.charAt(0)=="-") {

			isNegative = true;
			num = num.replace('-','');

		} else {

			isNegative = false;

		}
	
		var stringExpandedNum = new String(num);
			
		if (stringExpandedNum.length < 5) {
		
			stringExpandedNum = charFill(stringExpandedNum, 5, "0", LEFT);
		
		}
		
		if (isNegative) {
		
			stringExpandedNum = '-' + stringExpandedNum;
		
		}
		
		return stringExpandedNum;

	}
	function contractNumber(num) {
	
		var numObj = fixNumber(new String(num));
	
		var lenNum = numObj.length;
		var decimalLoc = lenNum-5;
		
		var afterDecimal = numObj.substr(decimalLoc, 5);
		var beforeDecimal = numObj.substr(0, decimalLoc);
		
		return parseFloat(beforeDecimal + '.' + afterDecimal);
	
	}
	function prepPointArray(pointArray){
	
		var sReturn = '';
		var sIndCoords;
		for (i=0;i<pointArray.length;i++){
		
			sReturn += (expandNumber(new String(pointArray[i].lat())) + ',' + expandNumber(new String(pointArray[i].lng())));
			
			if (i<pointArray.length-1)
				sReturn += ',';
		
		}
		
		return sReturn;
	
	}
	function getLastLegDistance(xArray, yArray){
	
		var distanceToReturn = 0;
		lastPointIdx = xArray.length - 1;
		secondToLastPointIdx = xArray.length - 2;
	
		if (xArray.length > 1) {
				
			var fLastLeg;
			distanceToReturn = returnDistanceInMiles(yArray[lastPointIdx], xArray[lastPointIdx], yArray[secondToLastPointIdx], xArray[secondToLastPointIdx]);
											
		}
		
		return distanceToReturn;
	
	}
	
	function removeLastLeg() {
	
		if (xArray.length > 0) {
			
			xArray.pop();
			yArray.pop();			
			gLatLngArray.pop();
			    
			updateDistances(xArray, yArray, REMOVE);
	
			prepMarkerArray();

			//markRouteAsUnsaved call must be before drawPolyLine or line will not be colored correctly
			markRouteAsUnsaved();

			drawPolyLine(gLatLngArray);

			drawMarkers(gLatLngArray);

			//redraw elevation graph...
			elevationArray.pop();
			//drawElevGraphQString();
			//elevationSwitch(currentElevationGraphHeight);
			drawElevationGraph()
			
			
		} else {
	
			alert('No points to remove');
	
		}
		
	}
	
	function encodePolyline(a) {
	
		var p = a.split(',');
		var d = '';
		var xo=0;
		var yo=0;
	
		for(c=0;c<p.length;c+=2) {
	
			x = p[c];
			xd = x - xo;
			xo = x;
			f = (Math.abs(xd) << 1) - (xd<0);
	
			do {
				e = f & 31;
				f>>=5;
				if(f){e|=32};
				d+=String.fromCharCode(e+63);
			} while(f!=0);
			
			y = p[c+1];
			yd = y - yo;
			yo = y;
			f = (Math.abs(yd)<<1)-(yd<0);
			
			do {
				e = f & 31;
				f>>=5;
				if(f){e|=32};
				d+=String.fromCharCode(e+63);
			} while (f != 0);
		}
	
		return d;
	
	} 
	function getQuerystringParameter(paramName, paramString){
	
		var sReturnStr = '';
		
		var queryStringObj = new String(paramString)
		var paramNameObj = new String(paramName);
		//queryStringObj = queryStringObj.toLowerCase();
		paramNameObj = paramNameObj.toLowerCase();
			
		//parameters were sent
		if (queryStringObj.indexOf('?') > -1) {
			
			var qStringArray = queryStringObj.split('?');
	
			if (qStringArray[1].length > 0) {
		
				var allParams = qStringArray[1]
				var paramArray = allParams.split("&");
		
				for (i=0; i<= paramArray.length-1; i++){
					
					var origCaseFullParam = paramArray[i];
					var nameValuePairObj = new String(paramArray[i]);
					nameValuePairObj = nameValuePairObj.toLowerCase();
					var nameValuePairArr = nameValuePairObj.split('=');
					var indParamName = nameValuePairArr[0];
					var indParamValue = nameValuePairArr[1];

					if (paramNameObj == indParamName) {

						sReturnStr =  unescape(origCaseFullParam.substr(indParamName.length+1));
						break;

					}
					//var origCaseFullParam = paramArray[i];
					//var lcaseFullParam = paramArray[i].toLowerCase();
	
					//if (lcaseFullParam.indexOf(paramNameObj) > -1)
					//
					//	sReturnStr =  unescape(origCaseFullParam.substr(paramNameObj.length));
					
				}
								
			
			}
		
		
		}
		
		return sReturnStr;
	
	}
	function addBookmark(title,url) {
		
		window.external.AddFavorite( url, title);		
	
	}
	function createPointListForRoute(pointArray){
	
		var sResult = '';
		for (var i = 0; i<pointArray.length; i++){
		
			sResult += pointArray[i].lat() + 'a' + pointArray[i].lng();
			
			if (i < pointArray.length - 1) {
			
				sResult += 'a';
			
			}
		
		}
		
		return sResult;
		
	}
	function returnPermalinkString(){

		var curCenterX = map.getCenter().lng();
		var curCenterY = map.getCenter().lat();
	
		var sPoints = '';
		if (gLatLngArray.length > 0) {
	
			//sPoints = encodePolyline(prepPointArray(gLatLngArray));
			sPoints = createPointListForRoute(gLatLngArray);
	
		}
		
		var locationString = new String(location.href);
		var locationArr = locationString.split('?');
		
		locationString = locationArr[0];
		
		//return (locationString + '?centerX=' + escape(curCenterX) + '&centerY=' + escape(curCenterY) + '&zl=' + new String(map.getZoom()) + '&fl=' + createFeatureListString() + '&polyline=' + escape(sPoints) + '&elev=' + createElevationQueryString());
		return ('centerX=' + escape(curCenterX) + '&centerY=' + escape(curCenterY) + '&zl=' + new String(map.getZoom()) + '&zv=2&fl=' + createFeatureListString() + '&polyline=' + escape(sPoints) + '&elev=' + createElevationQueryString() + '&rId=' + rId);

	}
	function createFeatureListString() {
	
		var sResult;
		
		if (map.getCurrentMapType()==G_SATELLITE_MAP) {

			sResult = 's';

		} else if (map.getCurrentMapType()==G_NORMAL_MAP) {

			sResult = 'm';

		} else if (map.getCurrentMapType()==G_HYBRID_MAP) {

			sResult = 'h';

		}
		sResult += "-";
		
		sResult += ((getCurrentUnits() == METRIC) ? 'm' : 'e'); 
		sResult += "-";
	
		sResult += ((document.getElementById('weightRow').style.display=='none') ? 'h' : 's');
		sResult += "-";
		
		sResult += escape(document.controlPanel.weight.value);
		
		sResult += "-";
		sResult += ((showMarkers==true) ? '1' : '0'); 

		return sResult;
				
	}
	function createTinyURL() {
	
		document.getElementById("url").value = returnPermalinkString();
		document.tinyUrlForm.submit();
	
	}
	function createPermalink(){
	
		saveRoute(returnPermalinkString());
		markRouteAsSaved();

			
	}
	function displayRouteUrlMessage(){

		document.getElementById('routeUrlMessage').innerHTML = "<div style='color:#ff0000'>URL for this route is: http://www.gmap-pedometer.com/?r="+rId+". " + ((document.all)?"<a href=\"javascript:addBookmark('Gmap Pedometer Route "+rId+"','http://www.gmap-pedometer.com/?r="+rId+"');\">Add bookmark</a>":"");
		//document.getElementById('routeUrlMessage').innerHTML = "URL for this route is: http://www.gmap-pedometer.com/?r="+rId;

	}
	function markRouteAsUnsaved(){

		document.getElementById('saveLink').innerHTML = saveLinkActive;
		routeSaved = false;

	}
	function markRouteAsSaved(){
		//saving message will be changed to "saved" after ajax call completes
		//currently being set to "Saving..."
		document.getElementById('saveLink').innerHTML = saveLinkSaving;
		routeSaved = true;
	}
	function getRoute(routeId){

		var request = GXmlHttp.create();
		request.open("POST", "getRoute.php", true);
		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		request.onreadystatechange = function() {
			if (request.readyState == 4) {

				//setting paramString eq to string from db
				paramString = '?' + request.responseText;
				//erase "looking up route" message we wrote earlier.
				document.getElementById("map").innerHTML='';
				drawMap();
				rehydrateMapFromUrl();
       
			}
		}
		request.send('rId=' + routeId);
	}

	function saveRoute(stringToSend){

		var request = GXmlHttp.create();
		request.open("POST", "saveRoute.asp", true);
		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		request.onreadystatechange = function() {
			if (request.readyState == 4) {

				rId = request.responseText;
				document.getElementById('saveLink').innerHTML = saveLinkInactive;
				displayRouteUrlMessage();
       
			}
		}
		request.send(stringToSend);
	}
	function decodePolyline(a) {
	
		if (rId.length == 0) {
		
			var b=a.length;
			var c=0;
			var d=new Array();
			var e=0;
			var f=0;
			while(c < b){
				var g;
				var h=0;
				var i=0;
				do{
					g=a.charCodeAt(c++)-63;
					i = i | (g&31)<<h;
					h = h + 5
				}while(g>=32);
				var l;
				if (i & 1){ 			
					l = ~(i >> 1); 	
				} else {				
					l = i >> 1; 	
				}
	    	
				e = e + l;
				d.push(e);
				
				h=0;
				i=0;
				do{
					g=a.charCodeAt(c++)-63;
					i = i | (g&31)<<h;
					h = h + 5;
				}while(g>=32);
	    	
				var m
				if (i & 1)
					m = ~(i >> 1);
				else
					m = i >> 1
					
				f = f + m;
				d.push(f)
			}
			return d;
		
		} else {
		
			var retArr = a.split('a');

			return retArr;
		
		}
	}
	function clearLinkHandler(){
	
		if (bRecordPoints) {
			
			if (confirm("Είσαι σίγουρος ότι θέλεις να ξεκινήσεις καινούργια καταγραφή;\nOK για να καθαρίσεις τα σημεία.\nCancel για να συνεχίσεις στην ίδια καταγραφή.")) {
			
				//distances array slightly different from all the other arrays;
				//it's initialized with a first element of 0.
				distancesArray.splice(1,distancesArray.length-1);
	
				legArray.splice(0,legArray.length);
				gLatLngArray.splice(0,gLatLngArray.length);
				xArray.splice(0,xArray.length);
				yArray.splice(0,yArray.length);
				mileMarkersToDraw.splice(0,mileMarkersToDraw.length)
				elevationArray.splice(0,elevationArray.length);
				iFoundElevationsSum = 0;
				bElevationsArrSum = 0;
				
				document.controlPanel.mileage.value='0';
				document.controlPanel.lastLeg.value='0';					
				document.controlPanel.calories.value='0';
			
				map.clearOverlays();
				drawElevationGraph();
				bRecordPoints=false;
				document.controlPanel.startRecording.value='Έναρξη Καταγραφής';
				
				//clear any routeid, so that user doesn't lose last route.
				if (rId != '') {
	
					document.getElementById('routeUrlMessage').innerHTML = "<div style='color:#ff0000'>Έναρξη νέας διαδρομής</div>";

				}

				markRouteAsUnsaved();
				rId = '';
	
			}
		} else {
		
			alert('Δεν έχει εισαχθεί διαδρομή ακόμα');
		
		}
	}
	function drawMarkers(gLatLngArray){

		//drawmarkers is called from toggleMarkers before route is created when rehydrating...
		if (gLatLngArray.length > 0) {	
		
			if (showMarkers) {
			
				drawStopStartMarker(gLatLngArray[0],START);
  	    	
				drawStopStartMarker(gLatLngArray[gLatLngArray.length-1],STOP);
        	
				for (var m=0;m<mileMarkersToDraw.length;m++) {
        		
					var imageUrl;
					
					var mileNum = m+1;
					if (mileNum<11) {
					
						imageUrl = "unitMarker."+mileNum+".png";
					
					} else {
        	
						imageUrl = "unitMarker.php?nm="+mileNum;
					
					}
					
					var icon = new GIcon();
					icon.image = imageUrl;
					icon.shadow = "http://www.google.com/mapfiles/shadow50.png";
					icon.iconSize = new GSize(20, 34);
					icon.shadowSize = new GSize(37, 34);
					icon.iconAnchor = new GPoint(9, 34);
					
					drawMileMarker(mileMarkersToDraw[m], icon, m);
        		
				} 
				
			}				
		}
	
	}
	function drawStopStartMarker(gLatLng,id){

		map.removeOverlay(ptHash[id]);
		ptHash[id] = new GMarker(gLatLng);
  		map.addOverlay(ptHash[id]);

	}
	//iterates through mileMarkersToDraw loop and removes any already
	//existing mile markers. Needed in cases like removeLeg, where the
	//gLatLng array may no longer contain all the markers 
	function removeAllMileMarkers(){
		
		for (var m=0;m<mileMarkersToDraw.length;m++) {
		
			if (ptHash[m] != undefined){
				
				map.removeOverlay(ptHash[m]);
				ptHash[m] = undefined;
				
			}

		}
	}
	//markers are drawn only if they are within bounds of the map, and only if they are not already on the map
	function drawMileMarker(gLatLng, icon, idx){
	
		var bRemove = false;
		var bAdd = false;

		if (map.getBounds().contains(gLatLng)){
		
			if (ptHash[idx] == undefined){
				
				ptHash[idx] = new GMarker(gLatLng, icon);
				map.addOverlay(ptHash[idx]);
				
			}
			  		
  		} else {
  			
			if (ptHash[idx] != undefined){
			
				map.removeOverlay(ptHash[idx]);
				ptHash[idx] = undefined;
			
			}

  		}

		
	}
	//google's built-in intersect function on bounds is buggy, rolled me own.
	//with thanks to http://www.tekpool.com/?p=23
	function doBoundsIntersect(rect1, rect2){
	
		var left1, right1, top1, bottom1;
		var left2, right2, top2, bottom2;
		
		left1 = rect1.minX;
		right1 = rect1.maxX; 
		top1 = rect1.minY; 
		bottom1 = rect1.maxY; 
	
		left2 = rect2.minX;
		right2 = rect2.maxX; 
		top2 = rect2.minY; 
		bottom2 = rect2.maxY; 
	
		return !(left2 > right1 || right2 < left1 || top2 > bottom1 || bottom2 < top1);

	}
	//helper function for drawPolyLine
	function drawPolyLineSegment(routeColor){
	
		polyLineSegmentsHash[routeSegmentsCount] = new GPolyline(currentLine, routeColor)
		map.addOverlay(polyLineSegmentsHash[routeSegmentsCount]);
		routeSegmentsCount++;
		currentLine.splice(0,currentLine.length)

	}
	//polyline is now drawn in multiple segments. Only segments where both points are within bounds are drawn
	function drawPolyLine(gLatLngArray){
		for (var i=0;i<routeSegmentsCount;i++){
	  		map.removeOverlay(polyLineSegmentsHash[i]);
		}    
		routeSegmentsCount = 0;
		//this function may be called from removeLastLeg, in which case 
		//we still want to clear points (above) but don't want to draw a new one.
		if (gLatLngArray.length > 0) {
			var routeColor;
			if (routeSaved){
				routeColor = '#0000FF';
			} else {
				routeColor = '#FF0000';
			}
			//to determine whether to draw a line segment, we check whether the rectangle described by the segment
			//intersects with the rectangle described by the current screen. If we just checked whether the begin and 
			//end points were on the current map, we'd miss lines that pass through the current map without originating
			//there.
			var lastPtAdded = false;
			var mapSW = map.getBounds().getSouthWest();
			var mapNE = map.getBounds().getNorthEast();
			//using GBounds instead of GLatLngBounds because a GBound can be created using any two points.
			//Constructor of GLatLngBounds requires we calculate NE and SW corners of bounds, which we may not have 
			var mapGBounds = new GBounds(new Array(map.fromLatLngToDivPixel(mapSW),map.fromLatLngToDivPixel(mapNE)));
			var thisGBounds;
			var nullPoint = new GPoint(0,0)
			for (var j=1; j<gLatLngArray.length; j++){
				thisGBounds = new GBounds(new Array(map.fromLatLngToDivPixel(gLatLngArray[j]),map.fromLatLngToDivPixel(gLatLngArray[j-1])));
				if (doBoundsIntersect(mapGBounds,thisGBounds)){
					if (!lastPtAdded){
						currentLine.push(gLatLngArray[j-1]);
					}
					currentLine.push(gLatLngArray[j]);
					lastPtAdded = true;
				} else {
					lastPtAdded = false;
					if (currentLine.length > 0){
						drawPolyLineSegment(routeColor);
					}
				}
			}
			if (currentLine.length > 0){
				drawPolyLineSegment(routeColor);				
			}
		}
	}
	function setCurrentUnits(unitsToSet){
	
		var unitInput = document.controlPanel.units;

		if (unitsToSet == ENGLISH) {
		
			unitInput[0].checked = true;
			unitInput[1].checked = false;
			
		} else if (unitsToSet == METRIC) {
		
			unitInput[0].checked = false;
			unitInput[1].checked = true;
			
		} 
	
	}
	function getCurrentUnits(){
	
		var curValue;
		var unitInput = document.controlPanel.units;

		if (unitInput[0].checked) {
		
			curValue = ENGLISH;
		
		} else if (unitInput[1].checked) {
    
			curValue = METRIC;
			
		}
		
		return curValue;
		
	
	}
	function getCurrentMultiplier(type){
	
		var curValue = getCurrentUnits();		
    
		var multiplier;
		
		if (type == DISTANCE) {

			if (curValue==METRIC) {
			
				multiplier = 1.852;
			
			} else {
			
				multiplier = 1.0;
        	
			}
			
		} else if (type ==  WEIGHT) {

			if (curValue==METRIC) {
			
				multiplier = 0.45359237;
			
			} else {
			
				multiplier = 1.0;
        	
			}

		} else if (type ==  SMALLDISTANCE) {

			if (curValue==METRIC) {
			
				multiplier = 0.3048;
			
			} else {
			
				multiplier = 1.0;
        	
			}

		}
		
		return multiplier;
	
	}
	function returnSmallDistanceInChosenUnits(valueToApplyTo){

		var multiplier = getCurrentMultiplier(SMALLDISTANCE);		
        
		return valueToApplyTo * multiplier;

	}
	function roundToTwoDecimalPlaces(decNum){
		
		return Math.round(decNum * 100)/100;
		
	}
	function returnDistanceInChosenUnits(valueToApplyTo){
		
		var multiplier = getCurrentMultiplier(DISTANCE);		
        
		return valueToApplyTo * multiplier;
	
	}	

	function toggleMarkers(showOrHide){

		if (showOrHide == SHOW) {

			showMarkers = true;
			document.getElementById('markerSwitch').innerHTML = 'Turn <a href="javascript:toggleMarkers(HIDE);">off</a> mile markers';

		} else if (showOrHide == HIDE) {

			showMarkers = false;
			document.getElementById('markerSwitch').innerHTML = 'Turn <a href="javascript:toggleMarkers(SHOW);">on</a> mile markers';

		}

		//whether we turned them off or on, we need to redraw. 
		prepMarkerArray();
		drawMarkers(gLatLngArray);

	}
	function toggleCalorieCounter(showOrHide){
	
		if (showOrHide == SHOW) {
		//if (document.getElementById('weightRow').style.display=='none') {
        
			document.getElementById('calorieCounterSwitch').innerHTML = '<a href="javascript:toggleCalorieCounter(HIDE);">Παύση</a> υπολογιστή';

			//ie uses the block property for this, FF wants table-row
			if (bIsIE) {

				document.getElementById('weightRow').style.display='block';
				document.getElementById('calorieRow').style.display='block';
				
			} else {

				document.getElementById('weightRow').style.display='table-row';
				document.getElementById('calorieRow').style.display='table-row';

			}
			
		} else if (showOrHide == HIDE) {
        
			document.getElementById('calorieCounterSwitch').innerHTML = '<a href="javascript:toggleCalorieCounter(SHOW);">Έναρξη</a> υπολογιστή';
			document.getElementById('weightRow').style.display='none';
			document.getElementById('calorieRow').style.display='none';
	    
		}
		
	}
	function updateWeightBoxWithUnitToggle(unitsToSet){
		
		//only needs to be done if units were actually changed. onclick fires even if value did not change
		if (unitsToSet != currentWeightUnits) {
		
			var rawWeightVal = document.controlPanel.weight.value;
			var convertedWeight;
			
			if (getCurrentUnits() == METRIC) {
			
				convertedWeight = parseFloat(rawWeightVal);
			

			} else {
            
				convertedWeight = parseFloat(rawWeightVal);
            
			}
			
			document.controlPanel.weight.value=convertedWeight;
			currentWeightUnits = getCurrentUnits();
			
		}
		

	}
	function handleUnitToggle(unitsToSet){
	
		updateWeightBoxWithUnitToggle(unitsToSet);
		setUnitLabels(unitsToSet);
		//if we switch units, it affects the mile markers, so we need to recalculate mile markers and redraw the polyline if we switch
		prepMarkerArray();
		//drawPolyLine(gLatLngArray);
		drawMarkers(gLatLngArray);

		//call elevationswitch to make sure we redraw graph appropriately
		elevationSwitch(currentElevationGraphHeight)
		
	}
	function setUnitLabels(unitsToSet){
	
		if (unitsToSet == METRIC) {
		 
			document.getElementById("dstUnits1").innerHTML = "km";
			document.getElementById("dstUnits2").innerHTML = "km";
			document.getElementById("wtUnits").innerHTML = "";
			                     
		} else if (unitsToSet == ENGLISH) {                 
                                 
			document.getElementById("dstUnits1").innerHTML = "miles";
			document.getElementById("dstUnits2").innerHTML = "miles";
			document.getElementById("wtUnits").innerHTML = "";

		}
		
		updateDistanceBoxes();
	
	}
	function setUnits(unitsToSet){
	
		if (unitsToSet != getCurrentUnits()) {
		
			setCurrentUnits(unitsToSet)
			setUnitLabels(unitsToSet);
			
		}
	
	}
	function geoCode(){
		
		var zoomLevelObj = document.locationSearch.zoom_level;
      	var zoomLevelObjVal = parseInt(zoomLevelObj[zoomLevelObj.selectedIndex].value);

		if (document.locationSearch.country.selectedIndex == 0) {
			var geocoder = new GClientGeocoder();
			var submittedAddress = document.getElementById("locationBox").value
			geocoder.getLatLng(
    			submittedAddress,
    			function(point) {
      				if (!point) {
        				alert("Sorry, couldn't find that location. Please check your submission and try again.\n\nIf the location is in China, Japan, or the UK, click \"more options\" and choose your country from the dropdown that appears.");
      				} else {
			        	map.setCenter(point, zoomLevelObjVal);
			      	}
    			}
  			);

		} else {

			var searchString;
			searchString = document.getElementById("locationBox").value + ',' + document.locationSearch.country[document.locationSearch.country.selectedIndex].value;
        	
			var request = GXmlHttp.create();
			request.open("GET", "getLoc.php?srch=" + searchString, true);
			request.onreadystatechange = function() {
				if (request.readyState == 4) {
					
					var textReturned = request.responseText;
					if (textReturned.length > 0) {
        	
						var textReturnedArr = textReturned.split(',');
						var xCoord = textReturnedArr[0];
						var yCoord = textReturnedArr[1];
        	
						map.setCenter(new GLatLng( yCoord, xCoord), parseInt(zoomLevelObj[zoomLevelObj.selectedIndex].value));
        	
					} else {
					
						alert("Συγνώμη αλλά δεν μπόρεσα να βρώ τις συντεταγμένες αυτές. Παρακαλώ ξαναπροσπαθήστε.");
					
					}
        	
				}
			}
			request.send(null);

		}
		
	}
	function showCountry(){
	
		var countryList = document.locationSearch.country;

		countryList.style.display='inline';
			
	}
	function printMap(){
		
		//document.getElementById("searchBox").style.display = 'none';
		//document.getElementById("copy").style.display = 'none';
		//document.getElementById("printDone").style.display = 'block';

		//document.getElementById("mapPane").style.left = '0%';
		
		window.print();

	}
	function printDone(){

		document.getElementById("printDone").style.display = 'none';
		document.getElementById("searchBox").style.display = 'block';
		document.getElementById("copy").style.display = 'block';

		document.getElementById("mapPane").style.left = '0%';
		document.getElementById("mapPane").style.width = '70%';
		document.getElementById("mapPane").style.height = '96%';

	}
	function getElevation(gLatLng,currentPointCoord) {
		//we only do lookups in the following cases:
		//new route
		//saved route that already has elevations
		//if a user is coming in with a saved route that has no elevations,
		//we don't do any lookups until such time as they choose to view the graph for the first time.
		if (currentPointCoord == 0) {
			performElevationLookup = true;
		}
		if (performElevationLookup) {
			var request = GXmlHttp.create();
			var result;
			request.open('GET', 'getElevation.php?x=' + gLatLng.lng() + '&y=' + gLatLng.lat(), true);
			request.onreadystatechange = function() {
				if (request.readyState == 4) {
				    var xmlDoc = GXml.parse(request.responseText);
					iFoundElevationsSum++;
					addElevation(xmlDoc.documentElement.childNodes[0].nodeValue,currentPointCoord);
			  	}
			}
			request.send(null);
		}
	}
	function addPreviouslyQueriedElevation(newElevation,currentPointCoord){
	
		//used when rehydrating state from permalink or completing there and back --
		//any case where we don't actually do a remote lookup to find the elevation
	
		//this var is used to determine how many of the requested elevations have come in. when adding elevation w/o a lookup, 
		//since we're not requesting the elevations, the code where the lookup is done is never executed, so
		//we never increment it. Increment it here to "fake out" the code in addElevation.
		if (performElevationLookup) {

			iFoundElevationsSum++;
			
		}

		addElevationValueToArray(newElevation,currentPointCoord);

	}
	function addElevationValueToArray(newElevation,currentPointCoord){

		//not using addElevation here, since it contains other processing, such as 
		//processing of errors that might come back from usgs, that we don't need
		//to do a second time once the graph has already been created.
		if (iFoundElevationsSum == bElevationsArrSum){
			
			bAllElevationsFound = true;
		
		} else {

			bAllElevationsFound = false;
			iPercent = Math.round((iFoundElevationsSum / bElevationsArrSum)*100);

		}
		elevationArray[currentPointCoord] = parseInt(newElevation*100)/100;

	}
	function addElevation(newElevation,currentPointCoord){
		
		//gisdata.usgs.net returns this value when there is a problem on their side
		//set  performElevationLookup so that subsequent lookups are not attempted
		if (newElevation == "-1.79769313486231E+308")  {
		
			bShowRefreshLink = true;
			newElevation = "0";
			//performElevationLookup = false;
		
		}
		
		addElevationValueToArray(newElevation,currentPointCoord);
		
		//elevGraphqString has page scope so it will still be available outside this function in case we need to redraw 
		//graph when that pane is resized
		//elevGraphqString = '';
		
		//drawElevGraphQString();
		
		drawElevationGraph();
		
	}
	function getPixelsPerUnit(){
	
		if (getCurrentUnits()==METRIC) {
			
			return '62';
			
		} else {

			return '100';

		}
	
	}
	function drawElevGraphHtml(elevGraphqString){
		
		var sReturnVal
		var fMaxElev = 0;
		var fMinElev = 0;
		var fStartElev = 0;
		
		sReturnVal = '';
		//string is in form: 0,110;.75,100;.85,110;1.1,85 -- distances followed by elevations
		var elevGraphStrObj = new String(elevGraphqString);
		var elevGraphArr = elevGraphStrObj.split(";");
		
		var STEP_SIZE = 50;
		var sCurrentElevations;
		var aElevChunks = new Array(0);
		
		CurrentElevations = '';
		
		for (var i=0; i<elevGraphArr.length;i++){			

			var sEntry = new String(elevGraphArr[i]);
			var aEntry = sEntry.split(",");
			var fCurrentElevation = parseFloat(aEntry[1]);			

			if (i==0){
				
				fMaxElev = fCurrentElevation;
				fMinElev = fCurrentElevation;
				fStartElev = fCurrentElevation;
			
			}

			if (fCurrentElevation > fMaxElev) {
				
				fMaxElev = fCurrentElevation;
				
			}
			
			if (fCurrentElevation < fMinElev) {
				
				fMinElev = fCurrentElevation;
				
			}

			CurrentElevations = CurrentElevations += roundToTwoDecimalPlaces(returnDistanceInChosenUnits(distancesArray[i+1])) + ',' + roundToTwoDecimalPlaces(returnSmallDistanceInChosenUnits(elevationArray[i])) + ';';

			if ((i == elevGraphArr.length-1) || ((i+1) % STEP_SIZE == 0)) {
				
				CurElevObj = new String(CurrentElevations);
				aElevChunks.push(CurElevObj.substr(0,CurElevObj.length-1));
				
				//put in code to trim off the semicolon here!!
			
			}
			
			//we want to have the point at each boundary repeated in the gif on both sides of the boundary
			//if we are at the boundary, and we know that we have at least two points left before the end, 
			//reinitialize the CurrentElevations string, which eventually has the effect of creating a new elevChunk
			if ((i < elevGraphArr.length-2) && ((i+1) % STEP_SIZE == 0)) {
			
				CurrentElevations = roundToTwoDecimalPlaces(returnDistanceInChosenUnits(distancesArray[i+1])) + ',' + roundToTwoDecimalPlaces(returnSmallDistanceInChosenUnits(elevationArray[i])) + ';';

			}
			
		}
		var finalDistance = roundToTwoDecimalPlaces(returnDistanceInChosenUnits(distancesArray[distancesArray.length-1]));
		
		sReturnVal += '<div style="width:'+(getPixelsPerUnit()*finalDistance)+'px">';
		for (var j=0; j<aElevChunks.length;j++) {
		
			sReturnVal += '<img style="margin:0px" src="drawGraph.php?elevDist='+aElevChunks[j]+'&graphHeight='+currentElevationGraphHeight+'&pixelsPerUnit='+getPixelsPerUnit()+'&min='+fMinElev+'&max='+fMaxElev+'&start='+fStartElev+'&totalDistance='+finalDistance+'">';
			
		}
		sReturnVal += '</div>';
	
		
		return sReturnVal;

	}
	function drawElevationGraph(){

		var elevGraphqString = drawElevGraphQString();
				
		if ((elevationArray.length >= 2) && (!bAllElevationsWereZero)){
		
			if (bAllElevationsFound){
        
//				document.getElementById("elevationChart").innerHTML= ((bShowRefreshLink)?REFRESH_LINK:"") + '<img style="margin:0px" src="drawGraph.php?elevDist='+elevGraphqString+'&graphHeight='+currentElevationGraphHeight+'&pixelsPerUnit='+getPixelsPerUnit()+'">';
				document.getElementById("elevationChart").innerHTML= ((bShowRefreshLink)?REFRESH_LINK:"") + drawElevGraphHtml(elevGraphqString);
			
			} else {
			
				document.getElementById("elevationChart").innerHTML= '<span style="font-family:arial;font-size:10pt">Please wait, looking up elevations...'+iPercent+'%</span>';
			
			}
        
		} else {
		
			document.getElementById("elevationChart").innerHTML = NO_GRAPH_MESSAGE;
        
		}
		
	}
	function elevationSwitch(displayHeight){
	
		//used in querystring and to tell php how high to draw the graph
		currentElevationGraphHeight = displayHeight;
		
		if (displayHeight == 0){
			
			document.getElementById("elevationSwitch0").innerHTML = unlinkElevation0;
			document.getElementById("elevationSwitch100").innerHTML = linkElevation100;
			document.getElementById("elevationSwitch200").innerHTML = linkElevation200;
			
			document.getElementById("elevationChart").style.display = "none";
			document.getElementById("elevationChart").style.height = displayHeight+"px";
			document.getElementById("map").style.height = mapHeight+"px";
        
		} else if (displayHeight == 100){
        
			document.getElementById("elevationSwitch0").innerHTML = linkElevation0;
			document.getElementById("elevationSwitch100").innerHTML = unlinkElevation100;
			document.getElementById("elevationSwitch200").innerHTML = linkElevation200;
			
			document.getElementById("elevationChart").style.display = "block";
			document.getElementById("elevationChart").style.height = displayHeight+"px";
			document.getElementById("map").style.height = (mapHeight-100)+"px";

		} else if (displayHeight == 200){

			document.getElementById("elevationSwitch0").innerHTML = linkElevation0;
			document.getElementById("elevationSwitch100").innerHTML = linkElevation100;
			document.getElementById("elevationSwitch200").innerHTML = unlinkElevation200;
			
			document.getElementById("elevationChart").style.display = "block";
			document.getElementById("elevationChart").style.height = displayHeight+"px";
			document.getElementById("map").style.height = (mapHeight-200)+"px";

		}
		
		if ((displayHeight == 100) || (displayHeight == 200)){
			
			//set this to execute in one millisecond, so that IE immediately redraws
			//the elevation div, rather than waiting until after the graph is complete
			window.setTimeout('getElevationsUponGraphSelect('+displayHeight+')', 1);
			
		}
	}
	function refreshGraph(){
		
		bShowRefreshLink = false;
		iFoundElevationsSum = 0;
		performElevationLookup = false;
		
		getElevationsUponGraphSelect(currentElevationGraphHeight);
		
	}
	function getElevationsUponGraphSelect(ElevGraphHeightFromUrl){
	
		if (ElevGraphHeightFromUrl != 0){ 

			//this function is called from elevationSwitch, which handles
			//the case where a user has chosen to turn on the elevation graph.
			//The elevGraphqString may or may not have been populated -- if it 
			//has not been, create it now. 

			if (!performElevationLookup) {
        	
				for (var i=0; i<gLatLngArray.length; i++) {
        	
					getElevation(gLatLngArray[i],i);
					
				}
				
				//if performElevationLookup was false, it means
				//we haven't done any lookups up to this point, so now that we are looking them 
				//all up, flip it to true now.
				//performElevationLookup = true;
			
			}
	    	
			//var elevGraphqString = drawElevGraphQString();
			drawElevationGraph();
			
		}
		
	}
	function createElevationQueryString(){
		
		var elevStrForUrl = '';
		
		for (var i =0;i<elevationArray.length;i++){
			
			elevStrForUrl += Math.round(elevationArray[i]*100);
			
			if (i < elevationArray.length-1) {
				
				elevStrForUrl += 'b';
	
			}
		
		}

		var sPerformElevLookup = (performElevationLookup)?"1":"0";

		return currentElevationGraphHeight + 'a' + sPerformElevLookup + 'a' + elevStrForUrl;
		
	}
	function drawElevGraphQString(){

		var elevGraphqString = '';
        
		for (i=0; i < elevationArray.length;i++){
		
			elevGraphqString += roundToTwoDecimalPlaces(returnDistanceInChosenUnits(distancesArray[i+1])) + ',' + roundToTwoDecimalPlaces(returnSmallDistanceInChosenUnits(elevationArray[i])) + ';';
			
			if (elevationArray[i] != '0'){
			
				bAllElevationsWereZero = false;
			
			}
			
		}
        
		var qStringObj = new String(elevGraphqString);
		return qStringObj.substring(0,qStringObj.length-1);

	}
	var debugWin;
	function debugIt(message){
	
		if (!debugWin){
		debugWin = window.open('','','');
		}
		debugWin.document.write(message+'<br>');
	
	}
	function debugItNoHr(message){
	
		if (!debugWin){
		debugWin = window.open('','','');
		}
		debugWin.document.write(message);
	
	}
	function svgon(){
		
		_mSvgEnabled = true;
		_mSvgForced  = true;
	
	}; 
