/* Script for displaying GoogleMap on Peakware.com
	Created by Terrill Thompson, http://www.mountbakermedia.com
	Added support for drawing routes in December 2009
	Updated to Google Maps Javascript API v3 Nov 2010 - Mar 2011
	
	Last update: March 24, 2011
*/
/* Possible values of whichMap: 

	blank - world map with no markers
	peak - shows current peak, plus most prominent surrounding peaks (using a different icon)
	area - shows most prominent peaks from the specified area
	addapeak - dynamic map, starts with entire world but changes as AddaPeak form changes
	routes - shows all routes for a given peak (each route plus its waypoints in a different color)
	addaroute = interactive map with drawing tools
	editroute = same as addaroute, but pre-populated
	person - shows a person's map, with all their favious features identified
	people - shows all users (is this supported yet??? should be - might be very cool)
	myconfig - shows users's hometown (use geocoding service, based on Country, state, city, lat, lng )
	Custom pre-defined maps: 
		8000m
		7summits
		50states
		cascades
		colorado
		california
		canada
		alps 
*/	

//global vars
var map;
var toldYou = false;
if (whichMap == 'person' || whichMap == 'myConfig' || whichMap == 'addapeak') { 
	var markers = new Array();
}
else if (whichMap == 'route') { 
	var loadingKml;
}
if (whichMap == 'route' || whichMap == 'editroute') { 
	var overlays = new Array();
}
if (whichMap == 'addaroute' || whichMap == 'editroute') { 
	//vars for drawing the route
	var startMarker;
	var endMarker;
	var trkpoints = new Array(); //array of points along a polyline 
	var midpoints = new Array(); //array of midpoints between trkpoints 
	var markers = new Array(); //array of icon/markers marking each waypoint on a route 
	var polyPoints = new Array(); //MVCArray for collection coordinates
	var polyLine; //linear overlay of connected line segments on the map 
	var mouseMoveListener;
	var toolID = 1;
	var mylistener;
	var editing = false;
	var extendingLine = false;
	var placemarking = false;
	var following = false;
	var markerCursor;
	var infoWindow;
	var totalDistance = 0.0;
	var pointIndex = 0; //number of points in the route
	var placemarkIndex = 0; //number of waypoint markers 
	var imageNormal = new google.maps.MarkerImage(
		"images/route_square.png",
		new google.maps.Size(11, 11),
		new google.maps.Point(0, 0),
		new google.maps.Point(6, 6)
	);
	var imageHover = new google.maps.MarkerImage(
		"images/route_square_over.png",
		new google.maps.Size(11, 11),
		new google.maps.Point(0, 0),
		new google.maps.Point(6, 6)
	);
	var imageNormalMidpoint = new google.maps.MarkerImage(
		"images/route_square_transparent.png",
		new google.maps.Size(11, 11),
		new google.maps.Point(0, 0),
		new google.maps.Point(6, 6)
	);
}
if (typeof zoom != 'undefined') { 
	if (zoom >= 9) { 
		if (typeof country != 'undefined') { 
			if (country == 'United States' || country == 'Canada') var showTopo = true;
			else showTopo = false;
		}
		else showTopo = false;
	}
	else showTopo = false;
}
else showTopo = false;

//set default lat, lng, & zoom if not already set
if ((typeof lat == 'undefined') || (typeof lng == 'undefined')) { 
	if (typeof pk != 'undefined') { 
		//can't show a peak map without coordinates
		var showMap = false;
	}
	else { 
		var defaults = getDefaults();
		var lat = defaults['lat'];
		var lng = defaults['lng'];
		var zoom = defaults['zoom'];
		var showMap = true;
	}
}
else var showMap = true;

function initMap(newLat,newLng) { 
	if (showMap) { 

		if (typeof newLat != 'undefined' && typeof newLng != 'undefined') { 
			//center of map has changed dynamically, and is different than global lat & lng
			var newCenter = new google.maps.LatLng(newLat, newLng);
		}
			
		var centerCoords = new google.maps.LatLng(lat, lng);
		if (showTopo == true) { 
			var mapTypes = [
				google.maps.MapTypeId.TERRAIN,
				google.maps.MapTypeId.ROADMAP,
				google.maps.MapTypeId.SATELLITE,
				google.maps.MapTypeId.HYBRID,
				'TOPO'
			];
		}
		else { //exclude TOPO from options
			var mapTypes = [
				google.maps.MapTypeId.TERRAIN,
				google.maps.MapTypeId.ROADMAP,
				google.maps.MapTypeId.SATELLITE,
				google.maps.MapTypeId.HYBRID,
			];
		}
		if (whichMap == 'addaroute' || whichMap == 'editroute') { 
			if (typeof newCenter != 'undefined') { 
				var myOptions = {
					zoom: zoom,
					center: newCenter,
					draggableCursor: 'default',
					draggingCursor: 'pointer',
					mapTypeControlOptions: {
						mapTypeIds: mapTypes
					}
				}
			}
			else { 
				var myOptions = {
					zoom: zoom,
					center: centerCoords,
					draggableCursor: 'default',
					draggingCursor: 'pointer',
					mapTypeControlOptions: {
						mapTypeIds: mapTypes
					}
				}
			}
		}
		else { 
			if (typeof newCenter != 'undefined') { 
				var myOptions = {
					zoom: zoom,
					center: newCenter,
					mapTypeControlOptions: {
						mapTypeIds: mapTypes
					}
				}
			}
			else { 
				var myOptions = {
					zoom: zoom,
					center: centerCoords,
					mapTypeControlOptions: {
						mapTypeIds: mapTypes
					}
				}
			}
		}
		map = new google.maps.Map(document.getElementById("map"),myOptions);

		if (whichMap == 'editroute') { 
			//adjust bounds 
			if ((typeof minLat != 'undefined') && (typeof minLng != 'undefined') 
				&& (typeof maxLat != 'undefined') && (typeof maxLng != 'undefined')) { 
				var sw = new google.maps.LatLng(minLat, minLng, true);
				var ne = new google.maps.LatLng(maxLat, maxLng, true);
				var bounds = new google.maps.LatLngBounds(sw,ne);
				map.fitBounds(bounds);
			}
		}
		if (showTopo == true) { 
			//define myTopo map type
			var mytopoMap = new google.maps.ImageMapType({
				getTileUrl: function(ll, z) {
					return "http://maps.mytopo.com/peakware/tilecache.py/1.0.0/topoG/" + z + "/" + ll.x + "/" + ll.y + ".jpg";
				},
				tileSize: new google.maps.Size(256, 256),
				isPng: true,
				maxZoom: 15,
				minZoom: 9,
				name: "Topo",
				alt: "Detailed topographic maps"
			}); 
			//add it to the available mapTypes
			map.mapTypes.set('TOPO', mytopoMap);
		}

		//set the default MapType
		map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
		//map.setMapTypeId('TOPO');
		//addTopoMap();

		if (whichMap == 'addaroute' || whichMap == 'editroute') { 
			polyPoints = new google.maps.MVCArray(); // collects coordinates
			preparePolyline(); // create a Polyline object
		}

		if (whichMap == 'route' || whichMap == 'editroute') showRoutes();

		//add listeners 
		
		google.maps.event.addListener(map,'bounds_changed', function(event) { 
			//wait until map is ready before adding markers or other features
			//there is no 'ready' event, but 'bounds_changed' seems to be a reliable indicator 
			if (whichMap == 'peak') { //maybe 'routes' and 'addaroute' too? 
				processMarkers(whichMap,centerCoords,pk,pkName);
			}
			else if (whichMap == 'addapeak') { 
				processMarkers(whichMap,centerCoords);
			}
			else if (whichMap == 'area') { 
				processMarkers(whichMap,centerCoords,area);
			}
			else if (whichMap == 'person') { 
				processMarkers(whichMap,centerCoords,personId);
			}
			else if (whichMap == 'route') { 
				//NOTE: The following doesn't work. bounds_changed is triggered BEFORE all KMLs are added
				//Need to listen for some other event that signals the completion of KMLs being loaded. What event???
				//After a new kml overlay is added, viewport changes, centered on the new layer 
				//If there are multiple routes, this is not desirable
				//the following code restores global bounds, which were calculated to include ALL routes
				if (loadingKml == true) { 
					if ((typeof minLat != 'undefined') && (typeof minLng != 'undefined') 
						&& (typeof maxLat != 'undefined') && (typeof maxLng != 'undefined')) { 
						var sw = new google.maps.LatLng(minLat, minLng, true);
						var ne = new google.maps.LatLng(maxLat, maxLng, true);
						var bounds = new google.maps.LatLngBounds(sw,ne);
						map.fitBounds(bounds);
					}
					loadingKml = false;
				}
			}
			else processMarkers(whichMap,centerCoords);
		});
		addEventListeners(whichMap);  
	}
	else { 
		showNoMap();
	}
}

