/* 
* @version      $Revision: 4 $
* @modifiedby   $LastChangedBy: cyberian_vincentwaller $
* @lastmodified $Date: 2008-02-21 15:32:54 -0800 (Thu, 21 Feb 2008) $
*/

var center_lat_param = 0;
var center_lng_param = 0;
var zoom_param = 0;
var maptype_param = "normal";

var started = true;
var map;
var geocoder;
var lines_ovl = new Array();
var distances = new Array();
var symbols = new Array();
var message;
var p = 10000;  // precision
var next_symbol = "default";
var auto_center = 0;
var movedmarker;
var mileage_markers = 0; // Mileage markers turned on or off?
var mileage_marker_list = new Array();
var dragMarker;
var BDragging;
var MouseOverMarker;

var mapID; // Tag ID for map DIV
var summaryID; // Tag ID for mileage text
var elevation_profileID; //Tag ID for elevation profile graph
var mapWidth;
var mapHeight;
var base_dir;
var marker_dialog_images_dir;

var save_route_form_submit;
var graphtopo_path;
var RideID;
var RideName = "Route";
var map_mode;

var show_elevation = 0; // Dislay elevation profile?

var follow_roads = 0;
// == use different GDirections for adding and dragging, it is just simpler that way ==
var mapdir = [];
var dirn1;
var dirn2;
var dirn3;

var dir2Loaded = false;
var dir3Loaded = false;

var global_icons = new Array();
var do_load_points = 0;
var do_load_url = false;
var MapData = new MapDataType();
var oldMapData = new MapDataType();
document.onkeyup = keyPressed;
var ignore_key_commands = false;

var current_point; //Last clicked point, used for infoWindow functions like changeMarker

var bool_fetch_directions = false;  // bool if directions should be fetched and saved
var saveRouteForm;

// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
GPolyline.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getVertex(0);
  if (metres < 0) return null;
  var dist=0;
  var olddist=0;
  for (var i=1; (i < this.getVertexCount() && dist < metres); i++) {
    olddist = dist;
    dist += this.getVertex(i).distanceFrom(this.getVertex(i-1));
  }
  if (dist < metres) {return null;}
  var p1= this.getVertex(i-2);
  var p2= this.getVertex(i-1);
  var m = (metres-olddist)/(dist-olddist);
  return new GLatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m);
};


function PointSort (a, b) {
  return a._pos - b._pos;
}

function getUploadFormSubmit() {
	return upload_form_submit;
}

function RBRMap() {
	this.mapElement = "map";
	this.summaryElement = "summary";
	this.elevation_profileElement = "elevation_profile";
	this.width =650;
	this.height = 550;
	this.base_dir = "";
	this.marker_dialog_images_dir = "marker_dialog_images/";
	this.save_route_form_submit = "saveroute.php";
	this.graphtopo_path = "http://www.roadbikerides.com/MappingSystem/graphtopo.php";
	this.RideID = "123";
	this.map_mode = "edit";
}

RBRMap.prototype.init = function() {
	base_dir = this.base_dir;
	marker_dialog_images_dir = this.marker_dialog_images_dir;
	save_route_form_submit = this.save_route_form_submit;
	map_mode = this.map_mode;
	graphtopo_path = this.graphtopo_path;
	RideID = this.RideID;
	loadMap(this.mapElement, this.summaryElement, this.elevation_profileElement, this.width, this.height);
}

function MapDataType()  {
    this._lat_min = 10000;
    this._lat_max = -10000;
    this._lng_min = 10000;
    this._lng_max = -10000;
    this._points = new Array();
}
MapDataType.prototype._points = new Array();
MapDataType.prototype._waypoints = new Array();
MapDataType.prototype._distance = 0;
MapDataType.prototype._removeMode = 0;
MapDataType.prototype._noline_mode = 0;
MapDataType.prototype._readonly_mode = 0;
MapDataType.prototype._hidepoints_mode = 0;
MapDataType.prototype._points_added = false;
MapDataType.prototype._import_all_tracks = true;
MapDataType.prototype._last_track_name = "";
MapDataType.prototype._this_track_name = "";
MapDataType.prototype._import_running = false;
MapDataType.prototype._points_need_resampling = false;
MapDataType.prototype._waypoint_mode = "";
MapDataType.prototype._next_waypoint_name = "Waypoint Name";
MapDataType.prototype._importedPoints = new Array();

MapDataType.prototype.addPoint = function(point, symbol, line, directions) {
	
	if(this._import_running && this._points_need_resampling){
		this._importedPoints.push([point.y,point.x,symbol]);
		return;
	}

    if (this._lat_min > point.lat())
        this._lat_min = point.lat();
    if (this._lat_max < point.lat())
        this._lat_max = point.lat();
    if (this._lng_max < point.lng())
        this._lng_max = point.lng();
    if (this._lng_min > point.lng())
        this._lng_min = point.lng();

    var pt = new MyPoint(point);
    if (symbol && symbol != "default") {
        pt._wpname = symbol;
    }
    pt._sym = symbol;
    pt._pos = this._points.length;
		if(this._points.length > 0) pt._directions = directions;

		this._points.push(pt);

		var p_last = this._points[pt._pos-1];
		if(!p_last) p_last = pt;
		if(p_last) 
		{
			// retrieving directions for all points at same time on submit instead and new points being done already  
			// fetchMapDirections([p_last, pt], false);
		}
		
    if (pt._pos == 0) {
        updateMarker(pt, "start", "Start of Track");
    }
    else if (pt._pos > 0) {
		if (line){
			pt._line = line;
			pt._distfromlast = line.getLength();
			this._distance += pt._distfromlast;
		}else{
			var p_last = this._points[pt._pos-1];
			pt._distfromlast = p_last._point.distanceFrom(pt._point);
			this._distance += pt._distfromlast;
		}
    }
    
    if (!this._import_running ) {
		if(line){
			updateMarker(pt, pt._sym);
			map.addOverlay(line);
			GEvent.addListener(line, "click", lineClicked);
		}else{
	        this.drawPoint(pt);
		}
		if(mileage_markers){
			this.drawMileageMarkers();
		}
		UpdateGraph();
        printSummary();
    }
};