function processMarkers(whichMap,centerCoords,id,pkName) {	

	//based on whichMap, show each marker by calling addMarker()
	//id is either pk or personId, depending on the value of whichMap
	//pkName is optional (only applies to maps related to a specific peak)
	if (whichMap == 'area') { 
		//show default markers for peaks in this area
		var ajaxUrl = createUrl(whichMap,zoom,id,1);			
		if (typeof ajaxUrl != 'undefined') showMarkers(whichMap,ajaxUrl,1);
		//also show secondary markers for out-of-area peaks appearing within map bounds
		var ajaxUrl = createUrl(whichMap,zoom,id,2);
		if (typeof ajaxUrl != 'undefined') showMarkers(whichMap,ajaxUrl,2);
	}
	else if (whichMap == 'peak') { 
		//show centered, non-draggable default marker for this peak
		addMarker('default',pkName,'red',true,false,false,centerCoords,1000);
		//also show secondary markers for nearby peaks 
		var ajaxUrl = createUrl(whichMap,zoom,id);
		if (typeof ajaxUrl != 'undefined') showMarkers(whichMap,ajaxUrl);
	}
	else if (whichMap == 'addapeak') { 
		//if marker doesn't already exist, create it
		if (markers.length < 1) { 
			//show centered, draggable, non-clickable default marker for this peak
			addMarker('default','Your peak here','red',true,true,true,centerCoords,1000);
		}
	}
	else if (whichMap == 'person') { 
		//show default marker identifying user's location (if defined)
		var ajaxUrl = createUrl(whichMap,zoom,id);
		if (typeof ajaxUrl != 'undefined') showMarkers(whichMap,ajaxUrl);
	}
	else if (whichMap == 'myConfig') { 
		//if marker doesn't already exist, add default marker identifying user's location 
		if (markers.length < 1) { 
			addMarker('default','My home','red',true,true,false,centerCoords,1000);	
		}
	}
	else if (whichMap == 'route' || whichMap == 'addaroute' || whichMap == 'editroute') { 
		//do nothing. Markers for these routes are handled elsewhere
	}
	else { 
		var ajaxUrl = createUrl(whichMap); 
		if (typeof ajaxUrl != 'undefined') showMarkers(whichMap,ajaxUrl);		
	}
}

function showMarkers(whichMap,ajaxUrl,areaMap) { 
	downloadUrl(ajaxUrl, function(data) {
		var xml = data.responseXML;
		if (xml) { 
			if (whichMap == 'peak' || 
				(whichMap == 'addaroute') || 
				(whichMap == 'area' && areaMap == '2')) { 
				var markerColor = 'blue';
			}
			else var markerColor = 'red';
			var mapMarkers = xml.documentElement.getElementsByTagName("marker");
			var zIndex = mapMarkers.length;
			for (var i = 0; i < mapMarkers.length; i++) {
				//get data from xml file (might not be the following fields)
				var markerId = mapMarkers[i].getAttribute("id");
				var markerType = mapMarkers[i].getAttribute("type");
				var markerName = mapMarkers[i].getAttribute("name");
				var markerLat = parseFloat(mapMarkers[i].getAttribute("lat"));
				var markerLng = parseFloat(mapMarkers[i].getAttribute("lng"));
				if ((typeof markerLat != 'undefined') && (typeof markerLng != 'undefined')) { 
					var markerLocation = new google.maps.LatLng(markerLat, markerLng);
				}
				var markerUrl = 'peaks.html?pk=' + markerId;
				addMarker('default',markerName,markerColor,true,false,false,markerLocation,zIndex,markerUrl);
				zIndex--;
			}
		}
	});
}

function downloadUrl(url,callback) {
	var request = window.ActiveXObject ?
		new ActiveXObject('Microsoft.XMLHTTP') :
		new XMLHttpRequest;

	request.onreadystatechange = function() {
		if (request.readyState == 4) {
			request.onreadystatechange = doNothing;
			callback(request, request.status);
		}
	};

	request.open('GET', url, true);
	request.send(null);
}

function addMarker(markerType,markerTitle,color,dot,draggable,hasInfoWindow,centerCoords,zIndex,url) { 
	//add a marker to the map 
	//markerType is either 'default','start','end' or 'arrow'
	//color is either: red, blue, green, ltblue, orange, pink, purple, yellow
	//dot is true or false; if true use icon that has a black dot in the middle
	//Could also use any of the other icons defined here (or define our own elsewhere): 
	//http://www.visual-case.it/cgi-bin/vc/GMapsIcons.pl
	//draggable is either true or false
	//hasInfoWindow is either true or false
	//zIndex is 1000 for featured icon, surrounding icons should be descending order of precedence 
	//url (if provided) will be opened in browser window if user clicks on  marker
	//NOTE: All different color markers (other than default) are displayed WITHOUT dots in the center
	//If dots are desired, change this var to true: 
	if (markerType != 'arrow') { 
		if (dot) 
			var icon = 'http://maps.google.com/mapfiles/ms/micons/' + color + '-dot.png';
		else 
			var icon = 'http://maps.google.com/mapfiles/ms/micons/' + color + '.png';
	}
	else { 
		var icon = 'http://maps.google.com/mapfiles/kml/pal5/icon6.png'; //arrow icon
		var iconShadow = 'http://maps.google.com/mapfiles/kml/pal5/icon6s.png'; //shadow (not currently used)
	}
	//create the marker 
	if (markerType == 'default' || markerType == 'arrow') { 
		var marker = new google.maps.Marker({
			position: centerCoords, 
			icon: icon,
			map: map,
			title: markerTitle,
			flat: true,
			draggable: draggable,
			zIndex: zIndex
		});
		if (whichMap == 'addaroute' || whichMap == 'editroute') { 
			markers.push(marker);
		}
	}
	else if (markerType == 'start') { 
		startMarker = new google.maps.Marker({
			position: centerCoords, 
			icon: icon,
			map: map,
			title: markerTitle,
			flat: true,
			draggable: draggable,
			zIndex: zIndex
		});
		if (whichMap == 'addaroute' || whichMap == 'editroute') { 
			markers.push(startMarker);
		}
	}
	else if (markerType == 'end') { 
		endMarker = new google.maps.Marker({
			position: centerCoords, 
			icon: icon,
			map: map,
			title: markerTitle,
			flat: true,
			draggable: draggable,
			zIndex: zIndex
		});
		if (whichMap == 'addaroute' || whichMap == 'editroute') { 
			markers.push(endMarker);
		}
	}
	if (whichMap == 'addaroute' || whichMap == 'editroute') { 
		placemarking = false;
		if (hasInfoWindow) { 
			var prompt = getMarkerPrompt(centerCoords);
			infoWindow = new google.maps.InfoWindow({
				content: prompt
			});
			//add event listener that removes the marker if infoWindow is closed without saving 
			google.maps.event.addListener(infoWindow, 'closeclick', function(event) {
				marker.setMap(null);
				//remove last marker from markers array
				markers.pop();
				select('btn_hand');
			});
			var tip = 'Enter a name and a description for this waypoint.';
			addTip(tip);
			//open the window!
			infoWindow.open(map,marker);
		}
		else if (markerType == 'default') select('btn_hand');
		else doNothing();
	}
	if (typeof url != 'undefined') { 
		google.maps.event.addListener(marker, 'click', function(event) {
			window.location = url;
		});
	}
	if (whichMap == 'person' || whichMap == 'myConfig' || whichMap == 'addapeak') { 
		//add this marker to the markers array (this is done elsewhere for other map types)
		markers.push(marker);
	}
	if (draggable == true) {
		//add a listener to update the latlng field after this marker has been dragged
		google.maps.event.addListener(marker,'dragend',function(event) { 
			var newPos = marker.getPosition();
			if (whichMap == 'addaroute' || whichMap == 'editroute') { 
				//cycle through all markers in array to find the index of the one you moved
				for (i=0; i<markers.length; i++) { 
					if (markers[i] == marker) { //this is the one!
						var thisMarkerPos = i;
						var thisLatLngField = 'wpt' + thisMarkerPos + 'LatLng';
						var newLatLng = newPos.lat() + ', ' + newPos.lng();
						if (document.getElementById(thisLatLngField)) { 
							document.getElementById(thisLatLngField).value=newLatLng;
						}
					}
				}
			}
			else if (whichMap == 'myConfig' || whichMap == 'addapeak') { 
				if (document.getElementById('latitude')) { 
					document.getElementById('latitude').value = newPos.lat();
				}
				if (document.getElementById('longitude')) { 
					document.getElementById('longitude').value = newPos.lng();
				}
			}
		});
	}
}

function createUrl(whichMap,zoom,id,areaMap) { 

	//id is personId, pk, or area, depending on value of whichMap 
	//areaMap is either null, 1 (markers within area), or 2 (markers surrounding area)
	var url = 'data/getmarkers.php?map=' + whichMap;
	if (whichMap == 'person') { 
		//first, clear map of other markers by removing references to them
		for(var i = 0; i < markers.length; i++) {
			markers[i].setMap(null);
		}
		url += '&personId=' + personId;
		if (document.getElementsByName('mapChoice')) {
			var mapChoices = document.getElementsByName('mapChoice');
			for(var i = 0; i < mapChoices.length; i++) {
				if (mapChoices[i].checked == true) { 
					var mapChoice = mapChoices[i].value;
					url += '&mapChoice=' + mapChoice;
				}
			}
		}
	}
	else if (whichMap=='addapeak' || whichMap=='people' || whichMap == 'peak' || whichMap == 'area') { 
		//the markers that get displayed are controlled in part by the bounds of the map 
		var bounds = map.getBounds();
		var southWest = bounds.getSouthWest();
		var northEast = bounds.getNorthEast();
		var span = bounds.toSpan(); 
		var swLat = southWest.lat(); 
		var swLng = southWest.lng();
		var neLat = northEast.lat();
		var neLng = northEast.lng();
		var latSpan = span.lat();
		var lngSpan = span.lng();
		url += "&swLat=" + swLat;
		url += "&swLng=" + swLng;
		url += "&neLat=" + neLat;
		url += "&neLng=" + neLng;
		url += "&lngSpan=" + lngSpan;
		url += "&latSpan=" + latSpan;
		url += "&zoom=" + zoom;
		if (whichMap=='peak') url += "&exclude=" + id;
		else if (whichMap=='area') { 
			if (areaMap == 1) url += "&area=" + id;
			else if (areaMap == 2) url += "&exclude=" + id;
		}
	}
	return url;
}

function addEventListeners(whichMap) { 
	if (whichMap == 'addaroute' || whichMap == 'editroute') { 
		google.maps.event.addListener(map, 'click', function(event) { 
			if (editing == true) {
				if (extendingLine == true) {  
					//user is continuing an existing line
				}
				addRoutePoint(event);
			}
			else if (placemarking == true) { 
				addWaypoint(event);
			}
			if (following == true) { 
				following = false;
				markerCursor.setMap(null);
				google.maps.event.removeListener(mouseMoveListener);
			}
		});
	}
	
	//update global var zoom as the map changes
	google.maps.event.addListener(map, 'zoom_changed', function(event) {
		var prevZoom = zoom;
		zoom = map.getZoom();
		if (whichMap == 'addapeak') { 
			doNothing(); //yet
		}
		else if (typeof country != 'undefined') { 
			if (country == 'United States' || country == 'Canada') { 
				var center = map.getCenter();
				if (zoom >= 9 && prevZoom < 9) {
					//reload the map with topo control
					showTopo = true;
					initMap(center.lat(),center.lng());
				}
				else if (zoom < 9 && prevZoom >= 9) { 
					//reload the map without topo control
					showTopo = false;
					initMap(center.lat(),center.lng());
				}
			}
		}
		//if there's a zoom form field on this page (which always has id='zoom', update it
		if (document.getElementById('zoom')) { 
			document.getElementById('zoom').value = zoom;
		}
	});
	//add mytopo print link if map changes to topo
	google.maps.event.addListener(map, 'maptypeid_changed', function(event) {
		if (map.getMapTypeId() == 'TOPO') addTopoLink();
		else removeTopoLink();
	});
}