function fetchMapDirections(points, bool_submit)
{
	if(!points.length) return;
	
  var maxpoints = 25;
	var coords = [];
	var subcoords = [];
	var subpoints = [];

  for(var i=0; i < points.length; i++)
  {
  	coords.push(points[i]._point.toUrlValue(6));
  }

	var steps = Math.ceil(points.length / maxpoints);
	
	for(var step=0; step < steps; step++)
	{
		var index = mapdir.length;
		var laststep = steps - 1;
		
		var firstindex = step * maxpoints;
		var subcoords = coords.slice(firstindex, maxpoints);
		var subpoints = points.slice(firstindex, maxpoints);

	/*
		var tmp = subcoords.reverse();
		var tmp = subpoints[firstindex]._pos == 0 ? tmp.push(subcoords[0]) : tmp.push(subcoords[firstindex-1]);
		subcoords = subcoords.reverse();
	*/	
		if(subcoords.length)
		{
			mapdir[index] = new GDirections();
			mapdir[index].index = index;
		  mapdir[index].coords = subcoords;
		  mapdir[index].points = subpoints;
		  mapdir[index].bool_submit = (step == laststep) ? bool_submit : false;
		
		  // get directions for added point
		 	GEvent.addListener(mapdir[index],"error", function() {
		    alert("Directions Failed: "+this.getStatus().code);
		  });
		  GEvent.addListener(mapdir[index],"load", function() {
		  	
		  	var gcoder = new GClientGeocoder();  
		  	var gstatus = this.getStatus();
		  	var points = this.points;
		  	var bool_submit = this.bool_submit;
		  	var index = this.index;
		  	//alert(index+" loaded");
				/*
				Returns the status of the directions request. The returned object has the following form: 
				{
				  code: 200
				  request: "directions"
				}
				The status code can take any of the values defined in GGeoStatusCode.   http://code.google.com/apis/maps/documentation/reference.html#GGeoStatusCode
				Constant Description 
				G_GEO_SUCCESS
				= 200  No errors occurred; the address was successfully parsed and its geocode has been returned. 
				(Since 2.55)
				 
				G_GEO_BAD_REQUEST
				= 400  A directions request could not be successfully parsed. For example, the request may have been rejected if it contained more than the maximum number of waypoints allowed. 
				(Since 2.81)
				 
				G_GEO_SERVER_ERROR
				= 500  A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known. 
				(Since 2.55)
				 
				G_GEO_MISSING_QUERY
				= 601  The HTTP q parameter was either missing or had no value. For geocoding requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input. 
				(Since 2.81)
				 
				G_GEO_MISSING_ADDRESS
				= 601  Synonym for G_GEO_MISSING_QUERY. 
				(Since 2.55)
				 
				G_GEO_UNKNOWN_ADDRESS
				= 602  No corresponding geographic location could be found for the specified address. This may be due to the fact that the address is relatively new, or it may be incorrect. 
				(Since 2.55)
				 
				G_GEO_UNAVAILABLE_ADDRESS
				= 603  The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons. 
				(Since 2.55)
				 
				G_GEO_UNKNOWN_DIRECTIONS
				= 604  The GDirections object could not compute directions between the points mentioned in the query. This is usually because there is no route available between the two points, or because we do not have data for routing in that region. 
				(Since 2.81)
				 
				G_GEO_BAD_KEY
				= 610  The given key is either invalid or does not match the domain for which it was given. 
				(Since 2.55)
				 
				G_GEO_TOO_MANY_QUERIES
				= 620  The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you're sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don't send the requests too quickly. 
				(Since 2.55)
				*/
		  	var routeCount = this.getNumRoutes(); //Returns the number of routes available in the result. For a successful query, this should be the total number of input waypoints minus 1. When no results are available (either because no query was issued or because the previous query was unsuccessful), this method returns 0. 
				var directions = [];
				var stats = [];
				var coords = this.coords;

				if(0) // Testing coordinates to see if polyline equal to google line for following path
				{
					var n = polyline.getVertexCount();
					var pts = new Array();
					for (var i=0; i<n; i++)
					{
						pts.push(this.getPolyline().getVertex(i));
					}
					var encodedLine2 = createEncodings(pts);
					
			   /*
					var linePts = new Array();
					for(var i=0; i < points.length; i++)
					{
						linePts.push(points[i]._point);
					}
					*/
			    var polyline = new GPolyline(linePts);
					var n = polyline.getVertexCount();
					var linePts = new Array();
					for (var i=0; i<n; i++){
						linePts.push(polyline.getVertex(i));
					}	
					var encodedLine = createEncodings(linePts);
									
					alert(linePts.length + ' ' + encodedLine + '\n'+pts.length+' '+encodedLine2);
				}
				
		  	if(1) //routeCount == this.coords.length-1
		  	{
					////if(routeCount > points.length-1) alert('steps: '+routeCount.length+' points: '+points.length);
		  		stats.push('route count: '+routeCount);
		  		
		  		//if(!routeCount) alert('no routes');
					for(var x=0; x < routeCount; x++ ) 
					{
						var groute = this.getRoute(x);
						var stepCount = groute.getNumSteps();
						////if(stepCount > 1) alert('steps: '+stepCount);
		  			
		  			stats.push('geocodes: '+this.getNumGeocodes()); //Returns the number of geocoded entries available in the result. For a successful query, this should be equal to the total number of input waypoints. When no results are available (either because no query was issued or because the previous query was unsuccessful), this method returns 0.
		  			stats.push('coords: '+this.coords.length);
		  			stats.push('route '+x+' step count: '+stepCount);
	
						if(0) // TEST OUTPUT
						{
							for ( var i=0; i < groute.getNumSteps(); i++ ) {
									directions += groute.getStep(i).getDescriptionHtml() + "<BR>";
							}
						}
						
						if(1) //stepCount == this.coords.length-1)
						{
							var tmp = [];
		  				//if(!stepCount) alert('no routes');
							for( var i=0; i < stepCount; i++ ) 
							{
		  					var str = groute.getStep(i).getDescriptionHtml();
		  					if(str.match("google_note") || directions.join('').match(str)) continue;
		  					tmp.push(str);
							}
							
							directions.push(tmp.join("<br>"));
						}
					}
				}
				
				for(var i=0; i < directions.length; i++)
				{
					var direction = directions[i];
					var pointindex = points[i]._pos;  // route return starts at 1st point
					// Not sure if should do this, maybe wait until submit function
		  		/////if(direction.match("google_note") || directions.join('').match(direction)) continue;
					MapData._points[pointindex]._directions = direction;
					//alert([pointindex, direction, MapData._points[pointindex]._directions]);
					stats.push('point '+pointindex+' direction: '+direction);
				}	 				
	 			
	 			//alert(directions.join('\n'));

		  	if(0) // FOR TESTING
		  	{
		  		alert('map '+index+'\n'+stats.join('\n')+' '+'\ndirections:  '+MapData._directions+' \ncoords: \n'+coords.join("\n"));
		  		return;
		  	}
				
				if(bool_submit)
				{
					SubmitRoute();
				}
							
		  });
		  
			// fetch directions
		  mapdir[index].loadFromWaypoints(subcoords,{getPolyline:true, getSteps:true});
		}
	}
}

MapDataType.prototype.resamplePoints = function() {
	if(this._importedPoints.length > 300){
		var resampledCoordinates = ResampleCoordinates(this._importedPoints,300); 	
	}else{
		var resampledCoordinates = this._importedPoints;
	}
	this._points_need_resampling = false;
	for(var i = 0; i < resampledCoordinates.length; i++){
		this.addPoint(new GLatLng(resampledCoordinates[i][0],resampledCoordinates[i][1]),resampledCoordinates[i][2]);
	}
}

MapDataType.prototype.addFollowRoadsPoint = function(point, line) {
    var pt = new MyPoint(point);
    pt._pos = this._points.length;
    pt._line = line;
    this._points.push(pt);
    updateMarker(pt, pt._sym);

};

MapDataType.prototype.drawMileageMarkers = function() {
	var all_pts = getAllPoints();
	var polypoints = new Array();
	var markerNum = 0;
	
	for(var i = 0; i < all_pts.length; i++){
		polypoints.push(all_pts[i]._point);
	}
    var polyline = new GPolyline(polypoints);
	var polylength = (polyline.getLength()/1000)*0.621371192;
	for (var miles = 5.0; miles < polylength; miles+=5.0){
		var cur_meters = miles * 1000/0.621371192;
		var marker_pt = polyline.GetPointAtDistance(cur_meters);
		markerNum = miles / 5;
		if(!mileage_marker_list[markerNum-1]){
		    var icon = getIcon(getMileageMarkerName(miles));
		    var opts = {draggable: false, clickable:false, icon: icon, title: ""};
			var marker = new GMarker(marker_pt, opts);
			map.addOverlay(marker);
			mileage_marker_list.push(marker);
		}else{
			map.removeOverlay(mileage_marker_list[markerNum-1]);
		    var icon = getIcon(getMileageMarkerName(miles));
		    var opts = {draggable: false, clickable:false, icon: icon, title: ""};
			var marker = new GMarker(marker_pt, opts);
			map.addOverlay(marker);
			mileage_marker_list.splice(markerNum-1, 1, marker);
		}
	}
	while(markerNum < mileage_marker_list.length){
		map.removeOverlay(mileage_marker_list[markerNum]);
		mileage_marker_list.splice(markerNum, 1);
	}
};

MapDataType.prototype.hideMileageMarkers = function() {
	
};

MapDataType.prototype.insertPoint = function(point, insertpos, line) {
    var pt = new MyPoint(point);
    pt._pos = insertpos+1;
    
	for (var i=pt._pos; i < this._points.length; i++) {
	  var p = MapData._points[i];
	  p._pos++;
	}

	if (line){
		pt._line = line;
	}
	
	this._points.push(pt);
	MapData._points.sort(PointSort);
	
	var p_last = this._points[pt._pos-1];
	pt._distfromlast = p_last._point.distanceFrom(pt._point);
	
};

MapDataType.prototype.getDirections = function(point) {
    if (this._points.length ==0){
		dirn1.loadFromWaypoints([point.toUrlValue(6),point.toUrlValue(6)],{getPolyline:true, getSteps:true});
	}else{
		var last_pt = this._points[this._points.length-1]._point;
		dirn1.loadFromWaypoints([last_pt.toUrlValue(6),point.toUrlValue(6)],{getPolyline:true, getSteps:true});
	}
};

MapDataType.prototype.addWayPoint = function(point, type, wpname) {

    if (this._lat_min > point.lat())
        this._lat_min = point.lat();
    if (this._lat_max < point.lat())
        this._lat_max = point.lat();
    if (this._lng_max < point.lng())
        this._lng_max = point.lng();
    if (this._lng_min > point.lng())
        this._lng_min = point.lng();

    var pt = null;

    for (var i=0; i < this._points.length; i++) {
      if (MapData._points[i]._point.lat() == point.lat() && MapData._points[i]._point.lng() == point.lng()) {
          pt = MapData._points[i];
          break;
      }
    }
    
    if (pt == null) {
        // not found ->> draw seperately
        pt = new MyPoint(new GLatLng(point.lat(), point.lng()));
        this._waypoints.push(pt);
    }

    if (wpname.match(/left/i) || wpname.match(/links/i)) {
        type="Left";
    } else if (wpname.match(/Right/i) || wpname.match(/Rechts/i)) {
        type="Right";
    } else if (wpname.match(/Continue/i)  || wpname.match(/Straight/i)  || wpname.match(/Weiter/i)) {
        type="Straight";
    } 
    if (wpname != "" && (!type || type == "" || type == "default" )) {
        type="Waypoint";
    }

    pt._wpname = wpname;
    pt._sym = type;
    if (!this._import_running) {
        updateMarker(pt, type, wpname);
    }
};

MapDataType.prototype.drawPoint = function(pt) {
    
    if (pt._pos > 0) {
        var p_last = this._points[pt._pos-1];
		if (!pt._line){
			var line = null;
			if (!MapData._readonly_mode) {
				line = drawLine(p_last._point, pt._point);
				updateMarker(pt, pt._sym);
			}
			pt._line = line;
		}else{
			updateMarker(pt, pt._sym);
			map.addOverlay(pt._line);
			GEvent.addListener(pt._line, "click", lineClicked);
		}
        
    } else {
      updateMarker(pt, pt._sym);
    }

};