function updateMap(whichMap) { 

	//user has clicked on "Update map" button 
	//Update map based on form fields that are on the current page 
	if (whichMap == 'myConfig') { 
		if (document.getElementById('latitude') && document.getElementById('longitude')) { 
			var newLat = document.getElementById('latitude').value;
			var newLng = document.getElementById('longitude').value;	
			if (newLat != '' && newLng != '') { 
				var hasCoords = true;
				var newCenter = new google.maps.LatLng(newLat, newLng);
				markers[0].setPosition(newCenter);
				map.setCenter(newCenter); 
				zoom = map.getZoom();
				if (zoom < 9) zoom = 9; //zoom in slightly
				map.setZoom(zoom); 
			}
			else 	var hasCoords = false;
		}
		else var hasCoords = false;
		if (!hasCoords) { 
			//no lat and lng are provided, try finding location using other fields
			if (document.getElementById('city')) { 
				var city = document.getElementById('city').value;
				var hasCity = true;
			}
			if (document.getElementById('state')) {
				var state = document.getElementById('state').value;
				var hasState = true;
			}
			if (document.getElementById('country')) { 
				var countryId = document.getElementById('country').selectedIndex;
				var country = document.getElementById('country').options[countryId].text;
				var hasCountry = true;
			}
			//use Google Geocoding Service to request coordinates
			var geocoder = new google.maps.Geocoder();
			if (hasCity && hasState && hasCountry) 
				var address = city +', ' + state + ', ' + country;
			else if (hasCity && hasState) 
				var address = city +', ' + state;
			else if (hasCity && hasCountry) 
				var address = city +', ' + country;
			else if (hasState && hasCountry)
				var address = state +', ' + country;
			else if (hasCountry)
				var address = country;
			if (typeof address != 'undefined') { 
				geocoder.geocode( { 'address': address}, function(results, status) {
					if (status == google.maps.GeocoderStatus.OK) {
						var newLocation = results[0].geometry.location;
						map.setCenter(newLocation);
						var marker = new google.maps.Marker({
							map: map, 
							position: newLocation
						}); 
						//update latitude and longitude fields 
						document.getElementById('latitude').value=newLocation.lat();
						document.getElementById('longitude').value=newLocation.lng();						
					} 
					else {
						alert("Unable to find " + address + " on the map: " + status);
					}
				});
			}
		}
	}	
	else	if (whichMap == 'addapeak') { 
		//zoom in based on available data 
		if (document.getElementById('latitude') && document.getElementById('longitude')) { 
			var newLat = document.getElementById('latitude').value;
			var newLng = document.getElementById('longitude').value;	
			if (newLat != '' && newLng != '') { 
				var hasCoords = true;
				var newCenter = new google.maps.LatLng(newLat, newLng);
				map.setCenter(newCenter); 
				zoom = map.getZoom();
				if (zoom < 9) zoom = 9; //zoom in slightly
				map.setZoom(zoom); 
				if (markers.length == 1) { 
					//update existing marker
					markers[0].setPosition(newCenter);
				}
				else { //create a new marker
					//but shouldn't we do this via addMarker() ???
					var marker = new google.maps.Marker({
						map: map, 
						position: newCenter,
						draggable: true
					});
				}
			}
			else 	var hasCoords = false;
		}
		else var hasCoords = false;
		if (!hasCoords) { 
			var error = 'To update the map, you must first enter a latitude and longitude. ';
			error += 'alternatively, you can use the map controls to search for the peak, ';
			error += 'and the latitude and longitude will be populated automatically. ';
			error += 'Please zoom in to get the most accurate coordinates possible.';
			if (document.getElementById('maperror')) { 
				document.getElementById('maperror').innerHTML=error;
				document.getElementById('maperror').style.display="block";
			}
			else alert (error);
		}
	}
	//if map includes a draggable marker, add a listener to respond when drag ends 
	//marker is defined elsewhere, as is dragend listener - is this section needed??? 
	if (typeof marker != 'undefined') { 
		if (marker.getDraggable()) { 
			google.maps.event.addListener(marker,'dragend',function(event) { 
				//get new position of marker & write lat & lng to lat/lng form fields
				var newPos = marker.getPosition();
				if (document.getElementById('latitude')) { 
					document.getElementById('latitude').value = newPos.lat();
				}
				if (document.getElementById('longitude')) { 
					document.getElementById('longitude').value = newPos.lng();
				}
			});
		}
	}
}

function addTopoMapType() { 
	//reload map with mytopo
	showTopo = true;
	newlat = centerLat;
	newlng = centerLng;
	initMap();
}

function removeTopoMapType() { 
	//reload map without mytopo
	showTopo = false;
	lat = centerLat;
	lng = centerLng;
	initMap();
}

function addTopoLink() {
	if (document.getElementById("printLink")) { 
		var center = map.getCenter();
		var topoUrl = 'http://www.mytopo.com/wildernet.cfm?pid=peakware&amp;lat=';
		topoUrl += center.lat() + '&amp;lon=' + center.lng();
		var topoHTML = '<a href="' + topoUrl + '">';
		topoHTML = topoHTML + 'Order a print of this topo map</a>';
		document.getElementById("printLink").innerHTML = topoHTML.toString();
	}
/*	//in-map link provided by MyTopo, using the out-of-map method above instead
	var link_div = document.createElement('div');
	link_div.style.fontFamily = 'Arial,sans-serif';
	link_div.style.fontSize = '1.0em';
	link_div.style.marginBottom = '17px';
	link_div.innerHTML = '<a href="http://www.mytopo.com/index.cfm">Topo maps provided by MyTopo.com</a>';
	return link_div;
*/	
}

function removeTopoLink() { 
	if (document.getElementById("printLink")) 
		document.getElementById("printLink").innerHTML = '';
}

function focusMapToArea (target,id) { 
	//called by addapeak via peakware.js (when continent or range is changed)
	//if target == 'continent', id is a name 
	//if target == 'area', id is an id 
	var ajaxUrl = 'scripts/ajaxFocusMap.php';
	$.post(ajaxUrl, { 
		target: target,
		id: id
	}, function (data) {
		var mapSpecs = data.split(',');
		var mapLat = mapSpecs[0];
		var mapLng = mapSpecs[1];
		var mapZoom = parseInt(mapSpecs[2]);
		var mapLatLng = new google.maps.LatLng(mapLat,mapLng);
		map.setZoom(mapZoom);
		map.setCenter(mapLatLng); 
		markers[0].setPosition(mapLatLng);
	});
}	