MapDataType.prototype.showTrack = function(forcedraw) {
    
    if (!forcedraw && this._points.length > 2000) {
		if (!confirm("There are more than 2000 segments (" +  this._points.length + ").\n" + 
              "This may crash your browser. Do you really want to display the track?")) {
            MapData._noline_mode = true;
	  	}
	  	/*
        alert("There are more than 2000 segments (" +  this._points.length + "). " + 
              "For Performance reasons, the data is loaded loaded in" +
              " \"Non-Line Mode\". If you know what you are doing, " +
              "you can later switch to another Mode via menu)");
            MapData._noline_mode = true;
        */
        //MapData._readonly_mode = true;
    } else if (!do_load_url && !forcedraw && this._points.length > 200 && map_mode == "edit") {
			/*
			alert("There are more than " + 200 + " segments (" +  this._points.length + "). " + 
		  	"The data is loaded load in \"Non-Edit Mode\" (If you know what you are doing, " +
		  	"you can later switch to \"Edit Mode\" via menu)");
			*/
  			MapData._hidepoints_mode = true;
        	MapData._readonly_mode = false;
        
    }

    if (MapData._noline_mode) {
    	this.drawWayPoints();
    } else if (MapData._readonly_mode){
    	this.showTrackAsPolyline();
    } else {
    	this.drawAllPoints();
    }

    if (this._points.length > 0) {
        updateMarker(this._points[0], "start", "Start of Track");
        updateMarker(this._points[this._points.length-1], "stop", "End of Track");
    }
    
    for (var i=0; i < this._waypoints.length; i++) {
        var wpt = this._waypoints[i];
        updateMarker(wpt, wpt._sym, wpt._wpname);
    }

    this.setAutoZoomAndCenter();
    saveSettings(false);
    printSummary();
};

MapDataType.prototype.drawAllPoints = function() {
    for (var i=0; i < this._points.length; i++) {
        this.drawPoint(this._points[i]);
    }
};

MapDataType.prototype.drawWayPoints = function() {
    for (var i=0; i < this._waypoints.length; i++) {
        var pt = this._waypoints[i];
        if (pt._sym != "" && pt._wpname != "") {
           updateMarker(pt, pt._sym);
        }
    }
    for (var i=0; i < this._points.length; i++) {
        var pt = this._points[i];
        if (pt._sym != "" && pt._wpname != "") {
           updateMarker(pt, pt._sym);
        }
    }
};

MapDataType.prototype.showTrackAsPolyline = function() {
        
    var points = new Array();
    for (var i=0; i< this._points.length; i++) {
      var pt = MapData._points[i];
      if (pt._sym && pt._sym != "default")
		updateMarker(pt, pt._sym);
		if(pt._line){
			for(var j=0; j< pt._line.getVertexCount(); j++){
				points.push(pt._line.getVertex(j));
			}			
		}
      if (!this._noline_mode )
          points.push(pt._point);
    }

    if (!this._noline_mode ) {
		if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
			var polyline = new GPolyline(points, "#0000ff", 3, 0.7);
		}else{
			var polyline = new BDCCPolyline(points, "#0000ff", 4, 1, "Click to insert point");
		}

		var polyline = new GPolyline(points, "#0000ff", 3);
        map.addOverlay(polyline);
    }


};

MapDataType.prototype.setAutoZoomAndCenter = function() {
	
	if (MapData._waypoint_mode)
		return;
	
    var bounds = new GLatLngBounds(
    new GLatLng(this._lat_min, this._lng_min),
    new GLatLng(this._lat_max, this._lng_max));
        
    var level = map.getBoundsZoomLevel(bounds);
    map.setZoom(level);
    //map.panTo(bounds.getCenter());
    map.setCenter(bounds.getCenter());
};

MapDataType.prototype.replaceMarker = function(overlay) {
    for (var i=0; i < this._points.length; i++) {
        var marker = this._points[i]._marker;
        if (overlay == marker) {
            updateMarker(this._points[i]);
        }
    }
};

MapDataType.prototype.removePoint = function(mypoint) 
{
    if(mypoint._marker)
		map.removeOverlay(mypoint._marker);
    
	if (dragMarker){
		map.removeOverlay(dragMarker);
		dragMarker = null;
	}
		
    var pos = mypoint._pos;
    var p_next = null;
    var p_prev = null;
    
    // replace last line (= this)
    if (pos > 0) {
        p_prev = this._points[pos-1];
        map.removeOverlay(mypoint._line);
    }

    // replace next line if exist (=next)
    if (this._points.length > pos+1) {
        p_next = this._points[pos+1];
        map.removeOverlay(p_next._line);
    }
    
    if (p_next && p_prev) {
		if(follow_roads){
			movedmarker = p_prev;
			dirn3.loadFromWaypoints([p_prev._point.toUrlValue(6),p_next._point.toUrlValue(6)],{getPolyline:true, getSteps:true});
			dir3Loaded = false;
		}else{
	        p_next._line = drawLine(p_prev._point, p_next._point);
    	    p_next._distfromlast = p_prev._point.distanceFrom(p_next._point);
		}
    }
	
	this._points.splice(pos,1);
    
    for (var i=pos; i<this._points.length; i++) {
    	this._points[i]._pos = i;
    }
	
	if(follow_roads && p_prev){
	}
	
	this._distance = 0;
	for (var i=0; i< this._points.length; i++) {
		   this._distance+=this._points[i]._distfromlast;
	}
	
	if(mileage_markers) this.drawMileageMarkers();
	UpdateGraph();
	
	printSummary();
};

MapDataType.prototype.reverseTrack = function() 
{
    if (this._points.length == 0)
        return;

	var startpt = this._points.length-1;
    for (var i=startpt-1; i >= 0; i--) {
		
		if(this._points[i+1]._line){
			
			var points = new Array();
			for(var j=this._points[i+1]._line.getVertexCount()-1; j>=0; j--){
				points.push(this._points[i+1]._line.getVertex(j));
			}
			
			if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
				var poly = new GPolyline(points, "#0000ff", 3, 0.7);
			}else{
				var poly = new BDCCPolyline(points, "#0000ff", 4, 1, "Click to insert point");
			}
			
	    	this.addPoint(this._points[i]._point,"default",poly);
		}else{
	    	this.addPoint(this._points[i]._point);
			
		}
			
    }

};


function MyPoint(point) {
    this._point = point;
}
MyPoint.prototype._point = null;
MyPoint.prototype._sym = "";
MyPoint.prototype._ele = null;
MyPoint.prototype._time = 0.0;
MyPoint.prototype._datetime = null;
MyPoint.prototype._marker = null;
MyPoint.prototype._line = null;
MyPoint.prototype._distfromlast = 0;
MyPoint.prototype._wpname = "";
MyPoint.prototype._notes = "";
MyPoint.prototype._directions = "";


function changeMarker(symbol) {
	updateMarker(current_point, symbol);
	map.closeInfoWindow();
}

function setNotes(noteText) {
	current_point._notes = noteText;
}

function updateMarker(mypoint, symbol, wpname) {
	
	if (!mypoint)
	  return;
	  
	var avail_symbols = new Array("start","stop","coolstop","bathroom","food","water");
	
	var found = false;
	for (cur_symbol in avail_symbols){
		if (avail_symbols[cur_symbol] == symbol){
			found = true;
			break;
		}
	}
	if(!found) symbol = "default";

	if (MapData._hidepoints_mode && (symbol == "" || symbol == "default" || !symbol))
		return;
	
	if (mypoint._marker)
	    map.removeOverlay(mypoint._marker);
    

    if (mypoint._pos == 0)
        mypoint._sym = "start";
    else if (symbol)
        mypoint._sym  = symbol;
    else if (!mypoint._pos) {
    	if (next_symbol != "" && next_symbol != "default")
          mypoint._sym  = next_symbol;
    } else {
		;
        //mypoint._sym  = next_symbol;
    }
    

    var icon = getIcon(mypoint._sym);
    var opts = null;
    var marker = null;
    
    if (MapData._waypoint_mode == "remove") {
    	MapData._waypoint_mode = "";
    	MapData.removeWayPoint(mypoint);
    	return;
    }
	    
    if (wpname && wpname != "") {
        mypoint._wpname = wpname;
    }
    
    if (!MapData._readonly_mode) {
        if (mypoint._wpname != "") {
            opts = {draggable: true, icon: icon, draggableCursor: 'crosshair', 
                    draggingCursor: 'move', title: mypoint._wpname};
        } else {
            opts = {draggable: true, icon: icon, draggableCursor: 'crosshair', 
                    draggingCursor: 'move'};
        }
        marker = new GMarker(mypoint._point, opts);
        
		addMarkerListeners(marker, mypoint);
    } else  {
        if (mypoint._wpname != "") {
            opts = {draggable: false, icon: icon, draggableCursor: 'crosshair', 
                    draggingCursor: 'move', title: mypoint._wpname};
        } else {
			if (mypoint._notes != ""){
				opts = {draggable: false, icon: icon, draggableCursor: 'crosshair', 
						draggingCursor: 'move'};
			}else{
				opts = {draggable: false, clickable:false, icon: icon};
			}
        }
        marker = new GMarker(mypoint._point, opts);
		
		if(mypoint._notes != "") {
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowHtml(mypoint._notes);
			});
		}
		
    }

    map.addOverlay(marker);
    mypoint._marker = marker;
}