function showRoutes() { 

	if (whichMap == 'route') { 
		//kmlUrls is an array of URLs
		if (typeof kmlUrls != 'undefined') { 
			if (kmlUrls.length > 0) { 
				for (i=0; i<kmlUrls.length; i++) { 
					var route = new google.maps.KmlLayer(kmlUrls[i]);
					route.setMap(map);
					overlays[i] = route;
					if (i == (kmlUrls.length-1)) { 
						//this is the last kmlUrl
						//after it's completed, bounds_changed event will be triggered
						//event listener defined elsewhere will adjust bounds at that point
						loadingKml = true;
					}
				}
			} 
		}
	}
	else if (whichMap == 'editroute' || whichMap == 'addaroute') {
		updatePlacemarkIndex();
		//kml layer is not editable. Need to plot each trkpoint individually
		//get data from HTML on the page
		if (document.getElementById('trkroute')) { 
			var trkRoute = document.getElementById('trkroute').value;
			var routeCoords = trkRoute.split('\n');
			for (i=0; i<routeCoords.length; i++) { 
				var thisLatLng = routeCoords[i].split(', ');
				var thisLat = thisLatLng[0];
				var thisLng = thisLatLng[1];
				var thisPoint = new google.maps.LatLng(thisLat,thisLng);
				polyPoints.push(thisPoint);
			} 
			polyLine.setPath(polyPoints);
			polyLine.setMap(map);
			calculateDistance();
		}
		//now do the same with waypoints
		var allDivs = document.getElementsByTagName('div');
		var numDivs = allDivs.length;
		for (i=0; i<numDivs; i++) { 
			if (allDivs[i].className == 'waypoint') { 
				var divId = allDivs[i].getAttribute('id');
				var nameId = divId + 'Name';
				var descId = divId + 'Desc';
				//var latId = divId + 'Lat';
				//var lngId = divId + 'Lng';
				var latLngId = divId + 'LatLng';
				var wptName = document.getElementById(nameId).value;
				var wptDesc = document.getElementById(descId).value;
				//var wptLat = document.getElementById(latId).value;
				//var wptLng = document.getElementById(lngId).value;
				var wptLatLng = document.getElementById(latLngId).value;
				var latLngArray = wptLatLng.split(', ');
				var wptLat = parseFloat(latLngArray[0]);
				var wptLng = parseFloat(latLngArray[1]);
				var latLng = new google.maps.LatLng(wptLat,wptLng);
				//consider modifying this so start and end markers are green and red, & all others blue
				addMarker('default',wptName,'red',true,true,false,latLng,1000);
			}
		}		
	}
}

function updatePlacemarkIndex() { 
	//count waypoint div's  
	var count=0;
	var allDivs = document.getElementsByTagName('div');
	var numDivs = allDivs.length;
	for (i=0; i<numDivs; i++) { 
		if (allDivs[i].className == 'waypoint') count++;
	}
	placemarkIndex = (count++);
}

function toggleRoute(which) { 

	if (typeof overlays != 'undefined') { 
		if (overlays[which].getMap()) { 
			//this overlay is attached to a map. Detach it. 
			overlays[which].setMap(null);
		}
		else { 
			//This overlay is NOT attached to a map. Attach it. 
			overlays[which].setMap(map);
		}
	}
}

function addWaypoint(point) { 
	//only called if user is placing waypoints with the placemark tool (not start or end)
	var friendlyIndex = placemarkIndex + 1; //don't start on 0
	var markerLabel = 'Waypoint #' + friendlyIndex;
	var markerName = 'wpt' + String(friendlyIndex);
	if (whichMap == 'addaroute') var markerColor = 'blue';
	else var markerColor = 'red';
	addMarker('default',markerLabel,markerColor,true,true,true,point.latLng,1000);
	//don't addWaypointDiv here. That will happen after user saves infoWindow (see processInfoWindow())
	placemarkIndex++;	
	placemarking = false;
}
	
function getDefaults() { 

	//might be able to customize this based on other known values
	//for now, set to center of the earth 
	var defaults = new Array();
	defaults['lat'] = 0;
	defaults['lng'] = 0;
	defaults['zoom'] = 1;
	return defaults;
}

function select(buttonId) {
	if (editing && buttonId != 'btn_line') { 
		editing = false;
		polyLine.setMap(null);
		preparePolyline();
	}
	if (placemarking && buttonId != 'btn_placemark') placemarking = false;
	if (following) { 
		following = false;
		markerCursor.setMap(null);
	}
	document.getElementById("btn_hand").className="unselected";
	document.getElementById("btn_line").className="unselected";
	document.getElementById("btn_placemark").className="unselected";
	document.getElementById(buttonId).className="selected";
}

function deleteWaypoint(wptId) { 
	//wptId is in the form 'wpt'+x where x is an index in the marker array
	//first, delete the marker from the map
	var markerIndex = parseInt(wptId.substr(3));
	deleteMarker(markerIndex);
	//second, remove the waypoint div
	if (document.getElementById(wptId)) { 
		var targetDiv = document.getElementById(wptId);
		targetDiv.parentNode.removeChild(targetDiv);
	}
	updateWaypointDivIds();
	placemarkIndex--;
}

function deleteMarker(which) {
	for(i = 0; i < markers.length; i++) {
		if (i == which) { 
			markers[i].setMap(null);
		}
	}
}

function clearMap() {
	//delete all map overlays by removing references to them
	//this function called by clicking either of the addaroute "Reset" buttons
	for(i = 0; i < trkpoints.length; i++) {
		if (trkpoints[i]) trkpoints[i].setMap(null);
	}
	for(i = 0; i < midpoints.length; i++) {
		if (midpoints[i]) midpoints[i].setMap(null);
	}
	for(i = 0; i < markers.length; i++) {
		if (markers[i]) markers[i].setMap(null);
	}
	for(i = 0; i < polyPoints.length; i++) {
		if (polyPoints[i]) polyPOints[i].setMap(null);
	}
	//delete start and end markers
	if (startMarker) startMarker.setMap(null);
	if (endMarker) endMarker.setMap(null);	
	polyLine.setMap(null);
	polyPoints = [];
	markers = [];
	preparePolyline();
	//reset counters
	var pointIndex = 0;
	var placemarkIndex = 0;
}

function stopEditing(){
	select("btn_hand");
	editing = false;
	extendingLine = false; //maybe? or is this premature? fart
	if (polyPoints.length > 1) { 
		var coords = '';
		for(var i = 0; i < polyPoints.length; i++) {
			var thisPoint = polyPoints.getAt(i);
			coords += thisPoint + '\n';
			if (i == (polyPoints.length-1)) { 
				//this is the last point. Add a marker
				addMarker('end','End','red',true,true,false,thisPoint,1000);
				//add waypoint div corresponding with this marker
				var wptId = 'wpt' + String(markers.length-1);
				addWaypointDiv(wptId,'End','',thisPoint);
			}
		}
		if (document.getElementById('trkroute')) { 
			//trkroute already exists. Just update it with new coords
			document.getElementById('trkroute').innerHTML = coords;
		}
		else { 
			//create the field
			addField('textarea','trkpoints','trkroute',coords,'Route Coordinates (Read Only)'); 
		}
		var tip = 'Finished! Click the <em>line draw</em> button again to edit your route, ';
		tip += 'or the <em>marker</em> button to add placemarks. Click <em>Save</em> when finished.';
		addTip(tip);
	}
	else { 
		addTip("You didn't draw anything.");
	}	
	//remove temporary editing overlays from map (trkpoints and midpoints)
	if (typeof trkpoints != 'undefined') { 
		for(var i = 0; i < trkpoints.length; i++) {
			trkpoints[i].setMap(null);
		}
	} 
	if (typeof midpoints != 'undefined') { 
		for(var i = 0; i < midpoints.length; i++) {
			midpoints[i].setMap(null);
		}
	} 
	polyPoints = polyLine.getPath();
	trkpoints = [];
	midpoints = [];
}

function preparePolyline(){
	var polyOptions = {
		path: polyPoints,
		strokeColor: "#FF0000",
		strokeOpacity: 1,
		strokeWeight: 3
	};
	polyLine = new google.maps.Polyline(polyOptions);
	polyLine.setMap(map);
}

function editLine(){
	if(editing == true){
		stopEditing();
   }
	else{	
		editing = true;
		select('btn_line');
		polyPoints = polyLine.getPath();
		if(polyPoints.length > 0){
			//user is continuing an existing line
			extendingLine = true;
			//check for an end marker, and if there is one, delete it 
			if (markers.length > 0) { 
				//the "End" marker isn't necessarily the last marker in the array 
				//other waypoints may have been added after the line was last edited
				for (i=0; i<markers.length; i++) { 
					if (markers[i].getTitle() == "End") { 
						//user didn't change the name of the End marker, 
						//so it's probably ok to delete it
						markers[i].setMap(null);
						//remove marker from array  
						markers.splice(i,1);
						//change ids of all waypoint divs so they're in synch with markers
						updateWaypointDivIds(); 
					}
				}	
			}
			//add editable midpoints to line
			for(var i = 0; i < polyPoints.length; i++) {
				var trkpoint = setTrkpoints(polyPoints.getAt(i)); 
				trkpoints.push(trkpoint);
				if(i > 0) {
					var midpoint = setMidpoints(polyPoints.getAt(i));
					midpoints.push(midpoint);
				}
			}
		}
		else { 
			//this is a new line
			addTip('To start drawing a route, click the trailhead or starting point on the map');
		}
	}
}

function addTip(tipText) { 
	if (document.getElementById('editor_tips')) { 
		document.getElementById('editor_tips').innerHTML = tipText;
	}
}

function addRoutePoint(point){ 
	//route drawing code
	polyPoints = polyLine.getPath();
	polyPoints.push(point.latLng); 
	if(polyPoints.length == 1) { 
		//this is the first point on the route. Add a marker. 
		addMarker('start','Start','green',true,true,false,point.latLng,1000);
		//add waypoint div corresponding with this marker
		var wptId = 'wpt' + String(markers.length-1);
		addWaypointDiv(wptId,'Start','',point.latLng);
		var newTip = 'Good. Now click along the route to draw the route. ';
		newTip += 'When finished, click the <em>line draw</em> button again.';
		addTip(newTip);
	}
	else { 
		//there is more than one point, so calculate distance so far
		calculateDistance();
	}
	pointIndex++;
}

function calculateDistance() { 
	//google returns distance in meters
	var totalDistance = google.maps.geometry.spherical.computeLength(polyPoints.getArray());
	//update routeMeters (hidden) field
	if (document.getElementById('routeMeters')) 
		document.getElementById('routeMeters').value=totalDistance.toFixed(3);
	//now update distance div so user can see it	
	if ((prefUnit == 'default' && country == 'United States') || (prefUnit == 'usa')) { 
		totalDistance = metersToFeet(totalDistance,3);
		if (totalDistance >= 5280) { 
			//express distance in miles
			var tdStr = (totalDistance/5280).toFixed(3) + ' miles';
		}
		else var tdStr = totalDistance.toFixed(3) + ' feet';
	}
	else { 
		if (totalDistance > 1000) { 
			//express distance in kilometers 
			var tdStr = (totalDistance/1000).toFixed(3) + ' km';
		}
		else var tdStr = totalDistance.toFixed(3) + ' meters';
	}
	document.getElementById("distance").innerHTML = 'Total Distance: '+ tdStr;
}

function metersToFeet(value,dec) {
	var result = value * 3.2808399;
	if (dec == 0) return Math.floor(result);
	else 	return round(result,dec);
} 

function round(value,dec) { 
	return String(Math.round(value*Math.pow(10,dec))/Math.pow(10,dec));
}