function markerMoved(mypoint, newloc) 
{
    var pos = mypoint._pos;
	if(newloc){
		mypoint._point = newloc;
		if(mypoint._marker) mypoint._marker.setPoint(newloc);
	}else{
	    mypoint._point = mypoint._marker.getPoint();
	}

	// replace last line (= this)
	if (pos > 0) {
		var p_last = MapData._points[pos-1];
		map.removeOverlay(mypoint._line);
		mypoint._line = drawLine(p_last._point, mypoint._point);
		mypoint._distfromlast = p_last._point.distanceFrom(mypoint._point);
		mypoint._directions = "";
	}

	// replace next line if exist (=next)
	if (MapData._points.length > pos+1) {
		var p_next = MapData._points[pos+1];
		map.removeOverlay(p_next._line);
		p_next._line = drawLine(mypoint._point, p_next._point);
		p_next._distfromlast = mypoint._point.distanceFrom(p_next._point);
		p_next._directions = "";
	}
	
	MapData._distance = 0;
	for (var i=0; i< MapData._points.length; i++) {
		   MapData._distance+=MapData._points[i]._distfromlast;
	}
	
	if(mileage_markers){
		MapData.drawMileageMarkers();
	}
	UpdateGraph();

	
	printSummary();
	
	var pt = mypoint._point;

	if (auto_center) {
		map.panTo(pt);
	}
}

function followRoadsMarkerMoved(mypoint, destpt){
    var pos = mypoint._pos;
	if (destpt){
		mypoint._point = destpt;
	}else{
	    mypoint._point = mypoint._marker.getPoint();
	}
	movedmarker = mypoint;
		
	if (pos > 0){
		// recalculate the polyline preceding this point
		var p_last = MapData._points[pos-1];
		map.removeOverlay(mypoint._line);
		dirn2.loadFromWaypoints([p_last._point.toUrlValue(6),mypoint._point.toUrlValue(6)],{getPolyline:true, getSteps:true});
		dir2Loaded = false;
	}else{
		dir2Loaded = true;
	}
	
	if (MapData._points.length > pos+1) {
		// recalculate the polyline following this point
		var p_next = MapData._points[pos+1];
		map.removeOverlay(p_next._line);
		dirn3.loadFromWaypoints([mypoint._point.toUrlValue(6),p_next._point.toUrlValue(6)],{getPolyline:true, getSteps:true});
		dir3Loaded = false;
	}else{
		dir3Loaded = true;
	}
	
}


function addPoint(point, symbol, line, directions) {
    MapData.addPoint(point, symbol, line, directions);
}

function removePoint() {
	MapData.removePoint(current_point);
}

function drawAllPoints(){
	MapData.drawAllPoints();
}

function insertPoint(point, insertpos, line) {
    MapData.insertPoint(point, insertpos, line);
}

function addPoints(str) {
    
    if (MapData._points_added) {
		if (confirm("There are more than one track in this file. The first Track is imported. Do you want to import also the track \"" 
		+ MapData._this_track_name + "\"?\n" +
		        "Press Cancel to skip")) {
            MapData._import_all_tracks = true;
	  	} else {
	  	    MapData._last_track_name = "";
  			return;
	  	}
    }
    
    var s = str.replace(/\s+/g, " ");
    s = s.replace(/^\s*/, "");
    s = s.replace(/\s*$/, "");
    var points = s.split(" ");
    //MapData._readonly_mode = (points.length > 200);

    for (var i=0; i<points.length; i++) {
        var fields = points[i].split(",");
        var lng = parseFloat(fields[0]);
        var lat = parseFloat(fields[1]);
        var ele = parseFloat(fields[2]);
        MapData.addPoint(new GLatLng(lat, lng));
        
        // PF 11.23.08 If we are resampling points, then we should throw away elevation data and retrieve the elevation data for the new points, when necessary
		if ((!MapData._points_need_resampling) && (ele && ele > 0))
            setEle(ele);
    }
    
    MapData._points_added = true;
}

function addWayPoint(point, type, wpname) {
    MapData.addWayPoint(point, type, wpname);
}

function addWayPointYXZ(y, x, z, type, wpname) {
    if (!wpname) {
        wpname = type;
        // type = z;
    }
    
    MapData.addWayPoint(new GLatLng(x, y), type, wpname);
}

function setEle(ele) {
    if (ele && ele != -1) {
        var lastpoint = MapData._points[MapData._points.length-1];
        lastpoint._ele = ele;
    }
}

function setTime(datetime) {
    if (datetime && datetime != "") {
        var lastpoint = MapData._points[MapData._points.length-1];
        lastpoint._datetime = datetime;
    }
}

function setCourseName(str) {
    str = str.replace(/<[^>]*>/g, "");
    if (str == "") {
        return;
    }
    //document.getElementById("courseName").value = str;
}

function startTrack() {
}


/** called from generated javascript code. */
function showTrackAsPolyline() {
    MapData.showTrackAsPolyline();
}

function gotoStart() {
	if(MapData._points.length > 0){
		var newCenterpt = MapData._points[0]._point;
		map.panTo(newCenterpt);
	}
}

function gotoEnd() {
	if(MapData._points.length > 0){
		var newCenterpt = MapData._points[MapData._points.length-1]._point;
        map.panTo(newCenterpt);
	}
}

function removeLastPoint() {
    
    if (MapData._readonly_mode)
        return;
    
    if (MapData._points.length < 1) {
      return;
    }
    
    var pt = MapData._points[MapData._points.length-1];

    if (auto_center && MapData._points.length > 1) {
		var newCenterpt = MapData._points[MapData._points.length-2]._point;
        map.panTo(newCenterpt);
    }

    if(pt._marker) map.removeOverlay(pt._marker);
    if (MapData._points.length > 1)
        map.removeOverlay(pt._line);

    msg = "removed point: ";
    if (MapData._distance)
        MapData._distance -= pt._distfromlast;
        
    MapData._points.pop();

	if(mileage_markers) MapData.drawMileageMarkers();
	UpdateGraph();
	
    printSummary();
}

function lineClicked(point) {
	if (!point) return; // Dunno why this is necessary, but cures disappearing lines
	
	for (var i=0; i < MapData._points.length; i++) {
		if(MapData._points[i]._line == this){
			var mypoint = MapData._points[i];
			var p_last = MapData._points[i-1];
			
			var routePoint = getClosestPointOnLines(point, mypoint._line); // Make sure inserted point is along clicked line
			
			map.removeOverlay(mypoint._line);
			MapData.insertPoint(routePoint, i - 1);
			MapData.drawPoint(MapData._points[i]);
			
			if(follow_roads){
				followRoadsMarkerMoved(MapData._points[i]);
			}else{
				
				mypoint._distfromlast = mypoint._point.distanceFrom(MapData._points[i]._point);
				MapData._points[i]._distfromlast = MapData._points[i]._point.distanceFrom(p_last._point);
		
				var line = drawLine(MapData._points[i]._point, mypoint._point);
				mypoint._line = line;
				printSummary();
			}
			i++;
		}
	}
}


function mapClicked(overlay, point) {
    
    var pt = point;
    //document.getElementById("symbol_type").focus();
	
    if (MapData._waypoint_mode == "add") {
    	addWayPoint(point, "", MapData._next_waypoint_name);
    	MapData._waypoint_mode = "";
    	return;
    } 

    if (!started)
        return;
        
    // will be handled by overlay itself
    if (overlay) {
        return;
    }

  
    var msg;
    var index = -1;
    
    // save settings without saving overlays
    saveSettings(false);
    
    if (auto_center && pt != null) {
        map.panTo(pt);
    }
    
    if (pt != null) {
        if (MapData._readonly_mode) {
            msg = "clicked: ";
        } else {
            msg = "added point: ";
			if(follow_roads){
				MapData.getDirections(point);
			}else{
	            MapData.addPoint(point);
			}
        }
    }

    
    printSummary();
}

function mapMouseMove(point, p2, p3) {

	if(BDragging || MouseOverMarker || !MapData._hidepoints_mode) {
		return;
	}
	
	var p = null;
	var pd = 9999;
	for(var i = MapData._points.length - 1; i >= 0; i--) {
		var ptemp = MapData._points[i]._point;
		var d = point.distanceFrom(ptemp);
		if(d < pd) {
			var dragIdx = i;
			p = ptemp;
			pd = d;
		}
	}
	if(!p) {
		return;
	}
	current_point = MapData._points[dragIdx];
	
	if(dragMarker) {
		dragMarker.setPoint(p);
		dragMarker.show();
	}else {
		dragMarker = new GMarker(p, {icon : getIcon("default"), draggable : true});
		addMarkerListeners(dragMarker);
		map.addOverlay(dragMarker);
	}
}

function printSummary() {
	
	if(map_mode == "edit") {
		
		var count = MapData._points.length;
		var speed = 25; //document.getElementById("speed").value;
		var secs = Math.round(MapData._distance / speed * 3.6);
		var hours = (secs - (secs % 3600))/3600;
		secs -= hours * 3600;
		var mins = (secs - (secs % 60))/60;
		secs -= mins * 60;
		
	    var summary = document.getElementById(summaryID);
		summary.innerHTML = "Total Miles: " + Math.round((MapData._distance/1000)*100*0.621371192)/100;
	}
}

function getMileageMarkerName(miles){
	var mileStr = String(miles);
	while(mileStr.length < 3){
		mileStr = "0" + mileStr;
	}
	return("mm_" + mileStr);
}