function setTrkpoints(point) { 
	var trkpoint = new google.maps.Marker({
		position: point,
		map: map,
		icon: imageNormal,
		raiseOnDrag: false,
		draggable: true
	});
	google.maps.event.addListener(trkpoint, "mouseover", function() {
		trkpoint.setIcon(imageHover);
	});
	google.maps.event.addListener(trkpoint, "mouseout", function() {
		trkpoint.setIcon(imageNormal);
	});
	google.maps.event.addListener(trkpoint, "drag", function() {
		for (var i = 0; i < trkpoints.length; i++) {
			if (trkpoints[i] == trkpoint) {
				polyLine.getPath().setAt(i, trkpoint.getPosition());
				moveMidpoint(i);
				break;
			}
		}
		polyPoints = polyLine.getPath();
	});
	google.maps.event.addListener(trkpoint, "click", function() {
		for (var i = 0; i < trkpoints.length; i++) {
			if (trkpoints[i] == trkpoint && trkpoints.length != 1) {
				trkpoint.setMap(null);
				trkpoints.splice(i, 1);
				polyLine.getPath().removeAt(i);
				removeMidpoint(i);
				break;
			}
		}
		polyPoints = polyLine.getPath();
	});
	return trkpoint;
}
function setMidpoints(point) {
	var prevPoint = trkpoints[trkpoints.length-2].getPosition();
	var trkpoint = new google.maps.Marker({
		position: new google.maps.LatLng(
			point.lat() - (0.5 * (point.lat() - prevPoint.lat())),
			point.lng() - (0.5 * (point.lng() - prevPoint.lng()))
		),
		map: map,
		icon: imageNormalMidpoint,
		raiseOnDrag: false,
		draggable: true
	});
	google.maps.event.addListener(trkpoint, "mouseover", function() {
		trkpoint.setIcon(imageNormal);
	});
	google.maps.event.addListener(trkpoint, "mouseout", function() {
		trkpoint.setIcon(imageNormalMidpoint);
	});
	google.maps.event.addListener(trkpoint, "dragend", function() {
		for (var i = 0; i < midpoints.length; i++) {
			if (midpoints[i] == trkpoint) {
				var newpos = trkpoint.getPosition();
				var startMarkerPos = trkpoints[i].getPosition();
				var firstVPos = new google.maps.LatLng(
					newpos.lat() - (0.5 * (newpos.lat() - startMarkerPos.lat())),
					newpos.lng() - (0.5 * (newpos.lng() - startMarkerPos.lng()))
				);
				var endMarkerPos = trkpoints[i+1].getPosition();
    			var secondVPos = new google.maps.LatLng(
    				newpos.lat() - (0.5 * (newpos.lat() - endMarkerPos.lat())),
    				newpos.lng() - (0.5 * (newpos.lng() - endMarkerPos.lng()))
    			);
    			var newVMarker = setMidpoints(secondVPos);
    			newVMarker.setPosition(secondVPos);//apply the correct position to the midpoint
    			var newMarker = setTrkpoints(newpos);
    			trkpoints.splice(i+1, 0, newMarker);
    			polyLine.getPath().insertAt(i+1, newpos);
    			trkpoint.setPosition(firstVPos);
    			midpoints.splice(i+1, 0, newVMarker);
    			break;
    		}
    	}
		polyPoints = polyLine.getPath();
	});
	return trkpoint;
}
function moveMidpoint(index) {
	var newpos = trkpoints[index].getPosition();
	if (index != 0) {
		var prevpos = trkpoints[index-1].getPosition();
		midpoints[index-1].setPosition(new google.maps.LatLng(
			newpos.lat() - (0.5 * (newpos.lat() - prevpos.lat())),
			newpos.lng() - (0.5 * (newpos.lng() - prevpos.lng()))
		));
	}
	if (index != trkpoints.length - 1) {
		var nextpos = trkpoints[index+1].getPosition();
		midpoints[index].setPosition(new google.maps.LatLng(
			newpos.lat() - (0.5 * (newpos.lat() - nextpos.lat())),
			newpos.lng() - (0.5 * (newpos.lng() - nextpos.lng()))
		));
	}
	calculateDistance();
}
function removeMidpoint(index) {
	if (trkpoints.length > 0) {//clicked marker has already been deleted
		if (index != trkpoints.length) {
			midpoints[index].setMap(null);
			midpoints.splice(index, 1);
		} 
		else {
			midpoints[index-1].setMap(null);
    		midpoints.splice(index-1, 1);
		}
	}
	if (index != 0 && index != trkpoints.length) {
		var prevpos = trkpoints[index-1].getPosition();
		var newpos = trkpoints[index].getPosition();
    	midpoints[index-1].setPosition(new google.maps.LatLng(
    		newpos.lat() - (0.5 * (newpos.lat() - prevpos.lat())),
    		newpos.lng() - (0.5 * (newpos.lng() - prevpos.lng()))
    	));
	}
	calculateDistance();
}

function addField (type,dataDiv,fieldName,value,fieldLabel,fieldClass) { 
	//add a form field to document, containing map data
	//type is either 'hidden','input', or 'textarea'
	//if the field already exists, update its value
	if (document.getElementById(fieldName)) { 
		if (type == 'textarea') 
			document.getElementById(fieldName).innerHTML=value;
		else document.getElementById(fieldName).value=value;
	}
	else { //field doesn't exist yet. Create it
		var thisDiv = document.getElementById(dataDiv);
		if (type != 'hidden') { 
			//add a label
			var newLabel = document.createElement('label');
			newLabel.setAttribute('for',fieldName); 
			var thisLabel = thisDiv.appendChild(newLabel);
			var labelText = document.createTextNode(fieldLabel);
			thisLabel.appendChild(labelText);
		}
		//add the form field
		if (type == 'input' || type == 'hidden') { 
			var newInput = document.createElement('input');
			if (type  == 'input') newInput.setAttribute('type','text'); 
			else newInput.setAttribute('type','hidden'); 
			newInput.setAttribute('name',fieldName); 
			newInput.setAttribute('id',fieldName); 
			if (fieldClass) newInput.setAttribute('class',fieldClass);
			if (fieldName.substr(0,5)=='trkpt') { 
				var lat = value.lat();
				var lng = value.lng();
				value = lat + ',' + lng;
			}
			newInput.setAttribute('value',value);
			if (type == 'input') thisLabel.appendChild(newInput);
			else thisDiv.appendChild(newInput);
		}
		else if (type == 'textarea') { 
			var newField = document.createElement('textarea');
			newField.setAttribute('rows','5');
			newField.setAttribute('name',fieldName); 
			newField.setAttribute('id',fieldName); 
			if (fieldClass) newField.setAttribute('class',fieldClass);
			if (fieldName == 'trkroute') newField.setAttribute('readonly','readonly');
			var thisTextArea = thisLabel.appendChild(newField);
			var newDesc = document.createTextNode(value);
			thisTextArea.appendChild(newDesc);
		}
	}
}

function placeMarker() {
	if (placemarking) { 
		//toggle button off
		select("btn_hand");
	}
	else { 
		select("btn_placemark");
		placemarking = true;
		markerFollowsCursor(); 
		var tip = 'Click a point on the map to add a placemark.';
		addTip(tip);
	}
}

function getMarkerPrompt(latLng) {

	var markerName = 'wpt' + String(placemarkIndex + 1); //don't start on 0 
	var prompt = '<div id="markerForm">';
	prompt += '<input type="hidden" name="markerName" id="markerName" value="' + markerName + '"/>';
	prompt += '<input type="hidden" name="wptLatLng" id="wptLatLng" value="' + latLng + '"/>';
	prompt += '<div><label id="wptNameLabel" for="wptName">Name: </label><br/>';
	prompt += '<input type="text" name="wptName" id="wptName"/></div>';
	prompt += '<div><label for="wptDesc">Description: </label><br/>';
	prompt += '<textarea rows="5" name="wptDesc" id="wptDesc"/></textarea></div>';
	prompt += '<div><input type="button" class="button" value="Save &amp; Close" ';
	prompt += 'onclick="processInfoWindow()"/></div>';	
	prompt += '</div>';
	return prompt;
}

function processInfoWindow() {
	//get data that was submitted by user. 
	var markerName = document.getElementById('markerName').value;
	var wptName = document.getElementById('wptName').value;
	var wptDesc = document.getElementById('wptDesc').value;
	var wptLatLng = document.getElementById('wptLatLng').value;
	//wptName is a required field. If user skipped it, don't close infowindow 
	if (wptName == '') { 
		//draw attention to the required field
		document.getElementById('wptName').style.backgroundColor='#ff3';
		document.getElementById('wptNameLabel').innerHTML = 'Name (<span style="color:#f00">required</span>):';
	}
	else { 
		//user completed the infoWindow form
		//use their input to update wayPoint div and marker 
		var thisIndex = (markers.length)-1;
		var wptId = 'wpt' + String(thisIndex);
		//change title of the new marker to wptName
		var thisMarker = markers[thisIndex];
		thisMarker.setTitle(wptName);
		addWaypointDiv(wptId,wptName,wptDesc,wptLatLng); 
		infoWindow.close();
		var tip = 'Done. To add another placemark, click the <em>marker</em> button. ';
		tip += 'Name and descriptions of all placemarks can be edited below.';
		addTip(tip);	
		select ('btn_hand');
	}
}