function getIcon(symbol) {
	
	var mm = false;

    if (symbol == null || symbol == "" ) {
        symbol = "default";
    }

    symbol = symbol.replace(/[,].*$/, "");
    symbol = symbol.replace(/[ ]+/, "_");
    
    for (var i=0; i<global_icons.length; i++) {
        var imgname = global_icons[i].image;
        if (imgname == base_dir + marker_dialog_images_dir + "marker_" + symbol + ".png" | imgname == base_dir + marker_dialog_images_dir + symbol + ".png") {
            return global_icons[i];
        }
    }

    var newIcon = new GIcon();
    global_icons.push(newIcon);

	if (symbol.substring(0,2) == "mm"){
	    newIcon.image = base_dir + marker_dialog_images_dir + symbol + ".png";
	    newIcon.printImage = base_dir + marker_dialog_images_dir + symbol + ".gif";
	    newIcon.mozPrintImage = base_dir + marker_dialog_images_dir + symbol + ".gif";
		mm = true;
	}else{
	    newIcon.image = base_dir + marker_dialog_images_dir + "marker_" + symbol + ".png";
	    newIcon.printImage = base_dir + marker_dialog_images_dir + "marker_" + symbol + ".gif";
	    newIcon.mozPrintImage = base_dir + marker_dialog_images_dir + "marker_" + symbol + ".gif";
	}
	
    if (symbol == "default") {
        newIcon.iconSize = new GSize(18, 18);
        newIcon.iconAnchor = new GPoint(9,9);
		newIcon.infoWindowAnchor = new GPoint(10,4); 
		//newIcon.shadow = base_dir + marker_dialog_images_dir + "shadow_graydot_default.png";
		//newIcon.shadowSize = new GSize(14,9);
	} else if (mm) {
		newIcon.iconSize = new GSize(21,18);
		newIcon.iconAnchor = new GPoint(10, 17);
		newIcon.shadow = base_dir + marker_dialog_images_dir + "shadow_mm.png";
		newIcon.shadowSize = new GSize(31,18);
	} else {
        newIcon.iconSize = new GSize(30, 33);
        newIcon.iconAnchor = new GPoint(15, 30);
		newIcon.infoWindowAnchor = new GPoint(15,18); 
		newIcon.shadow = base_dir + marker_dialog_images_dir + "shadow_route_marker.png";
        newIcon.shadowSize = new GSize(47.0, 33.0);
    }
    
    return newIcon;
}

function createMarker(point, pos, symbol, readonly) {
    
    var marker = null;
    
    if (symbol == null || symbol == "" )
        symbol = next_symbol;

    var icon = getIcon(symbol);
    
    var opts = null;
    
    if (!readonly) {
        opts = {draggable: true, icon: icon, draggableCursor: 'crosshair', 
                draggingCursor: 'move'};
        marker = new GMarker(point, opts);
            
		addMarkerListeners(marker);
		/*
		GEvent.addListener(marker, "dragend", function() {
            pointMoved(point);
        });
		*/
    } else  {
        opts = {draggable: false, icon: icon, draggableCursor: 'crosshair', 
                draggingCursor: 'move'};
        marker = new GMarker(point, opts);
    }

    map.addOverlay(marker);
    
    return marker;
}

function doubleClicked(event) {
    // alert("clicked");
    return false;
}

function mouseScrolled(event) {
    (event.detail || -event.wheelDelta) < 0 ? 
      map.zoomOut() : map.zoomIn();
    return false;
}

function mouseMoved(event) {
    return false;
}

function LocationFocus()
{
	ignore_key_commands = true;
}

function MapFocus()
{
	//alert(mapID);
	ignore_key_commands = false;
	//document.getElementById("symbol_type").focus();
}

function keyPressed(e) {

   if (MapData._waypoint_mode != "")
	   return;

   if (ignore_key_commands)
	   return;

   var KeyID = (window.event) ? window.event.keyCode : e.keyCode;
   // alert(KeyID);
   switch(KeyID)
   {
      case 61: // '+' (normal)
      case 107: // '+' (num)
      case 187: // '+' IE
        map.zoomIn();
		break; 
      case 109: // '-' (num+normal)
      case 189: // '+' IE
        map.zoomOut();
		break; 
      case 65: // 'a'
        MapData.setAutoZoomAndCenter();
		break; 
   }
   
}


function drawLine(p1, p2) {
    var lpoints = new Array();
    lpoints.push(p1);
    lpoints.push(p2);
    
	if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
		var polyLine = new GPolyline(lpoints, "#0000ff", 3, 0.7);
	}else{
		var polyLine = new BDCCPolyline(lpoints, "#0000ff", 4, 1, "Click to insert point");
	}
	
    map.addOverlay(polyLine);
    GEvent.addListener(polyLine, "click", lineClicked);

    
    return polyLine;
}
      
function loadForPrint(){
    map = new GMap2(document.getElementById(mapID), 
               {draggableCursor: 'crosshair' /*, 
                draggingCursor: 'move' */});
	loadSettings(true);
	
}

function loadMap(mapElement, summaryElement, elevation_profileElement, width, height) {
	
	mapID = mapElement;
	summaryID = summaryElement;
	elevation_profileID = elevation_profileElement;
	mapWidth = width;
	mapHeight = height;
    
    //window.onresize = resize;
    
    if (!GBrowserIsCompatible()) {
        return;
    }
	
	map = 0;
    map = new GMap2(document.getElementById(mapID), 
               {draggableCursor: 'crosshair' /*, 
                draggingCursor: 'move' */});
	if(map_mode != "print"){
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.addControl(new GOverviewMapControl());
	}
    
    GEvent.addListener(map, "click", mapClicked);
	GEvent.addListener(map, 'mousemove', mapMouseMove);
	
	// == use different GDirections for adding and dragging, it is just simpler that way ==
	dirn1 = 0;
	dirn1 = new GDirections();
	dirn2 = 0;
	dirn2 = new GDirections();
	dirn3 = 0;
	dirn3 = new GDirections();

	  	
	// == when the load event completes, plot the point on the street ==
	GEvent.addListener(dirn1,"load", function() {
		// snap to last vertex in the polyline
		var groute = dirn1.getRoute(0);
		var directions = "";
		for ( var i=0; i < groute.getNumSteps(); i++ ) {
			var str = groute.getStep(i).getDescriptionHtml() + "<BR>";
			directions += str;
		}
		
		var n = dirn1.getPolyline().getVertexCount();
		var points = new Array();
		for (var i=0; i<n; i++){
			points.push(dirn1.getPolyline().getVertex(i));
		}
		
		if(n>1){
			if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
				var poly = new GPolyline(points, "#0000ff", 3, 0.7);
			}else{
				var poly = new BDCCPolyline(points, "#0000ff", 4, 1, "Click to insert point");
			}
		}else{
			poly = null;
		}
		var lastPt = dirn1.getPolyline().getVertex(dirn1.getPolyline().getVertexCount()-1);
		addPoint(lastPt, "", poly, directions);
		if(mileage_markers) MapData.drawMileageMarkers();
		UpdateGraph();
		//alert('dirn1 loaded '+MapData._points.length);
	});

	GEvent.addListener(dirn1,"error", function() {
		if(confirm("Unable to load routing for this point, possibly because it is not supported for this region. Would you like to disable auto-routing?")){
			document.getElementById('followroads').checked = false;	
			toggleFollowRoads();
		}
	});
											   
	// == move the polyline preceding this point ==
	GEvent.addListener(dirn2,"load", function() {
		// snap to last vertex in the polyline
		var groute = dirn2.getRoute(0);
		var directions = "";
		for ( var i=0; i < groute.getNumSteps(); i++ ) {
				var str = groute.getStep(i).getDescriptionHtml() + "<BR>";
				directions += str;
		}
		var n = dirn2.getPolyline().getVertexCount();
		var points = new Array();
		for (var i=0; i<n; i++){
			points.push(dirn2.getPolyline().getVertex(i));
		}
		
		if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
			var poly = new GPolyline(points, "#0000ff", 3, 0.7);
		}else{
			var poly = new BDCCPolyline(points, "#0000ff", 4, 1, "Click to insert point");
		}
		
		var pos = movedmarker._pos-1;
		
		var p = dirn2.getPolyline().getVertex(n-1);
		movedmarker._point = p;
		movedmarker._directions = directions;
		if(movedmarker._marker) movedmarker._marker.setPoint(p);
		movedmarker._line = poly;
		movedmarker._distfromlast = movedmarker._line.getLength();
		map.addOverlay(poly);
		GEvent.addListener(poly, "click", lineClicked);			
		
		MapData._distance = 0;
		for (var i=0; i< MapData._points.length; i++) {
			   MapData._distance+=MapData._points[i]._distfromlast;
		}
		
		dir2Loaded = true;
		if (dir3Loaded) {
			//drawAllPoints();
			printSummary();
			if(mileage_markers) MapData.drawMileageMarkers();
			UpdateGraph();
		};		
		//alert('dirn2 loaded '+MapData._points.length);
	});
	
	GEvent.addListener(dirn2,"error", function() {
		if(confirm("Unable to load routing for this point, possibly because it is not supported for this region. Would you like to disable auto-routing?")){
			document.getElementById('followroads').checked = false;	
			toggleFollowRoads();
		}
		markerMoved(movedmarker);
	});

	// == move the polyline following this point ==
	GEvent.addListener(dirn3,"load", function() {
		var groute = dirn3.getRoute(0);
		var directions = "";
		for ( var i=0; i < groute.getNumSteps(); i++ ) {
			var str = groute.getStep(i).getDescriptionHtml() + "<BR>";
			directions += str;
		}
		var n = dirn3.getPolyline().getVertexCount();
		var points = new Array();
		for (var i=0; i<n; i++){
			points.push(dirn3.getPolyline().getVertex(i));
		}

		if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
			var poly = new GPolyline(points, "#0000ff", 3, 0.7);
		}else{
			var poly = new BDCCPolyline(points, "#0000ff", 4, 1, "Click to insert point");
		}

		var nextPos = movedmarker._pos+1;
		var nextPt = MapData._points[nextPos];
		//map.removeOverlay(nextPt._line);
		nextPt._line = poly;
		GEvent.addListener(poly, "click", lineClicked);			
		map.addOverlay(poly);
		nextPt._distfromlast = poly.getLength();
		nextPt._directions = directions;
		
		MapData._distance = 0;
		for (var i=0; i< MapData._points.length; i++) {
			   MapData._distance+=MapData._points[i]._distfromlast;
		}
		
		dir3Loaded = true;
		if (dir2Loaded) {
			//drawAllPoints();
			if(mileage_markers) MapData.drawMileageMarkers();
			UpdateGraph();
			printSummary();
		};
		//alert('dirn3 loaded '+MapData._points.length);
	});

	GEvent.addListener(dirn3,"error", function() {
		if(dir2Loaded){	// Means we actually skipped dir2
			if(confirm("Unable to load routing for this point, possibly because it is not supported for this region. Would you like to disable auto-routing?")){
				document.getElementById('followroads').checked = false;	
				toggleFollowRoads();
			}
			markerMoved(movedmarker);
		}
	});

	GEvent.addDomListener(document.getElementById(mapID),
	"double-click", doubleClicked);

	GEvent.addDomListener(document.getElementById(mapID),
	"DOMMouseScroll", mouseScrolled);

	GEvent.addDomListener(document.getElementById(mapID),
	"mousewheel", mouseScrolled); 

	GEvent.addDomListener(document.getElementById(mapID),
	"mousemove", mouseMoved); 
	
    GDraggableObject.setDraggableCursor('default');
    GDraggableObject.setDraggingCursor('crosshair');    
    
    GEvent.addListener(map, "moveend", function() {
      var center = map.getCenter();
    });

    geocoder = new GClientGeocoder();    
    
    reset();
    resize();
    
 	if(map_mode == "view" || map_mode == "print"){
		MapData._readonly_mode = true;
	}
       
    if (do_load_points) {
        loadSettings(false);
		//MapData.setAutoZoomAndCenter();
		importPoints();
        //setTimeout("importPoints();",1000);
        if (MapData._points.length) {
            MapData.setAutoZoomAndCenter();
						if(bool_fetch_directions)
						{
							//alert('load map, fetch dir');
							fetchMapDirections(MapData._points);
						}
        }
    } else {
        loadSettings(true);
    }

 	if(map_mode == "view"){
		toggleShowElevation();
	}else if(map_mode == "edit"){
		toggleShowElevation();
		toggleFollowRoads();
		toggleAutoCenter();
		toggleMileageMarkers();
	}	
}
function updateMapDirections()
{
	if(MapData._points.length)
	{ 
	  var coords = [];
	  for(var i=0; i < MapData._points.length; i++)
	  {
	  	coords.push(MapData._points[i]._point.toUrlValue(6));
	  }
	
		saveSettings(false);
  	reset();
	  dirn1.loadFromWaypoints(coords,{getPolyline:true, getSteps:true});
	}
}

function addMarkerListeners(marker, mapPoint) {
	if (mapPoint) GEvent.addListener(marker, "mouseover", function() {
		MouseOverMarker = true;
		if (dragMarker) dragMarker.hide();
	});
	
	if (mapPoint) GEvent.addListener(marker, "mouseout", function() {
		MouseOverMarker = false;
	});
	
	GEvent.addListener(marker, "click", function() {
	  BDragging = true;	
   	  if (mapPoint) current_point = mapPoint;
	  marker.openInfoWindowHtml("<iframe src='" + base_dir + "marker_dialog.html' scrolling='no' frameborder='no' height='250' width='325'></iframe>");}
	);
	
	GEvent.addListener(marker, 'dragstart', function() {
		if(mapPoint && dragMarker) dragMarker.hide();
		BDragging = true; 
	});
	
	GEvent.addListener(marker, "dragend", function() {
		BDragging = false;	
	   	if (mapPoint) current_point = mapPoint;
		if (MapData._readonly_mode){
			current_point._point = marker.getPoint();
			MapData.showTrackAsPolyline();
		}else if (follow_roads){
			followRoadsMarkerMoved(current_point,marker.getPoint());
		}else{
			markerMoved(current_point,marker.getPoint());
		}
	});
	
	GEvent.addListener(marker, 'infowindowopen', function() {
		BDragging = true; 
	});
	
	GEvent.addListener(marker, 'infowindowclose', function() {
		BDragging = false; 
	});
}

function switchMode(mode) {
    
    MapData._noline_mode = false;
    
    if (mode == 2) {    
        MapData._noline_mode = true;
        MapData._readonly_mode = true;
    } else if (mode == 0) {    
        MapData._readonly_mode = true;
    } else if (mode == 1) {    
        
        if (MapData._points.length > 200) {
    		if (!confirm("There are more than 200 segments (" +  MapData._points.length + "). " + 
    	  	"The \"Edit Mode\" may be very slow or even impossible (especially in Internet Explorer). " + 
    	  	"\nDo You really want to switch to \"Edit Mode\"?")) {
      			return;
    	  	}
        }
        
        MapData._readonly_mode = false;
    }
    
    map.clearOverlays();
    MapData.showTrack(true);
    updateMenu();
}


function findlocationChanged(address) {
    
    
  if (address == null || address == "")
     address = document.getElementById("findlocation").value;

  geocoder.getLatLng(
    address,
    function(point) {
      if (!point) {
        alert(address + " not found");
      } else {
        map.setCenter(point, 10);
        //var marker = new GMarker(point);
        //map.addOverlay(marker);
        //marker.openInfoWindowHtml(address + "<br/><br/>" + point);
      }
    }
  );
    
  document.getElementById("findlocation").value = "";
  document.getElementById("findlocation").blur();
  
  ignore_key_commands = false;

}


function loadSettings(loadpoints)
{
	// Default location if no location is saved in cookies and no route is loaded (Set to USA overview right now)
	var center_lat = 37.09024, center_lng = -95.712891, zoom = 4;
    var maptype = "normal";
    
    if (maptype_param != "")
        maptype = maptype_param;
    else if (getCookie("maptype"))
        maptype = getCookie("maptype");
    if (center_lat_param > 0)
        center_lat = center_lat_param;
    else if (getCookie("center_lat"))
        center_lat = parseFloat(getCookie("center_lat"));
    if (center_lng_param > 0)
        center_lng = center_lng_param;
    else if (getCookie("center_lng"))
        center_lng = parseFloat(getCookie("center_lng"));
    if (zoom_param > 0)
        zoom = zoom_param;
    else if (getCookie("zoom"))
        zoom = parseFloat(getCookie("zoom"));
    //if (getCookie("speed"))
    //    document.getElementById("speed").value = parseFloat(getCookie("speed"));
    //if (getCookie("routename"))
    //    document.getElementById("courseName").value = getCookie("routename");

    map.setCenter(new GLatLng(center_lat, center_lng), zoom);
    setMapType(maptype);
    
    
    if (center_lat_param > 0 && center_lng_param > 0) {
		;
    }

    if (loadpoints) {
        var pointstxt = getCookie("points");
        if (pointstxt && pointstxt != "") {
            // alert(pointstxt);
            var points = pointstxt.split(";");
            for (var i=0; i<points.length; i++) {
                var fields = points[i].split(",");
                var lat = parseFloat(fields[0]);
                var lng = parseFloat(fields[1]);
                var symbol = fields[2];
                var ele = parseFloat(fields[3]);
                addPoint(new GLatLng(lat, lng), symbol);
                setEle(ele);
            }
        }
    }
}

function saveSettings(savepointsalso)
{
   var expires = new Date();
    expires.setTime(expires.getTime() + 1000*60*60*24*365);
    var center = map.getCenter();
    expires = null; // never
    setCookie("center_lat", center.lat(), expires);
    setCookie("center_lng", center.lng(), expires);
    setCookie("zoom", map.getZoom(), expires);
    
    maptype = map.getCurrentMapType();
    if (maptype == G_NORMAL_MAP)
       setCookie("maptype", "normal", expires);
    if (maptype == G_SATELLITE_MAP)
       setCookie("maptype", "satellite", expires);
    if (maptype == G_HYBRID_MAP)
       setCookie("maptype", "hybrid", expires);

    /*
    var speed = document.getElementById("speed").value;
    setCookie("speed", speed, expires);
    var routename = document.getElementById("courseName").value;    
    setCookie("routename", routename, expires);
	*/
	
    if (savepointsalso) {
        var pointstxt = "";
        for (var i=0; i < MapData._points.length; i++) {
            var p = MapData._points[i];
            if (pointstxt != "")
                pointstxt += ";";
            pointstxt += p._point.lat() + "," + p._point.lng() + "," + p._sym + "," + p._ele;
        }    
        setCookie("points", pointstxt);
    }
}

function toggleAutoCenter(){
    auto_center = document.getElementById('autocenter').checked;
}

    pts = new MapDataType();
function toggleFollowRoads()
{
  follow_roads = document.getElementById('followroads').checked;
  
  if(0 && follow_roads && MapData._points.length > 1)
  { 			
		updateMapDirections();
  }
}


function toggleMileageMarkers(){
	mileage_markers = document.getElementById('mileagemarkers').checked;
	
	if(mileage_markers){
		MapData.drawMileageMarkers();
	}else{
		for(var i=0; i < mileage_marker_list.length; i++){
			mileage_marker_list[i].hide();
		}
	}
}

function toggleShowElevation(){
    show_elevation = document.getElementById('showelevation').checked;
	var dv = document.getElementById(elevation_profileID);
	var state = 'hidden';
	if(show_elevation){
		state = 'visible';
		dv.style.display = 'block';
		UpdateGraph();
	}else{
		dv.style.display = 'none';
	}
	
	resize();
}