function addWaypointDiv (wptId,wptName,wptDesc,wptLatLng) {
	//add a waypoint div to DOM, containing a form field with map data
	//if field already exists, just change its coordinates 
	if (document.getElementById(wptId)) { 
		var latLngField = wptId + 'LatLng';
		if (document.getElementById(latLngField)) { 
			document.getElementById(latLngField).value=wptLatLng;
		}
	}
	else { 
		var waypointsDiv = document.getElementById('waypoints');
		if (waypointsDiv) {
			//create a new div for this waypoint, and append it to div#waypoints
			var wptDiv = document.createElement('div');
			wptDiv.setAttribute('id',wptId);
			wptDiv.setAttribute('class','waypoint');
			var thisDiv = waypointsDiv.appendChild(wptDiv);
			//add a heading
			var newHeading = document.createElement('h3'); 
			var thisHeading = thisDiv.appendChild(newHeading);
			if (wptName == 'Start') var headingText = document.createTextNode('Start of Route');
			else if (wptName == 'End') var headingText = document.createTextNode('End of Route');
			else var headingText = document.createTextNode(wptName);
			thisHeading.appendChild(headingText);
			//add an X button to close (and delete) this waypoint div
			var xButton = document.createElement('input');
			xButton.setAttribute('type','button');
			xButton.setAttribute('id','del_' + wptId);
			xButton.setAttribute('title','Delete this Waypoint');
			xButton.setAttribute('class','xButton');
			xButton.setAttribute('value','X');
			xButton.setAttribute('onclick',"deleteWaypoint('" + wptId + "')");
			xButton.setAttribute('onkeypress','this.click()');
			thisDiv.appendChild(xButton);
			//add form fields
			var nameField = wptId + 'Name';
			var descField = wptId + 'Desc';
			var latlngField = wptId + 'LatLng';
			addField('input',wptId,nameField,wptName,'Name :','wptName');
			addField('textarea',wptId,descField,wptDesc,'Brief Description :','wptDesc');
			addField('hidden',wptId,latlngField,wptLatLng);
		}
	}
}

function updateWaypointDivIds() { 

	//waypoint div @id attributes needs to stay in synch with the markers array 
	//this function is called whenver markers are removed from array
	//divs appear in the dom in the order in which they were added to the array, so this is easy
	var allDivs = document.getElementsByTagName('div'); 
	var numDivs = allDivs.length;
	var numWaypoints = 0;
	for (i=0; i<numDivs; i++) { 
		if (allDivs[i].className == 'waypoint') { 
			var oldId = allDivs[i].id;
			var newId = 'wpt' + String(numWaypoints);
			if (oldId != newId) { 
				var oldNameField = oldId + 'Name';
				var oldDescField = oldId + 'Desc';
				var oldLatLngField = oldId + 'LatLng';
				var oldXButtonId = 'del_' + oldId;
				var newNameField = newId + 'Name';
				var newDescField = newId + 'Desc';
				var newLatLngField = newId + 'LatLng';
				var newXButtonId = 'del_' + newId;
				var newXOnclick = "deleteWaypoint('" + newId + "')";
				allDivs[i].setAttribute('id',newId);
				//now step through div's child elements to replace all of the above
				//allDivs[i].getElementsByTagName('h3')[0] = the heading, no update required
				var theseInputs = allDivs[i].getElementsByTagName('input');
				for (j=0; j<theseInputs.length; j++) { 
					if (theseInputs[j].id==oldXButtonId) { //xButton input
						theseInputs[j].setAttribute('id',newXButtonId); 
						theseInputs[j].setAttribute('onclick',newXOnclick); //xButton input
					}
					else if (theseInputs[j].id==oldNameField) { //Name input	
						theseInputs[j].setAttribute('id',newNameField); 
						theseInputs[j].setAttribute('name',newNameField);
					}
					else if (theseInputs[j].id==oldLatLngField) { //LatLng hidden input	
						theseInputs[j].setAttribute('id',newLatLngField); //LatLng hidden input
						theseInputs[j].setAttribute('name',newLatLngField); //LatLng hidden input
					}
				}
				var theseLabels = allDivs[i].getElementsByTagName('label');
				for (j=0; j<theseLabels.length; j++) { 
					if (theseLabels[j].getAttribute('for')==oldNameField) { //Name label
						theseLabels[j].setAttribute('for',newNameField);
					}
					else if (theseLabels[j].getAttribute('for')==oldDescField) { //Desc label
						theseLabels[j].setAttribute('for',newDescField);
					}
				}
				var theseTextareas = allDivs[i].getElementsByTagName('textarea');
				theseTextareas[0].setAttribute('id',newDescField); //Desc textarea
				theseTextareas[0].setAttribute('name',newDescField); //Desc textarea
			}
			numWaypoints++;			
		}
	}
}

function markerFollowsCursor(){
	if (whichMap == 'addaroute') var markerColor = 'blue';
	else var markerColor = 'red';
	var icon = 'http://maps.google.com/mapfiles/ms/micons/' + markerColor + '-dot.png';
	following = true;
	var noMore = false;
	mouseMoveListener = google.maps.event.addListener(map, 'mousemove', function(event){
		if(!noMore){ 
			markerCursor = new google.maps.Marker({
				icon: icon,
				map: map,
				draggable: true,
				autoPan: false,
				title: 'Click to place marker on the map'
			});
			noMore = true; 
		}
		if (following){
			markerCursor.setPosition(event.latLng);
		}
	});
}

function showNoMap() { 
	//unable to display map due to missing coordinates  
	//remove all map-related divs (which are all nested within #googleMap)
	if (document.getElementById('googleMap')) {
		var mapDiv = document.getElementById('googleMap');
		if (mapDiv.hasChildNodes()) { 
			while (mapDiv.childNodes.length >= 1) {
				mapDiv.removeChild(mapDiv.firstChild);       
			} 
		}
		//now replace the deleted content with a message
		var noMap = document.createElement('div');
		noMap.setAttribute('id','noMap');
		var msgHeading = document.createElement('h2');
		msgHeading.innerHTML = 'No Map Available';
		var msgP = document.createElement('p');
		var msg = 'We are unable to display a map for this peak '; 
		msg += 'because we are missing its latitude or longitude. ';
		msg += 'If you know this peak\'s coordinates please ';
		msg += '<a href="contactus.html">contact us</a>. ';
		msgP.innerHTML = msg;
		noMap.appendChild(msgHeading);
		noMap.appendChild(msgP);
		mapDiv.appendChild(noMap);
	}
}

function doNothing() {} 

if (window.addEventListener) {
	window.addEventListener('load', initMap, false);
}
else if (window.attachEvent) {
	window.attachEvent('onload', initMap);
}
else {
	document.addEventListener('load', initMap, false);
} 