function setMapType(maptype)
{
    if (maptype == "normal")
      map.setMapType(G_NORMAL_MAP);
    if (maptype == "satellite")
      map.setMapType(G_SATELLITE_MAP);
    if (maptype == "hybrid")
      map.setMapType(G_HYBRID_MAP);
}


function NewRoute(){
  
    if (MapData._points.length > 0 && !confirm("Remove all Points?"))
        return;
    
    reset();
    saveSettings(true);
}

//helper function to add elements to the form
function createNewFormElement(inputForm, elementName, elementValue){
	//var newElement = document.createElement("<input name='"+elementName+"' type='hidden'>");

	var span = document.createElement('span');
	span.innerHTML = "<input type='hidden' name='" + elementName + "' value='" + elementValue + "'>";
	inputForm.appendChild(span);	
	
	//inputForm.appendChild(newElement);
	//newElement.value = elementValue;
	return span;
}

function SaveRoute(){
	
	saveRouteForm = document.createElement("FORM");
	document.body.appendChild(saveRouteForm);
	saveRouteForm.method = "POST";
	saveRouteForm.style.id = "saveRouteForm";
	saveRouteForm.name = "saveRouteForm";
	saveRouteForm.action= save_route_form_submit;
	var routeStr = "";
	var directions = [];
	var bDirections = true;
	
	var miles = (MapData._distance/1000)*0.621371192;
	createNewFormElement(saveRouteForm,"miles",miles);

	var coords = [];
	
	//var routeArray = new Array();
	for(var i = 0; i < MapData._points.length; i++){
		
		if(0)
		{
			var tmp = [];
		  for (var word in MapData._points[i]) tmp.push(word +'='+MapData._points[i][word]);
			alert(tmp.join('\n'));
			return;
		}
		var curPt = MapData._points[i];
		coords.push(curPt._point);
		var ptArray = new Array();
		ptArray.push(createEncodings([curPt._point]));
		if(!curPt._ele){
			ptArray.push("");
		}else{
			ptArray.push(curPt._ele);
		}
		if(!curPt._sym){
			ptArray.push("");
		}else{
			ptArray.push(curPt._sym);
		}
		if (curPt._line && curPt._line.getVertexCount() > 2){
			var linePts = new Array();
			for(var j=0; j< curPt._line.getVertexCount(); j++){
				linePts.push(curPt._line.getVertex(j));
			}
			var encodedLine = createEncodings(linePts);
			////if(encodedLine) alert(i+ ' ' +encodedLine);
			ptArray.push(encodedLine );
		}else{
			ptArray.push("");
		}
		//alert('point '+i+' '+(curPt._line?curPt._line.getVertexCount():0));
		
		//Need to convert CRs to <BR> after we escape the string for notes, so that it doesn't mess up parsing when we load the route back in from the server
		var notesStr = escape(curPt._notes);
		curPt._notes = notesStr.replace(/%0A/g,"<BR>");
		
		//alert(curPt._directions);
		ptArray.push(curPt._notes);		
		
		// clear any undefined directions per point
		var direction = curPt._directions;
		if(!direction || direction=='undefined') 
		{
			MapData._points[curPt._pos]._directions = "";
			curPt._directions = "";
		}
		ptArray.push(curPt._directions);
		
		if(curPt._directions) directions.push(curPt._directions);
		//else bDirections = false;
		
		//routeArray.push(ptArray);
		createNewFormElement(saveRouteForm, ("coordinates[" + String(i+1) + "]"), ptArray[0]);
		createNewFormElement(saveRouteForm, "elevation[" + String(i+1) + "]", ptArray[1]);
		createNewFormElement(saveRouteForm, "symbol[" + String(i+1) + "]", escape(ptArray[2]));
		createNewFormElement(saveRouteForm, "line[" + String(i+1) + "]", ptArray[3]);
		createNewFormElement(saveRouteForm, "notes[" + String(i+1) + "]", ptArray[4]);
		createNewFormElement(saveRouteForm, "directions[" + String(i+1) + "]", escape(ptArray[5]));
		
		routeStr += ptArray.toString() + "\n";
	}
		
	if(bool_fetch_directions)
	{
		fetchMapDirections(MapData._points, true);
	}
	else
	{
		SubmitRoute();
	}	
}

function SubmitRoute()
{	
	var directions = new Array();
	
	// skip first point?
	for( var i=1; i < MapData._points.length; i++ ) 
	{
		var pointindex = MapData._points[i]._pos;
		var direction = MapData._points[pointindex]._directions;
		direction = direction.replace(/<div[^>]*class=\"google_note\"[^>]*>(.*?)<\/div>/gi, '');
		direction = direction.replace(/(<p>&nbsp;<\/p>)/gi, '');
		direction = direction.replace(/(<p>|<\/p>)/gi, '');

		// if any directions are missing, empty array and break - don't automate directions
		if(!direction) 
		{
			directions = new Array();
			break;
		}
		if(directions.join('').match(direction)) continue;
		directions.push(direction);
	}
			
	// if there are directions for each point, pass as auto directions to user for next step			
	if(directions.length)
	{
		createNewFormElement(saveRouteForm,"autoDirections", directions.join(""));	
	}
	
	if(0) // FOR TESTING
	{
		alert('Google Follow Road Directions:\n-------------------------------------\n '+directions.join("\n"));
		return;
	}
	
	saveRouteForm.submit();
}

function LoadRoute(routeString, routeName, rideID){
	//reset();
	if (routeString == "") return;
	if (routeName) RideName = routeName;
	if (rideID) RideID = rideID;
	
	var routeArray = new Array();
	var pointArray = routeString.split("%0A");
	for(var i=0; i < pointArray.length; i++){
		routeArray.push(pointArray[i].split(","));
	}
	
	//alert("Map loaded = " + map.isLoaded());
	
	for(var i=0; i < routeArray.length; i++){
		var curPt = routeArray[i];
		if (curPt.length < 4) continue; //Hack to account for empty points caused by CRs in notes before we fixed that.
		var ptCoords = decodeLine(curPt[0])[0];
		var symbol = unescape(curPt[2]);
		var encLine = curPt[3];
		var line = "";
		if(encLine){
			var linePts = decodeLine(encLine);
			if (navigator.userAgent.indexOf("MSIE") != -1 || MapData._hidepoints_mode ){
				line = new GPolyline(linePts, "#0000ff", 3, 0.7);
			}else{
				line = new BDCCPolyline(linePts, "#0000ff", 4, 1, "Click to insert point");
			}
		}
		addPoint(ptCoords, symbol, line);
		var curMapPoint = MapData._points[MapData._points.length-1];
		curMapPoint._ele = curPt[1];
		//Need to turn <BR> back into CRs
		notesStr = unescape(curPt[4]);
		curMapPoint._notes = notesStr.replace(/<BR>/g,"\n");
	}
}
      
function resize() {
	var mapd = document.getElementById(mapID);
	
	if (map_mode == "edit"){
		var profile_height = 0;
		if(show_elevation){
			profile_height = 150;
		}
		
		//mapd.style.height = (530 - profile_height)+ 'px';
		mapd.style.height = (mapHeight - profile_height)+ 'px';
		
		mapd.style.width = mapWidth + 'px';
		
		if (map)
		  map.checkResize();
		// alert("New height: " + mapd.style.height);
	} else {
		mapd.style.height = mapHeight + 'px';
		
		mapd.style.width = mapWidth + 'px';
	}
    
}

function CenterToStart() {
    if (MapData._points.length) {
        var point = MapData._points[0]._point;
        map.panTo(point);
    }
}

function CenterToEnd() {
    if (MapData._points.length) {
        var point = MapData._points[MapData._points.length-1]._point;
        map.panTo(point);
    }
}

function getRoutePixels(myLine){
	var zoom = map.getZoom();
	var routePixels = new Array();
	var projection = G_NORMAL_MAP.getProjection();

	for ( var i = 0; i < myLine.getVertexCount(); i++ ) {
		var Px = projection.fromLatLngToPixel(myLine.getVertex(i), zoom);
		routePixels.push(Px);
	}
	
	return routePixels;
}


function getClosestPointOnLines(myPoint,myLine) {
	// Scavenged from http://demo.geostart.nl/cSnapToRoute.js
	// Used to make sure inserted point lies exactly along clicked line

	var minDist;       
	var fTo;
	var fFrom;
	var x;
	var y;
	var i;
	var dist;
	var routePixels = getRoutePixels(myLine);
	var projection = G_NORMAL_MAP.getProjection();
	var zoom = map.getZoom();
	var pXy = projection.fromLatLngToPixel(myPoint, zoom);
		
	if (routePixels.length > 1){
		
			for (var n = 1 ; n < routePixels.length ; n++ ) {

				if (routePixels[n].x != routePixels[n-1].x) {
					var a = (routePixels[n].y - routePixels[n-1].y) / (routePixels[n].x - routePixels[n-1].x);
					var b = routePixels[n].y - a * routePixels[n].x;
					dist = Math.abs(a*pXy.x + b - pXy.y) / Math.sqrt(a*a+1);
				}
				else 
					dist = Math.abs(pXy.x - routePixels[n].x)
				
				// length^2 of line segment 
				var rl2 = Math.pow(routePixels[n].y - routePixels[n-1].y,2) + Math.pow(routePixels[n].x - routePixels[n-1].x,2);
				
				// distance^2 of pt to end line segment
				var ln2 = Math.pow(routePixels[n].y - pXy.y,2) + Math.pow(routePixels[n].x - pXy.x,2);

				// distance^2 of pt to begin line segment
				var lnm12 = Math.pow(routePixels[n-1].y - pXy.y,2) + Math.pow(routePixels[n-1].x - pXy.x,2);

				// minimum distance^2 of pt to infinite line
				var dist2 = Math.pow(dist,2);
				
				// calculated length^2 of line segment
				var calcrl2 = ln2 - dist2 + lnm12 - dist2;

				// redefine minimum distance to line segment (not infinite line) if necessary
				if (calcrl2 > rl2) 
					dist = Math.sqrt( Math.min(ln2,lnm12) );                               
				
				if ( (minDist == null) || (minDist > dist) ) {
				fTo  = ((Math.sqrt(lnm12 - dist2)) / Math.sqrt(rl2));
				minDist = dist;
				i = n;               
			}
				
		}
			
		if (fTo > 1 ) 
				fTo = 1;        

		fFrom = 1-fTo;

			var dx = routePixels[i-1].x - routePixels[i].x;
			var dy = routePixels[i-1].y - routePixels[i].y;

			x = routePixels[i-1].x - (dx * fTo);
			y = routePixels[i-1].y - (dy * fTo);

	}    
	
	return projection.fromPixelToLatLng(new GPoint(x,y), zoom);

}


function speedChanged() {
    var speed = document.getElementById("speed").value;    
    // alert("Speed: " + speed);
    if (speed > 0 && speed < 1000) {
        printSummary();
    }
}

function reset() {
    
    map.clearOverlays();
    lines_ovl = new Array();
    distances  = new Array();
    symbols = new Array();
    next_symbol = "default";
    MapData._readonly_mode = false;
    

    // remove all
    MapData = new MapDataType();
    
    
    var form = getForm("import");

    UpdateGraph();
	printSummary();
    
}

function doImport() {
    var form = getForm("import");
    var fname = form.userfile.value;

    if (fname == "") {
        alert("Select filename first!");
        return;
    }
    
    if (map) {
      reset();
      saveSettings(false);
    }
    
    setCookie("points", "");
    form.submit();
}

function getAllPoints(topoPoints){
    var num_points = MapData._points.length;
	var all_points = new Array();
    for (var i=0; i < num_points; i++) {
		if(MapData._points[i]._line){
			var vertex_count = MapData._points[i]._line.getVertexCount();
			for(var j=1; j < vertex_count - 1; j++){
				if(topoPoints){
					var pt = [ MapData._points[i]._line.getVertex(j).lat(), MapData._points[i]._line.getVertex(j).lng() ];
				}else{
				    var pt = new MyPoint(MapData._points[i]._line.getVertex(j));
				}
				all_points.push(pt);
			}
		}
		
		if(topoPoints){
			all_points.push([MapData._points[i]._point.lat(), MapData._points[i]._point.lng()]);
		}else{
			all_points.push(MapData._points[i]);
		}
	}
	return(all_points);
}

function UpdateGraph(){
	if(!show_elevation) return;
	var graphic = document.getElementById("elevation_profile_graphic");
	if (map_mode == "view"){
		var pts = getAllPoints(true);
		if(pts.length<=1) return;// For when the map gets reset
		var resampledCoordinates = ResampleCoordinates(pts); 	
		var encoded = createEncodings(resampledCoordinates,true);
		
		var URL = graphtopo_path + "?d=" + MapData._distance/1000.0 + "&l=" + encoded + "&r=" + RideID + "&m=profile";
		graphic.src = URL;
	}else if (map_mode == "edit"){
		var pts = getAllPoints(true);
		if (pts.length<=1){
			graphic.src = base_dir + "images/default_topo.png";
		}else{
			var resampledCoordinates = ResampleCoordinates(pts); 
			
			var encoded = createEncodings(resampledCoordinates,true);
			
			//Make sure we get rid of extra backslashes added for the database
			var re = new RegExp("\\\\\\\\", "g");
			encoded.replace(re, "\\");

			var URL = graphtopo_path + "?d=" + MapData._distance/1000.0 + "&l=" + encoded;
			
			graphic.src = URL;
	
		}
	}
	
}

//helper function to create the form
function getNewSubmitForm(){
	var submitForm = document.createElement("FORM");
	submitForm.setAttribute("id","formID");
	document.body.appendChild(submitForm);
	submitForm.method = "POST";
	return submitForm;
}

//helper function to add elements to the form
function createNewFormElement(inputForm, elementName, elementValue){
	var mystring = "<input name='"+elementName+"' type='hidden'>";
	var newElement = document.createElement("input");
	newElement.setAttribute("name",elementName);
	newElement.setAttribute("type","hidden");
	inputForm.appendChild(newElement);
	newElement.value = elementValue;
	return newElement;
}

function doExport(format, docompress) {
	    
    saveSettings(true);
    if (!format || format == "")
        return;

    var speed = 25; //document.getElementById("speed").value;    
    
    //output.value = "";
    var txt = "";
    var lastpoint;
    
    var dist = 0;
    var dur = 0;
    var alt = 0;
    var pointtype = 0;
    

    if (MapData._points.length == 0 && MapData._waypoints.length == 0) {
        alert("Add points first or import a track/route!");    
        return;
    }
	
	var all_points = getAllPoints();

    var num_points = all_points.length;
	var replace_timestamps = false;
	var elevation_present = false;
    
    
    for (var i=0; i < num_points; i++) {
		
        var point = null;
        
        if (txt.length > 0)
            txt += ";";
            
        var mypoint = all_points[i];
        var wpname = mypoint._wpname.replace(/[,]/, "~");
        
		if (i==0 && mypoint._datetime) {
			if (confirm("Do you want to replace existing timestamps?")) {
				replace_timestamps = true;
		  	}
		}
		
		
        point = mypoint._point;
        var pointtype = mypoint._sym;
        if (pointtype && pointtype.length > 1) {
            pointtype = pointtype.replace(/\..*/, "");
            pointtype = pointtype.replace(/.*\//, "");
            pointtype = pointtype.replace(/[,]/, "~");
        } else {
            pointtype = "";
        }
        
        alt = mypoint._ele;
        
		if (!elevation_present && alt > 0) {
			elevation_present = true;
		}
		
        if (lastpoint == null)
            lastpoint = point;
                    
        if (i > 0) {
            d = lastpoint.distanceFrom(point);
            dist += d;
            dur = dist / speed * 3.6;
        }
        
        txt += "rtept," + point.lng() + "," + point.lat() + "," + alt + "," + dist + "," + dur + ","
            + pointtype + "," + wpname;

		if (!replace_timestamps && mypoint._datetime) {
	        txt += "," + mypoint._datetime;
		}

        lastpoint = point;
    }
    
    var num_points = MapData._waypoints.length;
    
    for (var i=0; i < num_points; i++) {
        var point = null;
        
        if (txt.length > 0)
            txt += ";";
            
        var mypoint = MapData._waypoints[i];
        var wpname = mypoint._wpname.replace(/[,]/, "~");
        
        point = mypoint._point;
        var pointtype = mypoint._sym;
        if (pointtype && pointtype.length > 1) {
            pointtype = pointtype.replace(/\..*/, "");
            pointtype = pointtype.replace(/.*\//, "");
            pointtype = pointtype.replace(/[,]/, "~");
        } else {
            pointtype = "";
        }
        
        alt = mypoint._ele;
        txt += "waypt," + point.lng() + "," + point.lat() + "," + alt + "," + dist + "," + dur + ","
            + pointtype + "," + wpname + "," + mypoint._datetime;
    }

    if (!format)
      format = document.getElementById("ouput_format_selection").value;

    if (format == "0") {
       return;
    }
    
    
	var submitForm = getNewSubmitForm();
	createNewFormElement(submitForm, "formname", "export");
	createNewFormElement(submitForm, "data", txt);
	createNewFormElement(submitForm, "outputformat", format);
	createNewFormElement(submitForm, "coursename", RideName);
	createNewFormElement(submitForm, "speed", speed);
	createNewFormElement(submitForm, "duration", dur);
	createNewFormElement(submitForm, "distance", dist);
	createNewFormElement(submitForm, "docompress", 0);
	createNewFormElement(submitForm, "getelevation", true);

	submitForm.action = base_dir + "export.php";
	/*
    submitForm.data.value=txt;
    submitForm.outputformat.value=format;
    submitForm.coursename.value= "Track"; //document.getElementById("courseName").value;
    submitForm.speed.value=speed;
    submitForm.distance.value=dist;    
    submitForm.duration.value=dur;
    submitForm.getelevation.value= true; //document.getElementById('getelevation').checked;
	*/
	
	if (elevation_present) {
		if (confirm("Do you want to replace existing elevation data?")) {
		    submitForm.getelevation.value="true";
	  	}
	}
    
    /*
	if (docompress && docompress == 1) {
      submitForm.docompress.value=1;
    } else {
      submitForm.docompress.value=0;
    }
	*/
    submitForm.submit();
	
}


function getForm(name) 
{
    for (var i=0; i<document.forms.length; i++) {
        var form = document.forms[i];
        if (form && form.formname && form.formname.value == name) {
            return form;
        }
    }
    
    return null;
}

function createReqObj()
{
  brws = navigator.appName;
  if(brws == "Microsoft Internet Explorer")
  	rq = new ActiveXObject("Microsoft.XMLHTTP");
  else 
  	rq = new XMLHttpRequest(); 
  return rq;
}



