//written by: Keith Kaiser, 
//all rites reserved, no guarentees of any kind

//Not being the type who likes to re-invent wheels, below are some of the people who helped me with this project
//Laurent Haas F6FVY ==> http://f6fvy.free.fr/qthLocator/fullScreen.php
//Doug Henderson ==> http://www3.telus.net/DougHenderson/MarkerTabs_v2.html	
//Mike Williams ==> http://www.econym.demon.co.uk/googlemaps/index.htm
//Zouzou Wizman ==> http://prototype-window.xilinus.com/index.html -- help window, geocodeing window, etc.

//This program uses the following files
//GoogleMapper.tmpl (this program) is in templates
//balltrak0.js in lib
//controls.js in lib ==> holds the on map buttons such as 'Toggle Markers'
//elabel.js in lib
//balltrak.css in css
//window.js in lib
//protobype.js in lib

//GLog.write('m= '+m+' Up= '+altChangeUp+' tot= '+totChangeUp+' avg= '+totChangeUp/m);
//alert('say there');


var month=new Array(12)
	month[0]="January"
	month[1]="February"
	month[2]="March"
	month[3]="April"
	month[4]="May"
	month[5]="June"
	month[6]="July"
	month[7]="August"
	month[8]="September"
	month[9]="October"
	month[10]="November"
	month[11]="December"

var clickedPixel;
var clicklatlng;
var contextmenu;
	
var sunRise;
var sunSet;
var geo;
var map = null;				// the Google map object
//var minimap = null;
var station;
var theCenter;

var launchPoint; var burstPoint; var touchdownPoint; var centerSpot;
var mHgt;
var degreesPerRadian = 180.0 / Math.PI;
var radiansPerDegree = Math.PI / 180.0;
var touchdownFromLaunch;

var burstFromLaunch;
var sidebar_html = "";
var state = 'hidden';

var e; var z; var d;  // variable passed to the tohere/fromhere functions 

var lLab1;
var lHtml1;  var lHtml2;  var lHtml3;
var tdHtml1; var tdHtml2; var tdHtml3;
var tdLab1;  var tdLab2;  var tdLab3;

var htmls = [];
var gmarkers = [];
var elabels = [];  // elabel overlays all called label2

var to_htmls = [];  var from_htmls = [];

var circle1; var circle2;
var touchdownMarker; var launchMarker; var burstMarker;
var uppoints = []; var dnpoints = [];
var l2tpolyline;
var polygonClick;
var cntNsidebar;
var aMarker = new Array(5);  // altitude markers

var baseIcon = new GIcon(); 
		
// === Create an associative array of GIcons() ===
var gicons= new Array(10);
 		//gicons.shadow = "./mapicons/mm_20_shadow.png";
 		gicons[0] =  "./mapicons/mm_20_white.png";
 		gicons[1] =  "./mapicons/mm_20_red.png";
 		gicons[2] =  "./mapicons/mm_20_blue.png";
 		gicons[3] =  "./mapicons/mm_20_green.png";
 		gicons[4] =  "./mapicons/mm_20_brown.png";
 		gicons[5] =  "./mapicons/mm_20_purple.png";
 		gicons[6] =  "./mapicons/mm_20_yellow.png"; 
 		gicons[7] =  "./mapicons/mm_20_orange.png";
 		gicons[8] =  "./mapicons/mm_20_black.png";
		gicons[9] =  "./mapicons/mm_20_gray.png";
 		
var caricons = new Array(10);  	 
 		caricons[0] = "./mapicons/whiteCar.png";
 		caricons[1] = "./mapicons/redCar.png";
 		caricons[2] = "./mapicons/blueCar.png";
 		caricons[3] = "./mapicons/greenCar.png";
 		caricons[4] = "./mapicons/brownCar.png";
 		caricons[5] = "./mapicons/purpleCar.png";
 		caricons[6] = "./mapicons/yellowCar.png"; 
 		caricons[7] = "./mapicons/orangeCar.png";
 		caricons[8] = "./mapicons/blackCar.png";
		caricons[9] = "./mapicons/grayCar.png";
  		
var colorx= new Array(10);
	colorx[0] = "white";
	colorx[3] = "red";
	colorx[2] = "blue";
	colorx[1] = "green";
	colorx[4] = "brown";
	colorx[5] = "purple";
	colorx[6] = "yellow";
	colorx[7] = "orange";
	colorx[8] = "black";
	colorx[9] = "gray";


function initPage() {
  if (!GBrowserIsCompatible()) {
		alert("Note 123:\n\nYour browser may not be compatible with the Google Maps system.\nPlease visit http://maps.google.com for more informatoin.");
	} else {
    	var mapDiv = document.getElementById("mapDiv");

    load(mapDiv);
		showDiv('getPlot');
		document.getElementById('showTrack').checked=false;
		
  }
} //end of initPage function


function load(container) {
  	var bounds = new GLatLngBounds(); // empty GLatLngBounds object
  	var otherOpts = { 
          buttonStartingStyle: {display:'block',color:'#0000cc',background:'white',width:'6em',
            textAlign:'center', fontFamily:'smaller Arial', /*,fontSize:'12px'*/
            fontWeight:'bold', border:'1px solid red',
            padding:'1px', cursor:'pointer'},
            
          buttonHTML: 'Drag Zoom',
          buttonZoomingHTML: 'Drag a region on the map (click here to reset)',
          buttonZoomingStyle: {background:'yellow'},
          backButtonHTML: 'Drag Zoom Back',  
          backButtonStyle: {display:'none',marginTop:'3px',background:'#FFFFC8'},
          backButtonEnabled: true
        } 
        
	  	map = new GMap2(container); 
        
        
        /* ===== */
               /* ====== */
map.addMapType(G_PHYSICAL_MAP);  /* added 10/16/08 by KK */
  		map.addControl(new GLargeMapControl()); 
  		map.addControl(new GMapTypeControl());
  		map.addControl(new GScaleControl());  
   	/*	map.addControl(new PointZoomControl());
   	  	map.addControl(new TextualZoomControl(),
          			   new GControlPosition(G_ANCHOR_TOP_LEFT, 
          			   new GSize(7,27)));   */
        map.enableContinuousZoom(); 
   		map.addControl(new DragZoomControl({}, otherOpts, {}), 
   					   new GControlPosition(G_ANCHOR_TOP_LEFT, 
   					   new GSize(7,280)));
   		map.hideControls();
			GEvent.addListener(map, "mouseover", function(){
			map.showControls();
			});

			GEvent.addListener(map, "mouseout", function(){
			map.hideControls();
		}); 
   		
	// ====== Create a Client Geocoder ======
       geo = new GClientGeocoder(); 

      // ====== Array for decoding the failure codes ======
      var reasons=[];
      reasons[G_GEO_SUCCESS]            = "Success";
      reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had no value.";
      reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
      reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
      reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
      reasons[G_GEO_TOO_MANY_QUERIES]   = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
      reasons[G_GEO_SERVER_ERROR]       = "Server error: The geocoding request could not be successfully processed.";
      
    //put the lat lon of the map center in the centerPoint div
		GEvent.addListener(map, "moveend", function() {
			var center = map.getCenter();
				var latLngStr = 'Map Center: ('+(Math.round(center.y*10000)/10000) + ', '
				   +(Math.round(center.x*10000)/10000) + ')';

      	  	document.getElementById("centerPoint").innerHTML = latLngStr;
      	  	 	theCenter = (Math.round(center.y*10000)/10000)+', '+
				(Math.round(center.x*10000)/10000);
		});
		
		// === create the context menu div ===		
      	    contextmenu = document.createElement("div");
      	    contextmenu.style.listStyleType="none";
      		contextmenu.style.visibility="hidden";
      		contextmenu.style.background="#ffffff";
      		contextmenu.style.border="1px solid #8888FF";
      		contextmenu.style.fontSize="10pt";
      		contextmenu.style.textDecoration="none";
      		contextmenu.style.zIndex="5000";
			
		contextmenu.innerHTML += '<ul>';
		contextmenu.innerHTML  = '<li style="font-weight:bold";>Click to Select:</li>';
		contextmenu.innerHTML += '<li><a href="javascript:hideMarkers();"><div class="context">&nbsp;&nbsp;Toggle Marker Visibility&nbsp;&nbsp;</div></a></li>';
		contextmenu.innerHTML += '<br />';
		contextmenu.innerHTML += '<li style="font-weight:bold";>Add Markers:</li>';
      	contextmenu.innerHTML += '<li><a href="javascript:gridsquare();"><div class="context">&nbsp;&nbsp;Show Gridsquare</div></a></li>';
      	contextmenu.innerHTML += '<li><a href="javascript:addSMarker()"><div class="context">&nbsp;&nbsp;Add a start marker here</div></a></li>';
      	contextmenu.innerHTML += '<li><a href="javascript:addEMarker()"><div class="context">&nbsp;&nbsp;Add an end marker here&nbsp;&nbsp;</div></a></li><br />';
      	contextmenu.innerHTML += '<li><a href="javascript:geoCodethis()"><div class="context">&nbsp;&nbsp;Geocode a point or address&nbsp;&nbsp;</div></a></li>';
      	contextmenu.innerHTML += '<li><a href="javascript:showWeX()"><div class="context">&nbsp;&nbsp;Display the Weather Activity Planner&nbsp;&nbsp;</div></a></li>';
      	contextmenu.innerHTML += '<br />';
      	contextmenu.innerHTML += '<li style="font-weight:bold";>Zoom To Menu:</li>';
		contextmenu.innerHTML += '<li><a href="javascript:originalPosition();"><div class="context">&nbsp;&nbsp;Original Position&nbsp;&nbsp;</div></a></li>';
		contextmenu.innerHTML += '<li><a href="javascript:map.panTo(launchPoint);"><div class="context">&nbsp;&nbsp;Pan to Launch&nbsp;&nbsp;</div></a></li>';
        contextmenu.innerHTML += '<li><a href="javascript:map.panTo(burstPoint);"><div class="context">&nbsp;&nbsp;Pan to Burst&nbsp;&nbsp;</div></a></li>';
        contextmenu.innerHTML += '<li><a href="javascript:map.panTo(touchdownPoint);"><div class="context">&nbsp;&nbsp;Pan to Touchdown&nbsp;&nbsp;</div></a></li><br />';
        contextmenu.innerHTML += '<li><a href="javascript:zoomInHere()"><div class="context">&nbsp;&nbsp;Zoom in here&nbsp;&nbsp;</div></a></li>';
        contextmenu.innerHTML += '<li><a href="javascript:zoomOutHere()"><div class="context">&nbsp;&nbsp;Zoom out here&nbsp;&nbsp;</div></a></li>';
        contextmenu.innerHTML += '<li><a href="javascript:centreMapHere()"><div class="context">&nbsp;&nbsp;Centre map here&nbsp;&nbsp;</div></a></li>';
        contextmenu.innerHTML += '<br />';
        contextmenu.innerHTML += '<li style="font-weight:bold";>Help Menu:</li>';
		contextmenu.innerHTML += '<li><a href="javascript:help();"><div class="context">&nbsp;&nbsp;Help Menu&nbsp;&nbsp;</div></a></li>';
		contextmenu.innerHTML += '<li><a href="javascript:openitup('+"'http://nearspaceventures.com'"+');"><div class="context">&nbsp;&nbsp;NSV Home Page&nbsp;&nbsp;</div></a></li>';
		contextmenu.innerHTML += '<li><a href="javascript:openitup('+"'http://nearspaceventures.com/w3Baltrak/readyget.pl'"+');"><div class="context">&nbsp;&nbsp;NSV Data Entry Page&nbsp;&nbsp;</div></a></li>';
		contextmenu.innerHTML += '<li><a href="javascript:openitup('+"'http://nearspaceventures.com/cgi-bin/ascent.pl'"+');"><div class="context">&nbsp;&nbsp;NSV On-Line Ascent Calculator&nbsp;&nbsp;</div></a></li>';
		//contextmenu.innerHTML += '<li><a href="javascript:openitup('+"'http://aprs.he.fi'"+');"><div class="context">&nbsp;&nbsp;Google Maps APRS Tracker&nbsp;&nbsp;</div></a></li>';
		contextmenu.innerHTML += '<li><a href="javascript:openitup('+"'http://nearspaceventures.com/w3Baltrak/cgi-bin/setcurrmsn.pl'"+');"><div class="context">&nbsp;&nbsp;Lock It&nbsp;&nbsp;</div></a></li>';
		//contextmenu.innerHTML += '</ul>';

      	map.getContainer().appendChild(contextmenu);

		//this places the grid square around the point clicked
		GEvent.addListener(map,"singlerightclick",function(pixel,tile) {
			clicklatlng = map.fromContainerPixelToLatLng(pixel); 
			clickedPixel = pixel;
			var x=pixel.x;
			var y=pixel.y;
			if (x > map.getSize().width - 120) { x = map.getSize().width - 120 }
        	if (y > map.getSize().height - 100) { y = map.getSize().height - 100 }
        	var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(x,y));  
        	
        	var xcenter = map.getCenter();       	
        	var latCntr = xcenter.y;
        	var lngCntr = xcenter.x;
        	var fiBld = "'<li><a href=";
        	    fiBld += '"javascript:openitup(';
        	    fiBld += "'http://aprs.he.fi/?lat=";
        	    fiBld += latCntr;
        	    fiBld += '&lng=';
        	    fiBld += lngCntr;
        	    fiBld += "');";
        	    fiBld += '"><div class = "context">&nbsp;&nbsp;Google Maps APRS Tracker&nbsp;&nbsp;</div></a></li>';
        	    fiBld += "'";
        	
        	contextmenu.innerHTML += fiBld;
        	contextmenu.innerHTML += '</ul>';
			
        	pos.apply(contextmenu);
        	contextmenu.style.visibility = "visible";
      	});// end of the singlerightclick listener
         
     	// === If the user clicks on the map, close the context menu ===
     	GEvent.addListener(map, "click", function() {
        	contextmenu.style.visibility="hidden";
     	});
     
     	GEvent.addListener(map, "mousemove", function(point){
		    var latLngStr6 = point.y.toFixed(6) + ', ' + point.x.toFixed(6);
			var intro = 'Cursor at: ';
				document.getElementById( "timecoords" ).innerHTML = intro+latLngStr6;
	 	});
      				
		// create the default map
		map.setCenter(new GLatLng(0,0),0);		
					
     GDownloadUrl(xmlfilename, function(data) {
        var xml     = GXml.parse(data);
        var markers = xml.documentElement.getElementsByTagName("marker");
			 var session = xml.documentElement.getElementsByTagName("session");
			  //Session variables by the user
			  for (var t = 0; t < session.length; t++) {
     			var ascent      = session[t].getElementsByTagName('ascent')[0].firstChild.data;
				var descent     = session[t].getElementsByTagName('descent')[0].firstChild.data;
				var call_sign   = session[t].getElementsByTagName('call_sign')[0].firstChild.data;
				var burst       = session[t].getElementsByTagName('burst')[0].firstChild.data;
				var launch_lat  = session[t].getElementsByTagName('lat')[0].firstChild.data;
				var launch_lon  = session[t].getElementsByTagName('lon')[0].firstChild.data;
				var launch_date = session[t].getElementsByTagName('launch_date')[0].firstChild.data;
				var launch_time = session[t].getElementsByTagName('launch_time')[0].firstChild.data;
				var elevation   = session[t].getElementsByTagName('elevation')[0].firstChild.data;
				    station     = session[t].getElementsByTagName('station')[0].firstChild.data;
				var model       = session[t].getElementsByTagName('model')[0].firstChild.data;
	       } //end for loop of session variables
	
	          // load the weather station points data
					loadWXstations(); 
				
					// find a good spot to center the default map at
					var centerofflight = Math.round((markers.length)/3); //third of the data
					var kHgt = new Array(5) // altitudes in feet
						 kHgt[0] = 10000;
						 kHgt[1] = 30000;
						 kHgt[2] = 60000;
						 kHgt[3] = 90000;
						 kHgt[4] = 100000;
						 kHgt[5] = 110000;
	
					var kLoop = new Array(5) // switches
						 kLoop[0] = 1;
						 kLoop[1] = 1;
						 kLoop[2] = 1;
						 kLoop[3] = 1;
						 kLoop[4] = 1;
						 kLoop[5] = 1;
				
			 // for all values in the XML file process the data
         for (var i = 0; i < markers.length; i++) {
				   var Hgt = parseFloat(markers[i].getAttribute("hgt"));    /* altitude of this point */	  
					 var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
													parseFloat(markers[i].getAttribute("lng"))); 
					// ==== Each time a point is found, extent the bounds to include it =====
             		bounds.extend(point);
			
					  // find lat and lon of various altitudes
					  for (var j = 0; j < kHgt.length; j++){ 
						  if (Hgt >= kHgt[j] & kLoop[j] == 1){
								
							  var xxx = kHgt[j]/1000+'k';  // trim off some zeros
							  var aHorizon = Math.round(1.23 * Math.sqrt(parseFloat(Hgt)));
							  var aSpot    = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
																       parseFloat(markers[i].getAttribute("lng")));
							  var aBearing = bearing(launchPoint,aSpot);
							  var aTime    = Math.round(markers[i].getAttribute("ftm"));
							  var aDown    = Math.round(launchPoint.distanceFrom(aSpot)/1609.344);		
							   z = j; //this counts the markers
							
							  var aLab1 = xxx;
								
							  var tip = kHgt[j]+' ft, Horizon: '+aHorizon+' miles, '+aTime+'min. after launch';
							
							  var aHtml1 = 'Altitude: '+xxx+'<br />'+aSpot+'<br />Launch + '+aTime;
							      aHtml1 += ' Minutes'+'<br />Bearing: '+aBearing+' Degrees<br />';
							      aHtml1 += ' Down Range: '+aDown+' Miles';
													
									 // adds the altitude markers one at a time.
     				   		  		aMarker[j] = createTabbedMarker(aSpot,
										[new GInfoWindowTab(aLab1,aHtml1),
										 ],[],
										 kHgt[j]/1000, "click", 'K' , tip);					
							
							  			map.addOverlay(aMarker[j]);
			 				     
								 kLoop[j] = 0; //switch off																
							} // end of if hgt >= KHgt thing
							
						}		// end of for j=0 thing
						
					  if (markers[i].getAttribute("phz") == "Launch"){
						  launchPoint = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
													parseFloat(markers[i].getAttribute("lng")));
													
							//calculate sunrise and sunset times
					 		var strURL = "/cgi-bin/suntime.cgi?";
								strURL += "&type=rise"; 	
								strURL += "&lat="+launchPoint.lat();		
								strURL += "&lng="+launchPoint.lng();		
								strURL += "&zone=-6";		
								strURL += "&date="+launch_date;
									suntime(strURL);		
							
						}//end of finding launchPoint
						
						
						if (markers[i].getAttribute("phz") == "Burst"){
						  burstPoint = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
																parseFloat(markers[i].getAttribute("lng")));
							var burstHgt = parseFloat(markers[i].getAttribute("hgt"));
							// Radio Horizon = 1.23 * sqrt(Antenna Height)
							var burstHorizon = Math.round(1.23 * Math.sqrt(parseFloat(burstHgt)));
						    mHgt = parseFloat(burstHgt);
							var burstFtm = parseFloat(markers[i].getAttribute("ftm"));
							    burstFromLaunch = launchPoint.distanceFrom(burstPoint);
						}//end of finding burstPoint
						
						if (markers[i].getAttribute("phz") == "Touchdown"){
						  touchdownPoint = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
																	  parseFloat(markers[i].getAttribute("lng")));
							var touchdownFtm = parseFloat(markers[i].getAttribute("ftm"));
							    touchdownFromLaunch = launchPoint.distanceFrom(touchdownPoint);
						}//end of finding touchdownPoint
						
						if (i == centerofflight) { //more like 1/3 of it
						  centerSpot = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
																parseFloat(markers[i].getAttribute("lng")));
						}//end of finding center of flight path
						
						//create ascent points and descent points to be plotted
						if (markers[i].getAttribute("phz") == "Launch"
						  | markers[i].getAttribute("phz") == "Ascent"
						  | markers[i].getAttribute("phz") == "Burst") {
               				uppoints.push(new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    		 		  parseFloat(markers[i].getAttribute("lng"))));
           				 } else {
 							 dnpoints.push(new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                    		parseFloat(markers[i].getAttribute("lng"))));
 						 }    						
          } //end for var i loop running thru the markers

			// ===== determine the zoom level from the bounds =====
           map.setZoom(map.getBoundsZoomLevel(bounds));

          // ===== determine the centre from the bounds ======
          var clat = (bounds.getNorthEast().lat() + bounds.getSouthWest().lat()) /2;
          var clng = (bounds.getNorthEast().lng() + bounds.getSouthWest().lng()) /2;
            map.setCenter(new GLatLng(clat,clng));
					
					// put the balloon track ontop of the map ascent and descent
        	map.addOverlay(new GPolyline(uppoints, '#0033ff', 4, 1));
          	map.addOverlay(new GPolyline(dnpoints, '#ff0000', 4, 1));
					
				var gmarkers = [];	
								
					//add a straight line from launch to touchdown point
					l2tpolyline = new GPolyline([launchPoint,touchdownPoint],"#330000",2,1);
				  		map.addOverlay(l2tpolyline);
					
					// add a marker telling us what this line is
					var brng = bearing(launchPoint,touchdownPoint);
			
					var A=3;   // vary these variables to put the marker at
					var B=1;   // different locations along the line

					var nLat = (A*launchPoint.lat()+B*touchdownPoint.lat())/(A+B);
					var nLon = (A*launchPoint.lng()+B*touchdownPoint.lng())/(A+B);				

					var elabelPoint = new GLatLng(nLat,nLon);
					
					var withBreak = brng+' Degrees<br />'+Math.round(touchdownFromLaunch/1609.344)+' miles';
					
					var label2 = new ELabel(elabelPoint, withBreak, "elabel1", new GSize(0,0),90);
      		  			elabels.push(label2); 
							map.addOverlay(label2); 
		
				//add markers with tabbed info windows for launch, burst and touchdown
				// Launch marker	
				z = z + 1;
				e = touchdownPoint.toString();
				d = "'"+e.substring(1,e.length-1)+"'";
	
					lLab1 = 'Launch Site';
			  		lHtml1  = launchPoint;
					lHtml1 += "<br />At: "+launch_time+" ";
				
					lLab2 = "Directions";
        			lHtml2 = '<div style="width:'+3*88+'px">'+'<br>Directions: <a href="javascript:tohere('+z+')">To here</a> - <a href="javascript:fromhere('+z+','+d+')">From here</a></style>';
													
					lLab3 = "Maps";
					lHtml3 = '<div id="tdmini" style="width: 300px; height: 200px;"></div>';
						  
					tip = "Launch Point: "+launchPoint;	
												
					launchMarker = createTabbedMarker(launchPoint,
				    [new GInfoWindowTab(lLab1,lHtml1),
				     new GInfoWindowTab(lLab2,lHtml2),
				     new GInfoWindowTab(lLab3,lHtml3)
				     ],[],			 
					   11,"click",'',tip);
			
        	  		map.addOverlay(launchMarker); 				
			
				// Burst marker		
				z = z + 1;
				var bLab1 = 'Burst';
				var bHtml1  = burstPoint;
				    bHtml1 += "<br />At: "+burstHgt+" feet";
					  bHtml1 += "<br />Bearing: "+bearing(launchPoint,burstPoint);
					  bHtml1 += " degrees<br />Horizon: "+burstHorizon+" miles";
					
				tip = "Burst: "+burstPoint;	
						
				burstMarker = createTabbedMarker(burstPoint,
					[new GInfoWindowTab(bLab1,bHtml1),
				   ],[],
					1,"click",'',tip);
					
        	  map.addOverlay(burstMarker);	
				
				// Touchdown marker 
				z = z + 1;
	
				e = launchPoint.toString();
				d = "'"+e.substring(1,e.length-1)+"'";
				
					tdLab1  = "Touchdown";
					
				 	tdHtml1  =  touchdownPoint;
					tdHtml1 += "<br />At: T+ "+touchdownFtm+" min.";
					tdHtml1 += "<br />Bearing: "+bearing(launchPoint,touchdownPoint);
					tdHtml1 += " degrees";
				
					tdLab2  = "Directions";
          			tdHtml2 = '<div style="width:'+3*88+'px">'+'<br>Directions: <a href="javascript:tohere('+z+','+d+')">To here</a> - <a href="javascript:fromhere('+z+')">From here</a></style>';

					tdLab3 = "Maps";
					tdHtml3 = '<div id="tdmini" style="width: 300px; height: 200px;"></div>';
				
				  tip = "Touchdown: "+touchdownPoint;
					
					touchdownMarker = createTabbedMarker(touchdownPoint,
				    [new GInfoWindowTab(tdLab1,tdHtml1),
				     new GInfoWindowTab(tdLab2,tdHtml2),
					 new GInfoWindowTab(tdLab3,tdHtml3)
					],[],
					  19,"click",'',tip);		 
						
					try {
					}catch(e){
						alert('Error 504:\n\nException creating minimaps '+e);
					}
								
        	  		map.addOverlay(touchdownMarker);			
					
				// draw some circles at the touchdownPoint
				circle1 = drawCircle(touchdownPoint.lng(),touchdownPoint.lat(), 5, "#ff0000", 3, 0.5);
				circle2 = drawCircle(touchdownPoint.lng(),touchdownPoint.lat(), 10, "#000000", 3, 0.5);
				  map.addOverlay(circle1);
				  map.addOverlay(circle2);
				
				var ampm = 'am';
					if (launch_time > 12) ampm = 'pm';
						
					//this is the summary information to the right of the map
					var rHm = Math.round(1.23 * Math.sqrt(parseFloat(mHgt)));
					
					/* set up the current date and time */
					Stamp = new Date();
					epoch = Stamp.getTime();
					
					//this replaces both dashes (-) in the launch_date to slashes (/) to make it a real date value
					targetDate  = new Date((launch_date.replace(/-/,"/")).replace(/-/,"/")+" "+launch_time); 
					targetEpoch = targetDate.getTime();
				
					var Hours;
					var Mins;
					var Time;
						Hours = Stamp.getHours();
							if (Hours >= 12) {
								Time = " P.M.";
							}else {
								Time = " A.M.";
							}
							if (Hours > 12) {
								Hours -= 12;
							}
							if (Hours == 0) {
								Hours = 12;
							}
								Mins = Stamp.getMinutes();
									if (Mins < 10) {
										Mins = "0" + Mins;
									}
				
							tminus = Ttime(Math.floor(targetEpoch - epoch));						

					/* this is the end of the date time stuff */
							   
					var sumListItems = '<ul>';
						sumListItems += '<li><h2><span id="mission" onclick="javascript:ChangeMissionName();">Mission: '+call_sign+'</span></h2></li>';
						sumListItems += '<li><h2>Current Date &amp; Time:</h2></li>';
						sumListItems += '<li>'+(Date()+".")+'</li>';
						sumListItems += '<li>T-minus: '+tminus+'</li>';
						
						sumListItems += '<li><h2>Launch:</h2></li>';
					  	sumListItems += '<li>Call: '+call_sign+'</li>';
					  	sumListItems += '<li><span id="sunR"></span></li>';
						sumListItems += '<li><span id="sunS"></span></li>';
						sumListItems += '<li>Launch: '+launch_time+'</li>';
						sumListItems += '<li>On: '+launch_date+'</li>'
						sumListItems += '<li>Lat: '+launch_lat+'</li>';
						sumListItems += '<li>Lon: -'+launch_lon+'</li>';
						sumListItems += '<li>Base Elev: '+elevation+' ft.</li>';
						sumListItems += '<li onclick="javascript:ck4OtherWXStations();">Using '+model+
						' from '+station+'<b style="color:red";>*</b></li>';
						sumListItems += '<li><i>Requested --</i></li>';
						sumListItems += '<li>Ascent: '+ascent+' ft/m</li>';
						sumListItems += '<li>Max Altitude: '+burst+' feet</li>';
						sumListItems += '<li>Descending: '+descent+' ft/m</li>';
						sumListItems += '</ul><ul>';
						
						sumListItems += '<li><h2>Burst:</h2></li>';
						sumListItems += '<li>At: '+burstPoint+'</li>';
						sumListItems += '<li>Max Alt.: '+mHgt+' feet</li>';
						sumListItems += '<li>Radio Horizon: '+burstHorizon+' miles</li>';
						sumListItems += '<li>Flight Time T+: '+Math.round(burstFtm)+' minutes.</li>';
						sumListItems += '<li>Down Range: '+Math.round(burstFromLaunch/1609.344)+' miles.</li>';
						sumListItems += '</ul><ul>'; 			
						
						sumListItems += '<li><h2>Touchdown:</h2></li>';
						sumListItems += '<li>At: '+touchdownPoint+'</li>';
						sumListItems += '<li>Total Time T+: '+Math.round(touchdownFtm)+' minutes.</li>'
						sumListItems += '<li>Bearing: '+bearing(launchPoint,touchdownPoint)+' deg</li>'; 
						sumListItems += '<li>Down Range: '+Math.round(touchdownFromLaunch/1609.344)+' miles.</li>';
						sumListItems += '</ul><ul>'; 
						
						sumListItems += '</ul>';
											
						
		document.getElementById("call").value=call_sign;  //added 6/9/07 to default plot of callsign
						
		var pos = new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(300,10));
      	pos.apply(document.getElementById("ascent"));
      	map.getContainer().appendChild(document.getElementById("ascent"));
     
		 //  ======== Add a map overview ==========
			
			map.addControl(new GOverviewMapControl(new GSize(100,100))); 
			var overview = document.getElementById("map_overview"); 

			  hideMarkersSet = 0; // this switch is off so all markers are showing
						 
				  try {
				    document.getElementById("uList").innerHTML = sumListItems;
					}catch(e) {
					  alert('Error 610:\n\nProblem writing to uList Div');
					} 
					
					try {
				    map.savePosition();
					}catch(e) {
				    alert('Error 616:\n\nThe savePosition did not work');
					}						
      }); //end of function(data) inside of gdownloadurl
showDiv('getPlot');
	
} //end of load function

function openitup(url) {
	contextmenu.style.visibility="hidden";
	newwindown=window.open(url,'name');
	
}

function timeConvert(blockDate){
	var y = blockDate.substring(0,4);
	var m = blockDate.substring(4,6)-1; /* Jan = 0 */
	var d = blockDate.substring(6,8);
	var h = blockDate.substring(8,10);
	var x = blockDate.substring(10,12);
	var s = blockDate.substring(12,14);
	var dateVar = new Date(y, m, d, h, x, s);
		return dateVar;
	/*
		GLog.write('y= '+y+' m= '+m+' d= '+d+' h= '+h+' x= '+x+' s= '+s+' dateVar= '+dateVar)
*/
}

function suntime(strURL){
	GDownloadUrl(strURL, function(data, responseCode) {
 			var xml = GXml.parse(data);
 			var riseArray = xml.documentElement.getElementsByTagName("rise"); 
 			 	sunRise = GXml.value(riseArray[0]);
 			var setArray = xml.documentElement.getElementsByTagName("set");
 				sunSet = GXml.value(setArray[0]);
 		document.getElementById('sunR').innerHTML = 'Sunrise: '+sunRise+'a.m.';
 		document.getElementById('sunS').innerHTML = 'Sunset: '+sunSet+'p.m.';
	});
}

// A function to create a tabbed marker and set up the event window
// This version accepts a variable number of tabs, passed in the arrays htmls[] and labels[]
// index is the number of the letter or number that appears in the icon
// how is either "click" or "mousover", tip is a standard mouseover tip
function createTabbedMarker(point, htmls, labels, index, how, whichIcon, tip) {
	var letter = String.fromCharCode("A".charCodeAt(0) + index);
	var nummer = String.fromCharCode("01".charCodeAt(0) + index);
	
	if (whichIcon == 'mm'){
		//baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
		baseIcon.shadow = "http://nearspaceventures.com/w3Baltrak/mapicons/mm_20_shadow.png";
		baseIcon.iconSize = new GSize(12, 20);
		baseIcon.shadowSize = new GSize(22, 20);
		baseIcon.iconAnchor = new GPoint(6, 20);
		baseIcon.infoWindowAnchor = new GPoint(5, 1);
	}else if (whichIcon == 'WX'){
		baseIcon.shadow = "./mapicons/shadow.png";
		baseIcon.iconSize = new GSize(20, 34);
		baseIcon.shadowSize = new GSize(37, 34);
		baseIcon.iconAnchor = new GPoint(9, 34);
		baseIcon.infoWindowAnchor = new GPoint(9, 2);
		baseIcon.infoShadowAnchor = new GPoint(18, 25);
	}else{
		baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
		baseIcon.iconSize = new GSize(20, 34);
		baseIcon.shadowSize = new GSize(37, 34);
		baseIcon.iconAnchor = new GPoint(9, 34);
		baseIcon.infoWindowAnchor = new GPoint(9, 2);
		baseIcon.infoShadowAnchor = new GPoint(18, 25);
	}

/*mm_20_   width="12" height="20"*/
	var icon = new GIcon(baseIcon);
		//if (index == 100) index = '00'; // covers 100,000 feet
		if (whichIcon == 'x'){
	  		icon.image = "./mapicons/nicon"+index+".png";
	  	}else if(whichIcon == "rbN"){
	  		icon.image = "./mapicons/rbN.png";
		}else if(whichIcon == "rbS"){
	  		icon.image = "./mapicons/rbS.png";
		}else if(whichIcon == "rbE"){
	  		icon.image = "./mapicons/rbE.png";
		}else if(whichIcon == "rbW"){
	  		icon.image = "./mapicons/rbW.png";
		}else if(whichIcon == "rbNE"){
	  		icon.image = "./mapicons/rbNE.png";
		}else if(whichIcon == "rbSE"){
	  		icon.image = "./mapicons/rbSE.png";
		}else if(whichIcon == "rbSW"){
	  		icon.image = "./mapicons/rbSW.png";
		}else if(whichIcon == "rbNW"){
	  		icon.image = "./mapicons/rbNW.png";
		}else if(whichIcon == 'L'){
	  		icon.image = "./mapicons/dd-start.png";
		}else if(whichIcon == 'M'){
	  		icon.image = "./mapicons/marker"+index+".png";
		}else if(whichIcon == 'K'){
	  		icon.image = "./mapicons/realballoon"+index+".png";
		}else if(whichIcon == '1'){
			icon.image = "./mapicons/marker" + nummer + ".png";
		}else if(whichIcon == 'R'){
			icon.image = "./mapicons/realballoonL.png";
		}else if(whichIcon == 'WX'){
			icon.image = "./mapicons/wx.png";
		}else if(whichIcon == 'mm'){
			icon.image = gicons[index];
		}else{
			icon.image = "./mapicons/marker" + letter + ".png";
		}
		
		var marker = new GMarker(point, {icon:icon, title:tip});
		
		var marker_num = gmarkers.length;   // how many gmarkers are there
        	marker.marker_num = marker_num;
      		marker.htmls = htmls;
      		gmarkers[marker_num] = marker;
  	try {
  	  GEvent.addListener(gmarkers[marker_num], "click", function() {
          marker.openInfoWindowTabsHtml(gmarkers[marker_num].htmls);
          
          	var dMapDiv = document.getElementById("tdmini");          	
          	var tdmini = new GMap2(dMapDiv);
          		tdmini.setCenter(point, 13);
          			tdmini.addControl(new GMapTypeControl(true));
  					tdmini.addControl(new GScaleControl());
  					tdmini.addControl(new GSmallMapControl);
          		
          	var CopyrightDiv = dMapDiv.firstChild.nextSibling;
			var CopyrightImg = dMapDiv.firstChild.nextSibling.nextSibling;
				CopyrightDiv.style.display = "none"; 
				CopyrightImg.style.display = "none"; 		
				
			var	miniMarker = createMarker(point, tip);
				tdmini.addOverlay(miniMarker);
				  
      });
  	}catch(e){
  		GLog.write('Error 678: Exception: '+e);
  	}
	    return marker;
} // end of createTabbedMarker
	
 // functions that open the directions forms
function tohere(z,d) {
  var tabLabel = 'Directions';
  var numTabs = gmarkers[z].htmls.length;
  var divWidth = numTabs * 88;
	
	  if (numTabs < 3) divWidth = 4*88;
  // The info window version with the "to here" form open
  var tabHtml = '<div style="width:'+divWidth+'px">'+
    '<br>Directions: <b>To here</b> - <a href="javascript:fromhere(' + z + ')">From here</a>' +
    '<br>Start address: Default: LaunchPoint<form action="http://maps.google.com/maps" method="get" target="_blank">' +
    '<input type="text" size="40" maxlength="40" name="saddr" id="saddr" value="'+d+'" /><br>' +
    '<input value="Get Directions" type="submit"/>' +
    '<input type="hidden" name="daddr" value="' + gmarkers[z].getPoint().lat() + ',' + gmarkers[z].getPoint().lng() + 
       // "(" + name + ")" + 
    '"/></style>';
		
    gmarkers[z].htmls[numTabs-1]= new GInfoWindowTab(tabLabel,tabHtml);
    gmarkers[z].openInfoWindowTabsHtml(gmarkers[z].htmls,{selectedTab:numTabs-1});
}

function fromhere(z,d) {
  var tabLabel = 'Directions';
  var numTabs = gmarkers[z].htmls.length;
  var divWidth = numTabs * 88;
    if (numTabs < 3) divWidth = 4*88;
        // The info window version with the "from here" form open
  var tabHtml = '<div style="width:'+divWidth+'px">'+
    '<br>Directions: <a href="javascript:tohere(' + z + ')">To here</a> - <b>From here</b>' +
    '<br>End address:<form action="http://maps.google.com/maps" method="get"" target="_blank">' +
    '<input type="text" size="40" maxlength="40" name="daddr" id="daddr" value="'+d+'" /><br>' +
    '<input value="Get Directions" type="submit"/>' +
    '<input type="hidden" name="saddr" value="' + gmarkers[z].getPoint().lat() + ',' + gmarkers[z].getPoint().lng() + 
    '"/></style>';

    gmarkers[z].htmls[numTabs-1]= new GInfoWindowTab(tabLabel,tabHtml);
    gmarkers[z].openInfoWindowTabsHtml(gmarkers[z].htmls,{selectedTab:numTabs-1});
}

function drawCircle(lng, lat, radius, color, width, opacity) {
	var d2r = Math.PI/180;
	var r2d = 180/Math.PI; 
	var Clat = (radius/3963)*r2d;   
	var Clng = Clat/Math.cos(lat*d2r); 
	var Cpoints = [];
			
	  for (var i=0; i < 33; i++) { 
		  var theta = Math.PI * (i/16); 
		    Cx = lng + (Clng * Math.cos(theta)); 
		    Cy = lat + (Clat * Math.sin(theta)); 

		  var P = new GPoint(Cx,Cy);
			
			  //this puts a marker on the circles 
			  if (i == 11){
				  // add ELabels to mark the radius circles
				  var boxScore = radius+' Miles';		
		 		  var label2 = new ELabel(new GLatLng(Cy,Cx), boxScore, "elabel", new GSize(10,0), 90 );
      		  		elabels.push(label2);
						map.addOverlay(label2); 
			  } // end of adding markers to the circles
		      Cpoints.push(P); 
	  }; 
	return new GPolyline(Cpoints, color, width, opacity);
}

// Returns the bearing in degrees between two points.
// North = 0, East = 90, South = 180, West = 270.
function bearing( from, to ) {
  // Convert to radians.
	try {
  		var lat1 = from.latRadians();
  		var lon1 = from.lngRadians();
  		var lat2 = to.latRadians();
  		var lon2 = to.lngRadians();
	}catch(e){
		alert('Error 832:\n\nError in bearing function, check the callsign.');
			return;
	}

  // Compute the angle.
  var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
    if ( angle < 0.0 )
		  angle  += Math.PI * 2.0;

       // And convert result to degrees.
       angle = angle * degreesPerRadian;
       angle = angle.toFixed(1);

    return angle;
}

//hide or show a DIV
function showDiv(layer_ref) {
  if (state == 'visible') {
	  state = 'hidden';
	}else {
	  state = 'visible';
	}
	if (document.all) { //IS IE 4 or 5 (or 6 beta)
	  eval( "document.all." + layer_ref + ".style.visibility = state");
	}
	if (document.layers) { //IS NETSCAPE 4 or below
	  document.layers[layer_ref].visibility = state;
	}
	if (document.getElementById && !document.all) {
	  var maxwell_smart = document.getElementById(layer_ref);
		maxwell_smart.style.visibility = state;
	}
} 

var hideMarkersSet; // switch0=they are showing, 1=they are not
function hideMarkers() {			
	if (hideMarkersSet == 0){
	  hidelabels();
	  for (var i=0;i<gmarkers.length;i++) {
	    map.removeOverlay(gmarkers[i]);
	  }
		  hideMarkersSet = 1;
	}else{
	  showlabels();
	  for (var i=0;i<gmarkers.length;i++) {
	    map.addOverlay(gmarkers[i]);
	  }
		  hideMarkersSet = 0;
	}
}

function hidelabels() {
  for (var i=0; i<elabels.length; i++) {
    elabels[i].hide();
  }
}
      
function showlabels() {
  for (var i=0; i<elabels.length; i++) {
    elabels[i].show();
  }
}

 // This function picks up the click and opens the corresponding info window
function myclick(i) {
  urlMkr.openInfoWindowHtml(htmls[i]);
}


//show the weather activity planner
function showWeX() {
	var wxurl = 'http://forecast.weather.gov/MapClick.php?b0=t&b0mn=&b0mx=&b1=rh&b1mn=&b1mx=&b2=td&b2mn=&b2mx=&b3=wsmph&b3mn=0&b3mx=10&b4=sc&b4mn=0&b4mx=50&b5=pp&b5mn=0&b5mx=25&textField1=39.2048&textField2=-94.3878&Submit=Submit&FcstType=wxplan&site=EAX';
	    wxurl += launchPoint.lat();
	    wxurl += '&textField2=';
	    wxurl += launchPoint.lng();

	window.open(wxurl);
	contextmenu.style.visibility="hidden";
}


//getcall reads the call input field on the map and returns an XML file
//with the current findu location of each call sign, then plots them on the map
//http://www.econym.demon.co.uk/googlemaps/examples/map2.htm
var polyline = [];  //one polyline per call sign
var sidebar_html = "<h2>Live Track:</h2>";
var callcnt = 0; // how many calls regardless of loop count
var bestSpd = 0;
var bestSpdLoc = [];
var bestSpdMkr = [];
var bestSpdCntr = 0;
			
function getCall() {

	var call = removeSpaces(document.getElementById("call").value);
		if (call == ''){alert('Error 928:\n\nNo callsign entered, try again.'); return;}
	var loop = 0;  //how many for each time the go button is clicked
  	var Mpoints = []; 
	var currZoom = map.getZoom();
	var testhgt = 0;		
	var maxhgt = 0;
	var start = 24; //how many hours out from now
	var totChangeUp = 0;	var totChangeDn = 0;
	var hiddenValues = new Array();
	
	// find the ssid of the callsign entered
	// the extra replace is to handle a start time on the call, &start=96 for example
	var	temp = new Array();
		temp = call.replace("&","-").split("-");
	var ssid = temp[1];
	
	var calltype = new Array(10);
		calltype[0] = 'Other';
		calltype[1] = 'Mobile';
		calltype[2] = 'Digipeater';
		calltype[3] = 'Digipeater';
		calltype[4] = 'HF to VHF';
		calltype[5] = 'IGate';
		calltype[6] = 'Mobile';
		calltype[7] = 'D7/D700';
		calltype[8] = 'Boat';
		calltype[9] = 'Mobile';
		calltype[10] = 'Digital';
		calltype[11] = 'Balloon';
		calltype[12] = 'Balloon';
		calltype[13] = 'Misc.';
		calltype[14] = 'Trucks';
		calltype[15] = 'HF';
	 	
	// thank you to Mike Williams at The Blackpool Community Church Javascript Team
	// http://www.econym.demon.co.uk/googlemaps/
	//"findem.xml" or '/cgi-bin/findem.pl?call='+call+'&start=28'
	//pass the start hours in the call 
	  GDownloadUrl('/cgi-bin/findem.pl?call='+call, function(data) {
	  	document.getElementById("gobtn").value = 'Add/Update';
			var xml = GXml.parse(data);
      		var posit = xml.documentElement.getElementsByTagName("posit");
	
			  for (var t = 0; t < posit.length; t++) {
			  	loop = loop + 1; 	 	//local count of callsigns
				callcnt = callcnt + 1;  //global count of callsigns
				
     		  	var callsign = posit[t].getElementsByTagName('callsign')[0].firstChild.data.toUpperCase(); 
     		  
     		  	//is this callsign already in the sidebar?
     		 	if (sidebar_html.indexOf(callsign) > 0){
     		 		stuff  = document.getElementById(callsign).innerHTML; 
     		 			temp = new Array();
						temp = stuff.split(' ');
						cntNsidebar = temp[0];

				 	totalattributes=0;
				 	
					//yes, then get and use its color
					for (i=0;i<document.getElementById(callsign).attributes.length;i++){
						if (document.getElementById(callsign).attributes[i].specified)
							totalattributes++
								el=document.getElementById(callsign);
								el.attributes[0].nodeName //returns the name of the first attribute of el
								el.attributes[0].nodeValue //returns the value of the first attribute of el
					} //end of for loop
                        //the problem above is the value returend is color: red, so split it off below
						findIt = el.attributes[0].nodeValue; /*reassign thisColor */
							temp = new Array();
							temp = findIt.split(' ');
							thisColor = temp[1];
				}else{ //no, assign it a new color
					thisColor = colorx[callcnt];
				} //end of if 
			
					var marker = posit[t].getElementsByTagName('marker');
						if (marker.length == 0){
							alert('Error 1005:\n\nNo APRS data in the last 24 hours for '+callsign+',\ntry another call.');
								return;
						}
						
					var finducnt = marker.length;
					
				if (calltype == 'Balloon') {
					
					var sicon = new GIcon();
						sicon.image = "./mapicons/mm_20_"+colorx[callcnt]+".png";
						sicon.shadow = "./mapicons/mm_20_shadow.png";
						sicon.iconSize = new GSize(12, 20);
						sicon.shadowSize = new GSize(22, 20);
						sicon.iconAnchor = new GPoint(6, 20);
						sicon.infoWindowAnchor = new GPoint(5, 1);
				}else{
					var sicon = new GIcon();
						sicon.image = "./mapicons/"+thisColor+"Car.png";
						sicon.shadow = "./mapicons/mm_20_shadow.png";
						sicon.iconSize = new GSize(12, 20);
						sicon.shadowSize = new GSize(22, 20);
						sicon.iconAnchor = new GPoint(6, 20);
						sicon.infoWindowAnchor = new GPoint(5, 1);
				}
		
					for (var m = 0; m < marker.length; m++) {		
						Mpoints.push(new GLatLng(parseFloat(marker[m].getAttribute("lat")),
												 parseFloat(marker[m].getAttribute("lng"))));
												 									
							var point = new GLatLng(parseFloat(marker[m].getAttribute("lat")),
													parseFloat(marker[m].getAttribute("lng"))); 
							//instantanious values
							var ilat 	 = parseFloat(marker[m].getAttribute("lat"));
							var ilon 	 = parseFloat(marker[m].getAttribute("lng"));
							var itim  	 = marker[m].getAttribute("tim");
							var icrs	 = parseFloat(marker[m].getAttribute("crs")); 
							var ispd  	 = parseFloat(marker[m].getAttribute("spd")); 
							var ialt     = parseFloat(marker[m].getAttribute("alt"));
								if (ialt == 0){ialt = palt;}else{var palt = ialt;}
						
							var itemp 	 = new Date();
							var itemph 	 = itemp.getTimezoneOffset( )/60; // in hours
							var iendtime = new Date(itim.substring(0,4),itim.substring(4,6)-1,
					                           		itim.substring(6,8),itim.substring(8,10)-itemph,
					           				  	 	itim.substring(10,12),itim.substring(12,14));
							var ilastreport = howlong(iendtime);
							
						//find maximum speed
						if (ispd > bestSpd) {
								bestSpd    = ispd;
								bestSpdLoc = new GLatLng(ilat, ilon);
						
								var bestHTML = 'Maximum Speed Location<br />';
									bestHTML += 'Time: '+itim+'<br />';
							    	bestHTML += point+'<br />';
							    	bestHTML += 'course: '+icrs+'<br />';
							    	bestHTML += 'Altitude: '+ialt+'<br />';
							    	bestHTML += 'speed: '+ispd+'mph <br />';
												    
								bestSpdMkr = createTabbedMarker(bestSpdLoc,
				    	  			[new GInfoWindowTab(callsign,bestHTML),
									 new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
									],[],callcnt,"click",'mm','Maximum Speed Marker for: '+callsign);
						} //end of maximum speed routine
														
						if (m == 0) { //this is the first point
							var startHTML = callsign+'<br />First Reported Location<br />';
								startHTML += 'Time: '+itim+'<br />';
							    startHTML += point+'<br />';
							    startHTML += 'course: '+icrs+'<br />';
							    startHTML += 'Altitude: '+ialt+'<br />';
							    startHTML += 'speed: '+ispd+'mph <br />';
							    
							var startMarker = createTabbedMarker(point,
				    	  		[new GInfoWindowTab(callsign,startHTML),
				    	  		 new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
				    	  		],[],callcnt+1,"click",direction(icrs),'First Reported Location');
								
								map.addOverlay(startMarker);
								
							var starttim 	= marker[m].getAttribute("tim");
							var altChangeUp = parseFloat(marker[m].getAttribute("alt"));
							var altChangeDn = parseFloat(marker[m].getAttribute("alt"));
		
						} //end m = 0 if loop
						
						if (m > 0) {// all the rest of the points
							if (testhgt < parseFloat(marker[m].getAttribute("alt"))){
								altChangeUp = (parseFloat(marker[m].getAttribute("alt")) - testhgt);
							}else{
								altChangeDn = (testhgt - parseFloat(marker[m].getAttribute("alt")));
							}
								totChangeUp = altChangeUp + totChangeUp;
								totChangeDn = altChangeDn + totChangeDn;
								
							//should we put a marker at 60k
							if (ialt > 59500 & ialt < 60500 ) {
							  var sixtyHTML = callsign+'<br />Ascent Passed 60,000 Feet Location<br />';
								sixtyHTML += 'Time: '+itim+'<br />';
							    sixtyHTML += point+'<br />';
							    sixtyHTML += 'course: '+icrs+'<br />';
							    sixtyHTML += 'Altitude: '+ialt+'<br />';
							    sixtyHTML += 'speed: '+ispd+'mph <br />';
							    
							  var sixtyMarker = createTabbedMarker(point,
				    	  		[new GInfoWindowTab('First Report',sixtyHTML)],
								['Again',sixtyHTML],callcnt-1,"click",direction(icrs),'Passed 60k Location');
								
								map.addOverlay(sixtyMarker);
							}
						} //end m > 0 if loop
						
						if (m == (marker.length)-1) {		// get the last point (most current) 
						  	var brng  = parseFloat(marker[m].getAttribute("crs")); 
							var hgt   = parseFloat(marker[m].getAttribute("alt")); 
							var tim   = marker[m].getAttribute("tim");
							var spd   = parseFloat(marker[m].getAttribute("spd")); 
							
							//the distance from the launch point to this point
							var launchtoHere = Math.round(launchPoint.distanceFrom(point)/1609.344);				
							var tip = callsign+', '+hgt+'ft, '+spd+'mph, '+launchtoHere+' miles from launch';
							
							//temp and temph are used to adjust the hour value for local time not UTC
							var temp    = new Date();
							var temph   = temp.getTimezoneOffset( )/60; // in hours
							var endtime = new Date(tim.substring(0,4),tim.substring(4,6)-1,
					                           	   tim.substring(6,8),tim.substring(8,10)-temph,
					           				  	   tim.substring(10,12),tim.substring(12,14));
							var lastreport = howlong(endtime);
						}	//end of if loop		     
					
						var testhgt = parseFloat(marker[m].getAttribute("alt")); 
									
						if (testhgt < maxhgt) { 
							var maxlat = testlat;  					
							var maxlon = testlon;
							var maxendtime = testendtime; 	
							var maxspd = testspd;	
							var crs = testcrs;
							var maxM = m;
						} else {
							maxhgt = testhgt;
								var testlat 	= parseFloat(marker[m].getAttribute("lat"));
								var testlon 	= parseFloat(marker[m].getAttribute("lng"));
								var testtim  	= marker[m].getAttribute("tim");
								var testcrs		= parseFloat(marker[m].getAttribute("crs")); 
								var testspd  	= parseFloat(marker[m].getAttribute("spd")); 
								var testtemp 	= new Date();
								var testtemph 	= testtemp.getTimezoneOffset( )/60; // in hours
								var testendtime = new Date(testtim.substring(0,4),testtim.substring(4,6)-1,
					                           			   testtim.substring(6,8),testtim.substring(8,10)-testtemph,
					           				  	 		   testtim.substring(10,12),testtim.substring(12,14));
								var testlastreport = howlong(testendtime);
						}  					
				} //end of marker loop
					
				//plot the max point only if there is one
				if (maxhgt > 0){
					var maxpoint = new GLatLng(maxlat,maxlon);   
					var maxwords = 'Maximum Altitude Report:<br />Place: '+maxlat+', '+maxlon+'<br />At: '
						+maxhgt+' feet<br />Moving At: '
						+testspd+' mph<br />'+testlastreport+' ago';
					
						//plot the point using an appropriate marker icon
						if (sidebar_html.indexOf(callsign) > 0){
							stuff  = document.getElementById(callsign).innerHTML; 
								cntNsidebar = stuff.substring(0,2);
						}else{
							cntNsidebar = callcnt;
						}
						
						//GLog.write('callcnt= '+callcnt+' cntNsidebar= '+cntNsidebar);
						if (ssid == '11' | ssid == '12') {
							var maxmarker = createTabbedMarker(maxpoint,
				    	  		[new GInfoWindowTab('Max Alt',maxwords),
				    	  		 new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
				    	  		],[],cntNsidebar,"click",direction(testcrs),tip);
						}else{	
							var maxmarker = createTabbedMarker(maxpoint,
				    	  		[new GInfoWindowTab('Max Alt', maxwords),
				    	  		 new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
				    	  		],[],cntNsidebar,"click",'mm','Maximum Altitude Marker for: callsign');
						}
     						map.addOverlay(maxmarker);
					} 	
                                           
						//plot the line of the item being tracked 
					  polyline[callcnt-1] = new GPolyline(Mpoints, thisColor, 4, 1);
					    map.addOverlay(polyline[callcnt-1]);
							 if(!document.getElementById('showTrack').checked) {
							    map.removeOverlay(polyline[callcnt-1]);
							 }	
							 	
					var howFar = Math.round((polyline[callcnt-1].getLength())/1609.344);
					var curHrz = Math.round(1.23 * Math.sqrt(parseFloat(ialt)));
						
				 z = z + 1;
				 e = touchdownPoint.toString();
				 d = "'"+e.substring(1,e.length-1)+"'";
				
					var urlMkrLab2  = "Directions";
        			var urlMkrLab2  = "Directions";
        			var urlMkrHtml2 = '<div style="width:'+3*88+'px">'+'<br>Directions: <a href="javascript:tohere('
        				+z+','+d+')">To here</a> - <a href="javascript:fromhere('+z+','+d+')">From here</a></style>';
        				
					// get just the callsign not the ssid 
					var temp = new Array();
						temp = callsign.split('-');
					var modCall = temp[0];
					var urlMkrLabl = callsign;

					var urlMkrHtml = "Current End Point<br />"+point+"<br />";
						urlMkrHtml += "Report Received: "+lastreport+" ago<br />";
						urlMkrHtml += "Course: "+brng+", Speed: "+spd+" MPH, at ";
						urlMkrHtml += hgt+" feet.<br />";
						urlMkrHtml += "Current Radio Horizon: "+curHrz+" miles<br />";
						urlMkrHtml += "Traveled: "+howFar+" miles<br />";
						urlMkrHtml += "Now "+launchtoHere+" miles from the launch site<br />";
						urlMkrHtml += "Touchdown is: "+bearing(point,touchdownPoint)+' degrees, and ';
						urlMkrHtml += Math.round(point.distanceFrom(touchdownPoint)/1609.344)+' miles from here.';
						urlMkrHtml += '<br /><br /><a href="http://www.qrz.com/callsign/'+modCall;
						urlMkrHtml += '" target="_blank"> QRZ link to '+modCall+'</a>';
						
					var urlMkr = createTabbedMarker(point,
						[new GInfoWindowTab(urlMkrLabl,urlMkrHtml),
				     	 new GInfoWindowTab(urlMkrLab2,urlMkrHtml2),
				     	 new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
				     	],[],callcnt-1,"click",direction(brng),tip);
		
        	 	  		map.addOverlay(urlMkr);	
				
							//if the callsign is already in the sideboard lets only update that part of it
							if (sidebar_html.indexOf(callsign) > 0){							 		 
								stuff  = document.getElementById(callsign).innerHTML; 
								cntNsidebar = stuff.substring(0,2);
									
								var mod_html = '<span id="'+callsign+'" style="color:'+thisColor+'">'+cntNsidebar+' -- '
								+callsign+' - '+finducnt+' pts' 
								+'<br /> First: '+timeConvert(starttim)
								+'<br /> Last: '+lastreport
								+'<br /> Traveled: '+howFar+' miles'
								+'<br /> Radio Horizon: '+curHrz+' miles'
								+'<br /> Speed: '+spd+'mph'
								+'<br /> <span id="bstSpd" onclick="javascript:map.addOverlay(bestSpdMkr);">Max Speed: '+bestSpd+'mph</span>'
								+'<br /> Cur Alt: '+ialt+' ft.'
								+'<br /> Max Alt: '
								+maxhgt+' ft.<br />Avg. Ascent: '+Math.round(totChangeUp/finducnt)
								+' fpm<br />Avg. Descent: '
								+Math.round(totChangeDn/finducnt)+' fpm<br /> Position: '+point+'</span>';
								  	//lets replace only this callsign
									document.getElementById(callsign).innerHTML = mod_html;
							}else{  /* this is the default action */
								sidebar_html += '<span id="'+callsign+'" style="color:'+thisColor+'">'+callcnt+' -- '+callsign+' - '
								+finducnt+' pts' /*<br /> Start: '+starttim+'<br />End Time: '+testtim */
								+'<br /> First: '+timeConvert(starttim)
								+'<br /> Last: '+lastreport
								+'<br /> Traveled: '+howFar+' miles'
								+'<br /> Radio Horizon: '+curHrz+' miles'
								+'<br /> Speed: '+spd+'mph'
								+'<br /> <span id="bstSpd" onclick="javascript:map.addOverlay(bestSpdMkr);">Max Speed: '+bestSpd+'mph</span>'
								+'<br /> Cur Alt: '+ialt+' ft.'
								+'<br /> Max Alt: '
								+maxhgt+' ft.<br />Avg. Ascent: '+Math.round(totChangeUp/finducnt)+' fpm<br />Avg. Descent: '
								+Math.round(totChangeDn/finducnt)+' fpm<br /> Position: '+point+'</span><br />';
								
								  document.getElementById("sidebar").innerHTML = sidebar_html;
							}
				} // end of posit loop
		}); //end of download url function
}

function showBestSpd() {
	map.addOverlay(bestSpdMkr);
}

function RGB2HTML(red, green, blue)
{
    var decColor = red + 256 * green + 65536 * blue;
    	return decColor.toString(16);
}

function direction(bering) {
  var whichRB = "";
		if (bering > 0 & bering <= 22.5) {whichRB = "rbN"}
			else if (bering > 22.5 & bering <= 67.5) {whichRB = "rbNE"}
			else if (bering > 67.5 & bering <= 112.5) {whichRB = "rbE"}
			else if (bering > 112.5 & bering <= 157.5) {whichRB = "rbSE"}
			else if (bering > 157.5 & bering <= 202.5) {whichRB = "rbS"}
			else if (bering > 202.5 & bering <= 247.5) {whichRB = "rbSW"}
			else if (bering > 247.5 & bering <= 292.5) {whichRB = "rbW"}
			else if (bering > 292.5 & bering <= 337.5) {whichRB = "rbNW"}
			else if (bering > 337.5 & bering <= 360) {whichRB = "rbN"}	
			
			return whichRB;
}

function showTracks(){
  if(document.getElementById('showTrack').checked) {
	  for (var i = 0; i < polyline.length; i++) {
			map.addOverlay(polyline[i]); 
		}
	}else{
	  for (var i = 0; i < polyline.length; i++) {
			map.removeOverlay(polyline[i]); 
		}
	}
}

function removeSpaces(string) {
	var tstring = "";
	  string = '' + string;
	  splitstring = string.split(" ");
			try {
		  		for(i = 0; i < splitstring.length; i++)
			  		tstring += splitstring[i];
						return tstring;
			}catch(e) {
				alert('Error 1322:\n\nThere is a problem with the call sign, please check the value.');
					return;
			}
}


function howlong(endtime) {
  var endtime = endtime;
  var nowtime = new Date();	

	var longsince = nowtime.getTime() - endtime.getTime();
			
	var msecondsPerMinute = 1000 * 60;
  var msecondsPerHour   = msecondsPerMinute * 60;
  var msecondsPerDay    = msecondsPerHour * 24;
					
	// Calculate how many days longsince contains, then subtract that
  // many days from longsince to come up with a remainder
	var days = Math.floor( longsince / msecondsPerDay );
    longsince = longsince - (days * msecondsPerDay );
						
	// Repeat the previous calculation on the remainder using hours,
  // then subtract the hours from the remainder
  var hours = Math.floor( longsince / msecondsPerHour );
    longsince = longsince - (hours * msecondsPerHour );

  var minutes = Math.floor( longsince / msecondsPerMinute );
    longsince = longsince - (minutes * msecondsPerMinute );

  var seconds = Math.floor( longsince / 1000 );
	
	var lastrpt = days+' day '+hours+' hours '+minutes+' minutes '+seconds+' seconds';
	  
		if (days == 0) {
		  lastrpt = hours+' hours '+minutes+' minutes '+seconds+' seconds';
		}
		if (days == 0 & hours == 0){
		  lastrpt = minutes+' minutes '+seconds+' seconds';
		}
		if (days == 0 & hours == 0 & minutes == 0){
		  lastrpt = seconds+' seconds';
		}
		
	    return lastrpt;
}

var colorIndex = 0;

function rndmColor(){
colors = new Array(14)
colors[0]="0"
colors[1]="1"
colors[2]="2"
colors[3]="3"
colors[4]="4"
colors[5]="5"
colors[5]="6"
colors[6]="7"
colors[7]="8"
colors[8]="9"
colors[9]="a"
colors[10]="b"
colors[11]="c"
colors[12]="d"
colors[13]="e"
colors[14]="f"

digit = new Array(5);
color="#";
for (i=0;i<6;i++){
digit[i]=colors[Math.round(Math.random()*14)]
color = color+digit[i]; 
}
return color;
}

//plot a single point
	var numOfMiscPoint = 0; /* number each one */
	var miscPoint_SideBar = '<h2>Misc. Points:</h2>';
	
function getptCoord() {
	numOfMiscPoint = numOfMiscPoint + 1;
	
  	var ptCoord = removeSpaces(document.getElementById("ptCoord").value);
	var currZoom = map.getZoom();
	var coords = new Array(2);
	 	 	coords = ptCoord.split(",");
	    lat = parseFloat(coords[0]);
	    lon = parseFloat(coords[1]);
	var miscPoint = new GLatLng(lat,lon);
	
	var tip = 'Point # '+numOfMiscPoint+': '+lat+', '+lon;

	var miscMarker = createTabbedMarker(miscPoint,
		[new GInfoWindowTab('Point # '+numOfMiscPoint,lat+', '+lon),
		 new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
		],[],numOfMiscPoint,"click",'1',tip);
					
      map.addOverlay(miscMarker); 

			miscPoint_SideBar += 'Point # '+numOfMiscPoint+' @ '+lat+', '+lon+'<br />';
			
			document.getElementById("pointSidebar").innerHTML = miscPoint_SideBar;
}

var miscMarker;
 // ====== Geocoding ======
function showAddress() {
	numOfMiscPoint = numOfMiscPoint + 1; /* counter continued from above */
	
  var search = document.getElementById("search").value; 
  
    // ====== Perform the Geocoding ======        
    geo.getLocations(search, function (result)
      { 
            // If that was successful
            if (result.Status.code == G_GEO_SUCCESS) {
              // How many resuts were found
             
              // Loop through the results, placing markers
              for (var i=0; i<result.Placemark.length; i++) {
                var p = result.Placemark[i].Point.coordinates;
              
				var point = new GLatLng(p[1],p[0]);
						
				var tip = 'Point # '+numOfMiscPoint+': '+p[1]+', '+p[0];
				var hideit = '<a href="javascript:map.removeOverlay(miscMarker);">Remove this point</a>';
		
				miscMarker = createTabbedMarker(point,       
					[new GInfoWindowTab('Point # '+numOfMiscPoint,p[1]+', '+p[0]+'<br />' +search+'<br /><br />'+hideit),
				     new GInfoWindowTab("Map",'<div id="tdmini" style="width: 300px; height: 200px;"></div>')
				    ],[],numOfMiscPoint,"click",'1',tip);
		
      					map.addOverlay(miscMarker); 

							miscPoint_SideBar += 'Point # '+numOfMiscPoint+' @ '+Math.round(p[1]*10000)/10000;
							miscPoint_SideBar += ', '+Math.round(p[0]*10000)/10000+'<br />';
									
								document.getElementById("pointSidebar").innerHTML = miscPoint_SideBar;
              }
              // centre the map on the first result
              //var p = result.Placemark[0].Point.coordinates;
              //map.setCenter(new GLatLng(p[1],p[0]),14);
            } //end if
            // ====== Decode the error status ======
            else {
              var reason="Code "+result.Status.code;
              if (reasons[result.Status.code]) {
                reason = reasons[result.Status.code]
              } 
              alert('Note 1442:\n\nCould not find "'+search+ '" ' + reason);
            } //end else 
          } //end geo.getlocations
        ); //end geo.getlocations
      } //end function

function loadWXstations(){
  GDownloadUrl('dat/wxstations.txt', function(data){
        // === split the document into lines ===
        lines = data.split("|");

        for (var i=0; i<lines.length; i++) {
          if (lines[i].length > 1) {
            // === split each line into parts separated by "," and use the contents ===
            parts = lines[i].split(",");

				var wxsymb = parts[0].substring(1,4);
				
					if (wxsymb == removeSpaces(station)){		
		            	var wxname  = parts[1];
						var wxstate = parts[2];
            			var wxlat   = parseFloat(parts[3]);
            			var wxlng   = parseFloat(parts[4]);         
            			var wxelev  = Math.round(parseFloat(parts[5])*3.2808399);			
						var wxpoint = new GLatLng(wxlat,wxlng);		
						var wxTbear = bearing(touchdownPoint,wxpoint);
						var wxTdist = Math.round(wxpoint.distanceFrom(touchdownPoint)/1609.344);
						var wxLbear = bearing(launchPoint,wxpoint);
						var wxLdist = Math.round(wxpoint.distanceFrom(launchPoint)/1609.344);
						var wxmsg = 'WX Station '+wxsymb+'<br />'+wxname+', '+wxstate+'<br />'+wxlat+', '+wxlng+
					            '   at '+wxelev+' feet asl'+
					            '<br />'+wxTdist+' miles and '+wxTbear+' deg. from Touchdown<br />'
					                    +wxLdist+' miles and '+wxLbear+' deg. from Launch Point.';
			
						var wxMarker = createTabbedMarker(wxpoint,
					  		[new GInfoWindowTab('WX Station',wxmsg),
				     		],[],'',"click",'WX','Information about the selected WX Station');
           		 			map.addOverlay(wxMarker);
    			 }}}});          
} //end loadWXstations function

//this function looks for other WX stations along and either side of the direct line between the launch point
//and the touchdown point. The area of search is an ellipse whose major foci are the launch and touchdown points
//and whose minor foci are calculaed to be 40% as wide as the distance L to T
function ck4OtherWXStations() {
	var wxcntr = 0;
	var ck4wx = confirm("Look for and mark other WX stations in the flight path?\n\nThis will be done using an ellipse "+
	"to define the search area with launch and touchdown as our foci.\n\nNew stations will appear on the map.");
		
	if (ck4wx) {
		GDownloadUrl('dat/wxstations.txt', function(data){
        // === split the document into lines ===
        lines = data.split("|");
	
        for (var i=0; i<lines.length; i++) {
          if (lines[i].length > 1) {
            // === split each line into parts separated by "," and use the contents ===
            parts = lines[i].split(",");

				var wxsymb = parts[0].substring(1,4);
				
				var wxname  = parts[1];
				var wxstate = parts[2];
           		var wxlat   = parseFloat(parts[3]);
           		var wxlng   = parseFloat(parts[4]);         
           		var wxelev  = Math.round(parseFloat(parts[5])*3.2808399);			
				var wxpoint = new GLatLng(wxlat,wxlng);		
				var wxTbear = bearing(touchdownPoint,wxpoint);
				var wxTdist = Math.round(wxpoint.distanceFrom(touchdownPoint)/1609.344);
				var wxLbear = bearing(launchPoint,wxpoint);
				var wxLdist = Math.round(wxpoint.distanceFrom(launchPoint)/1609.344);
											
				//find out if its in the ellipse..
				//A point P is inside the ellipse if the sum of the distances
				//from P to launchPoint and from P to touchdownPoint is less than touchdownFromLaunch*sqrt(1+r*r)
				
				var PtoT  = Math.round(wxpoint.distanceFrom(touchdownPoint)); // P to touchdownPoint
				var PtoL  = Math.round(wxpoint.distanceFrom(launchPoint));	// P to launchPoint
				var sumD  = Math.round(PtoL + PtoT);	
				var r     = 0.4;  /* ratio of major vs minor axis in the ellipse */						
				var rd    = Math.round(r * touchdownFromLaunch)/1609.344; 			/* minor axis length (distance) */
				var ckVal = Math.round(touchdownFromLaunch*Math.sqrt(1+(r*r)));
									
					if (sumD < ckVal) {	
						var wxmsg = 'WX Station '+wxsymb+'<br />'+wxname+', '+wxstate+'<br />'+wxlat+', '+wxlng+
					            '   at '+wxelev+' feet asl'+
					            '<br />'+wxTdist+' miles and '+wxTbear+' deg. from Touchdown<br />'
					                    +wxLdist+' miles and '+wxLbear+' deg. from Launch Point.';
			
						var wxMarker = createTabbedMarker(wxpoint,
					  			[new GInfoWindowTab('WX Station',wxmsg),
				     		 ],[],			 
					   			'',"click",'WX','Information about the selected WX Station');
           		 			map.addOverlay(wxMarker);
           		 			
           		 		wxcntr = wxcntr + 1;
           		 		//GLog.write('wxcntr= '+wxcntr);
					
					} //end if sumD < ckVal
          } //end if lines[i].length > 1
        } //end for var i=0; i<lines.length; i++
        if (wxcntr < 1) {
        	alert(wxcntr+' No additional WX stations were found.');
        }else{alert(wxcntr+' New WX stations were marked on your map.')}
      }) //end GDownloadUrl function
     
	} //end ck4wx 
} // end ck4OtherWXStations function

function two(x) {
	return ((x>9)?"":"0")+x;
}

function three(x) {
	return ((x>99)?"":"0")+((x>9)?"":"0")+x;
}

function Ttime(ms) {
	var sec = Math.floor(ms/1000);
		ms = ms % 1000;
		t = three(ms);

	var min = Math.floor(sec/60);
		sec = sec % 60;
		t = two(sec) + ":" + t;

	var hr = Math.floor(min/60);
		min = min % 60;
		t = two(min) + ":" + t;

	var day = Math.floor(hr/24);
		hr = hr % 60;
		t = two(hr) + ":" + t;
		t = day + ":" + t;

			return t;
}

function ChangeMissionName() {
	var newMission = prompt("Change Mission name to?", document.getElementById("mission").innerHTML);
	 //confirm('Change '+document.getElementById("mission").innerHTML+' to '+newMission);
	 	document.getElementById("mission").innerHTML = newMission;
}

function geoCodethis() {
var	insideHtml = '<form onsubmit="showAddress(); return false">';
	insideHtml += '<h2>GeoCode an Address:</h2>';
	insideHtml += 'Enter an address:<br />';
    insideHtml += '<input id="search" size="60" type="text" value="10 Richards Rd., Kansas City, Missouri 64116"><br />';
    insideHtml += '<input type="submit" value="Plot!">';
    insideHtml += '<br /><br />';
    insideHtml += '<h2>Mark a Point:</h2>';
    insideHtml += 'Enter a coordinate:<br />';
	insideHtml += '<input name="ptCoord" type="text" id="ptCoord" value="'+theCenter+'"  size="30" /><br />';
	insideHtml += '<input onclick="getptCoord()" type="button" class="goptbtn" value ="Plot" />';
	insideHtml += '</form>';
	/*mac_os_x*/
var win = new Window({className: "mac_os_x", title: "Geocoding Options",
	width:500, height:350}); 
  win.getContent().innerHTML = insideHtml; 

  win.setDestroyOnClose(); 
  win.showCenter();
  win.setConstraint(true, {left:0, right:0, top: 30, bottom:10})
  win.toFront();
  contextmenu.style.visibility="hidden";
}

function help(trialArray) { 

	var win = new Window('window_id', {className: "dialog", title: "dumpArray",top:100, left:100,  width:600, height:575, zIndex:150, opacity:1, resizable: false, minimizable: true, maximizable: false});

	win.getContent().innerHTML = accordian();
	win.setDestroyOnClose();
	win.showCenter(); 
	win.toFront();

	var myAccordion2 = new Rico.Accordion( $('accordionDiv'), {panelHeight:300} );
	contextmenu.style.visibility="hidden";
}

//In the nearspace folder where this javascript is, is also a folder called windows_js_1.3 it contains all the info
//about making this cool stuff work. The accordian thing below is part of the rico stuff.
function accordian() {
var htmlString = '';
	htmlString += '<div id="accordionDiv">';
	htmlString += '<div id="help2Panel">';
	htmlString += '<div id="help2Header" class="accordionTabTitleBar">';
	htmlString += 'Help +';
	htmlString += '</div>';
	htmlString += '<div id="helpContent2" class="accordionTabContentBox">';
	htmlString += 'Click on the blue title bars below to view ';
	htmlString += 'additional content<br /><br />';
	htmlString += 'Try this...<br />';
	htmlString += '<ul>';
	htmlString += '<li>Rightclick any place on the map... the gridsquare of that location will be displayed.</li>';
	htmlString += "<li>Click on 'Show track' and 'Go' to follow a balloon using findu.com, click on 'Add/Update' and ";
	htmlString += "it's position will be updated.</li>";
	htmlString += "<li>By clicking anyplace in the 'Mission' box in the sidebar you can change your mission name</li>";
	htmlString += "<li>By clicking on the 'Using...' information line in the sidebar, you can ask the system to find ";
	htmlString += "any additional NOAA reporting airports within the predicted flight path.</li>";
	htmlString += "<li>By clicking the 'Geocode a point or address' button at the bottom of the screen you can place ";
	htmlString += "a marker at either an address or latitude longitdue, or both...</li>";
	htmlString += "<li>Directions to or from the launch or touchdown point are available by clicking the marker.</li>";
	htmlString += "<li>A more detail map of the launch and touchdown point are available by clicking the marker.</li>";
	htmlString += "<li>Adding a '&start=48' to the callsign makes findu use data starting 48 hours ago, any value ";
	htmlString += "can be used in this way. e.g. wa0tjt-1&start=96</li>";
	htmlString += "<li>After adding the track of a callsign, clicking on the max speed in the sidebar adds a marker ";
	htmlString += "at the location of it.</li>";
	htmlString += '</ul>';
	htmlString += '</div>';
	htmlString += '</div>';
	htmlString += '<div id="addcomment2Panel">';
	htmlString += '<div id="addcomment2Header" class="accordionTabTitleBar">';
	htmlString += 'Add Comment Form';
	htmlString += '</div>';
	htmlString += '<div id="addcomment2Content" class="accordionTabContentBox">';
	htmlString += 'Use the Add a comment tool to add a comment<br />';
	htmlString += 'This function coming soon...';
	htmlString += '</div>';
	htmlString += '</div> ';
	htmlString += '<div id="disclaimer2Panel">';
	htmlString += '<div id="disclaimer2Header" class="accordionTabTitleBar">';
	htmlString += 'Who are we.... and Who wrote all this??';
	htmlString += '</div>';
	htmlString += '<div id="disclaimer2Content" class="accordionTabContentBox">';
	htmlString += '<h2>Near Space Ventures Inc.</h2>';
	htmlString += 'All the Perl scripts that collect the NOAA data and do all the heavy math ';
	htmlString += 'were written by: <b>Troy Campbell</b><br /><br />';
    htmlString += 'The Google maps interface and all its toys was written by: <b>Keith Kaiser</b><br /><br />';
    htmlString += 'A lot of other code is in here from various sources who were kind enough to lend ';
    htmlString += 'their talents. Each is recognized within the various javaScript they contributed.<br />';
    htmlString += 'Some of these people are;<br />'
    htmlString += 'Laurent Haas F6FVY ==> http://f6fvy.free.fr/qthLocator/fullScreen.php<br />';
	htmlString += 'Doug Henderson ==> http://www3.telus.net/DougHenderson/MarkerTabs_v2.html	<br />';
	htmlString += 'Mike Williams ==> http://www.econym.demon.co.uk/googlemaps/index.htm<br />';
	htmlString += 'Zouzou Wizman ==> http://prototype-window.xilinus.com/index.html<br /><br />';
	htmlString += 'If you have any questions, problems, praise or ideas for enhancments<br /> ';
	htmlString += 'please send e-Mail to keith.kaiser@gmail.com<br />';
	htmlString += '<br />P.S.<br />We will also take donations, balloons are expensive.';	
	htmlString += '</div>';
	htmlString += '</div>';
	htmlString += '</div>';	

		return htmlString;
}

var responseCode;
var LogData;
function finduLogClick() {
	var call = removeSpaces(document.getElementById("call").value);
		if (call == ''){alert('Error 1723:\n\nNo callsign entered, try again.'); return;};
		
			GDownloadUrl('http://nearspaceventures.com/cgi-bin/findem.pl?call='+call, function(data, responseCode) {

				var xml = GXml.parse(data);
      			var posit = xml.documentElement.getElementsByTagName("posit");
      			//var callsign = posit.getElementsByTagName('callsign')[0].firstChild.data.toUpperCase(); 
	
			  //for (var t = 0; t < posit.length; t++) {
				
				//var findUdata = '<h2>Log of: '+call+'<br /><br />';
					//findUdata += data;
			GLog.write(data);
		/*		var win = new Window({className: "mac_os_x", title: "Findu Log of: "+call,
					width:500, height:350}); 
  
  					win.getContent().innerHTML = findUdata; 

  					win.setDestroyOnClose(); 
  					win.showCenter();
  					win.setConstraint(true, {left:0, right:0, top: 30, bottom:10});
  					win.toFront(); */
			  //}
			});
}

// Creates a simple marker at the given point
function createMarker(point, words) {
	var marker = new GMarker(point,{draggable:true});
  		GEvent.addListener(marker, "click", function() {
     	marker.openInfoWindowHtml(words);
     });
	return marker;
} 
var spoint;
var epoint;

function addSMarker() {
	point = clicklatlng;
	spoint =  new GLatLng(clicklatlng.y,clicklatlng.x);	
	xpoint = Math.round(clicklatlng.y * 10000) / 10000+' '+Math.round(clicklatlng.x * 10000) / 10000;
	title = 'Start Marker';
	var typeIcon = new GIcon(G_DEFAULT_ICON);
	typeIcon.image = "./mapicons/dd-start.png";
	
	
	smarker = new GMarker(point,{icon:typeIcon, title:title, draggable:true});
	var stolaunch = Math.round(spoint.distanceFrom(launchPoint)/1609.344);
	var stotouch = Math.round(spoint.distanceFrom(touchdownPoint)/1609.344);
	
	stab1Words = '<div id="tab1" class="bubble"><ul>';
	stab1Words +='<li>This Location: '+xpoint+'</li><br />';
	stab1Words +='<li>'+stolaunch+' miles to the launch point</li>';
	stab1Words +='<li>'+stotouch+' miles to the touchdown point</li><br />';
	stab1Words +='<li><a href="javascript:map.removeOverlay(smarker);">Remove this point</a></li>';
	stab1Words +='</ul></div>';
	
	GEvent.addListener(smarker, "click", function() {
		var tab1 = new GInfoWindowTab("Info", stab1Words);
		var tab2 = new GInfoWindowTab("Map", '<div id="tdmini" style="width: 300px; height: 200px;"></div>');
		var infoTabs = [tab1,tab2];
		smarker.openInfoWindowTabsHtml(infoTabs);
	});
		map.addOverlay(smarker);
		contextmenu.style.visibility="hidden";
}

var s2epolyline;

function addEMarker() {
	point = clicklatlng;
	epoint =  new GLatLng(clicklatlng.y,clicklatlng.x);	
	xpoint = Math.round(clicklatlng.y * 10000) / 10000+' '+Math.round(clicklatlng.x * 10000) / 10000;
	title = 'End Marker';
	var typeIcon = new GIcon(G_DEFAULT_ICON);
	typeIcon.image = "./mapicons/dd-end.png";
	
	
	emarker = new GMarker(point,{icon:typeIcon, title:title});
	var etosmarker = Math.round(epoint.distanceFrom(spoint)/1609.344);
	var etolaunch = Math.round(epoint.distanceFrom(launchPoint)/1609.344);
	var etotouch = Math.round(epoint.distanceFrom(touchdownPoint)/1609.344);
	var stoebearing = bearing(spoint, epoint);
	
	etab1Words = '<div id="tab1" class="bubble"><ul>';
	etab1Words +='<li>This Location: '+xpoint+'</li><br />';
	etab1Words +='<li>Bearing from Start: '+stoebearing+' degrees</li>';
	etab1Words +='<li>Start to End distance: '+etosmarker+' miles</li>';
	etab1Words +='<li>'+etolaunch+' miles to the launch point</li>';
	etab1Words +='<li>'+etotouch+' miles to the touchdown point</li><br />';
	etab1Words +='<li><a href="javascript:map.removeOverlay(emarker); map.removeOverlay(s2epolyline); map.removeOverlay(smarker);">Remove this marker</li>';
	etab1Words +='</ul></div>';
	 
	GEvent.addListener(emarker, "click", function() {
		var tab1 = new GInfoWindowTab("Info", etab1Words);
		var tab2 = new GInfoWindowTab("Map", '<div id="tdmini" style="width: 300px; height: 200px;"></div>');
		var infoTabs = [tab1,tab2];
		emarker.openInfoWindowTabsHtml(infoTabs);
	});
		map.addOverlay(emarker);
			s2epolyline = new GPolyline([spoint,epoint],"#330000",2,1);
				map.addOverlay(s2epolyline);
		contextmenu.style.visibility="hidden";
}


function gridsquare(){
	
	if (clickedPixel) {
		var longDir;
          if (clicklatlng.x < 0)
            longDir = "W"
          else
            longDir = "E";
          var latDir;
          if (clicklatlng.y < 0)
            latDir = "S"
          else
            latDir = "N";
            
          var longDeg;
          var longMin;
          if (clicklatlng.x > 0){
            longDeg = Math.floor(clicklatlng.x);
            longMin = (clicklatlng.x - longDeg) * 100;
          }else{
            longDeg = Math.ceil(clicklatlng.x);
            longMin = (longDeg - clicklatlng.x) * 100;
          }
          
          var longMin2 = longMin * 60 / 100;
          var longSec = Math.round((longMin2 - Math.floor(longMin2)) * 60);
          
          var latDeg;
          var latMin;
          
          if (clicklatlng.y > 0){
            latDeg = Math.floor(clicklatlng.y);
            latMin = (clicklatlng.y - latDeg) * 100;
          }else{
            latDeg = Math.ceil(clicklatlng.y);
            latMin = (latDeg - clicklatlng.y) * 100;
          }
          
          var latMin2 = latMin * 60 / 100;
          var latSec = Math.round((latMin2 - Math.floor(latMin2)) * 60);
          
          var strHtml = "<font face='arial' size='3'>Grid Square Calculator<br />\n";
          strHtml += "Lat : " + Math.round(clicklatlng.y * 10000) / 10000 + " " + latDir;
          strHtml += " (" + latDeg + "&deg; " + Math.floor(latMin2) + "' " + latSec + "'' "+ latDir + ")";
          strHtml += "<br />\n";
          strHtml += "Long : " + Math.round(clicklatlng.x * 10000) / 10000 + " " + longDir;
          strHtml += " (" + longDeg + "&deg; " + Math.floor(longMin2) + "' " + longSec + "'' "+ longDir + ")";
          strHtml += "<br />\n";
        
          var ychr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
          var ynum = "0123456789";
          var yqth, yi, yk, ydiv, yres, ylp, y;
          var y     = 0;
          var ycalc = new Array(0,0,0);
          var yn    = new Array(0,0,0,0,0,0,0);

          ycalc[1] = clicklatlng.x + 180;
          ycalc[2] = clicklatlng.y +  90;

          for (yi = 1; yi < 3; ++yi) {
            for (yk = 1; yk < 4; ++yk) {
              if (yk != 3) {
                if (yi == 1) {
                  if (yk == 1) ydiv = 20;
                  if (yk == 2) ydiv = 2;
                }
                if (yi == 2) {
                  if (yk == 1) ydiv = 10;
                  if (yk == 2) ydiv = 1;
                }

                yres = ycalc[yi] / ydiv;
                ycalc[yi] = yres;
                if (ycalc[yi]>0)
                  ylp = Math.floor(yres)
                else
                  ylp = Math.ceil(yres);
                ycalc[yi] = (ycalc[yi] - ylp) * ydiv;
              }else {
                if (yi == 1)
                  ydiv = 12
                else
                  ydiv = 24;

                yres = ycalc[yi] * ydiv;
                ycalc[yi] = yres;
                if (ycalc[yi] > 0)
                  ylp = Math.floor(yres)
                else
                  ylp = Math.ceil(yres);
              }

            ++y;
            yn[y] = ylp;
            }
          }
  
          yqth = ychr.charAt(yn[1]) + ychr.charAt(yn[4]) + ynum.charAt(yn[2]);
          yqth += ynum.charAt(yn[5]) + ychr.charAt(yn[3])+ ychr.charAt(yn[6]);

          strHtml += "Grid Square: " + yqth + "</font>";

   //      map.removeOverlay(polygonClick);
   		  //polygonClick.redraw(true);
          map.openInfoWindowHtml(clicklatlng, strHtml);
      
          // Square limits
          var bottomLeftLong = Math.floor(clicklatlng.x / 0.0833333333) * 0.0833333333;
          var bottomLeftLat = Math.floor(clicklatlng.y / 0.0416666666) * 0.0416666666;
                 
          polygonClick = new GPolygon([
            new GLatLng(bottomLeftLat, bottomLeftLong),
            new GLatLng(bottomLeftLat, bottomLeftLong + 0.0833333333),
            new GLatLng(bottomLeftLat + 0.0416666666, bottomLeftLong + 0.0833333333),
            new GLatLng(bottomLeftLat + 0.0416666666, bottomLeftLong),
            new GLatLng(bottomLeftLat, bottomLeftLong)
          ], "#FF0000", 4,.25,'red',.10);
                          
          map.addOverlay(polygonClick);
          contextmenu.style.visibility="hidden";
        } // if (point)
} // end of gridsquare

function originalPosition() {
	map.returnToSavedPosition();
	contextmenu.style.visibility="hidden";
}

function zoomInHere() {
        // perform the requested operation
        var point = map.fromContainerPixelToLatLng(clickedPixel)
        map.zoomIn(point,true);
        // hide the context menu now that it has been used
        contextmenu.style.visibility="hidden";
}      
function zoomOutHere() {
        // perform the requested operation
        var point = map.fromContainerPixelToLatLng(clickedPixel)
        map.setCenter(point,map.getZoom()-1); // There is no map.zoomOut() equivalent
        // hide the context menu now that it has been used
        contextmenu.style.visibility="hidden";
}      
function centreMapHere() {
        // perform the requested operation
        var point = map.fromContainerPixelToLatLng(clickedPixel)
        map.setCenter(point);
        // hide the context menu now that it has been used
        contextmenu.style.visibility="hidden";
}

function add() {
var marker1;
var marker2;
var label1;
var label2;
var button=0;
var dist=0;
var line;
var poly;
var m1; var m2;
	
function measure() {
	if(marker1&&marker2)
		line = [marker1.getPoint(),marker2.getPoint()];
		dist=marker1.getPoint().distanceFrom(marker2.getPoint());
		dnum=dist;
		var direction=parseInt(bearing(marker1.getPoint(),marker2.getPoint()));
		
			if (direction < 180) {
				m1=direction+180;
				m2=direction;
			} else
			if (direction > 180) {
				m2=direction;
				m1=direction-180;	
			}
			
		dist="&nbsp;&nbsp;"+dist.toFixed(0)+"m<br />&nbsp;&nbsp;"+Math.round(dist.toFixed(0)*1.0936133)+"yards"; 
	if(parseInt(dnum)>1609){
		dist="&nbsp;&nbsp;"+(parseInt(dnum)/1000).toFixed(1)+"km<br />&nbsp;&nbsp;"+Math.round((parseInt(dnum)/1000).toFixed(1)*0.621371192)+"miles";}		
		
		label1.setContents("m1&nbsp;<br />"+dist+"<br />"+m1+"degrees");
		label2.setContents("m2&nbsp;<br />"+dist+"<br />"+m2+"degrees");
		
		label1.setPoint(marker1.getPoint());
		label2.setPoint(marker2.getPoint());
		
	if(poly)map.removeOverlay(poly);
		poly = new GPolyline(line,'#FFFF00', 8, 1)
		map.addOverlay(poly);
}

document.getElementById("add").value="click on map";

GEvent.addListener(map, 'click', function(overlay,pnt) {
	if(pnt&&button==0) {
		marker1 = new GMarker(pnt,{draggable: true});
		map.addOverlay(marker1);
		marker1.enableDragging();
		label1=new ELabel(pnt, dist,"labelstyle",new GSize(2,20),60);
			map.addOverlay(label1);
		marker2 = new GMarker(pnt,{draggable: true});
			map.addOverlay(marker2);
		marker2.enableDragging();
		label2=new ELabel(pnt, dist,"labelstyle",new GSize(2,20),60);
			map.addOverlay(label2);
	}
	
GEvent.addListener(marker1,"drag",function(){measure();});
GEvent.addListener(marker1,"dblclick",function(){clr();});
GEvent.addListener(marker2,"drag",function(){measure();});
GEvent.addListener(marker2,"dblclick",function(){clr();});
document.getElementById("add").value="You Have a Ruler";
button++;
});

function clr(){
//map.clearOverlays();
	map.removeOverlay(poly);
	map.removeOverlay(marker1);
	map.removeOverlay(marker2);
	map.removeOverlay(label1);
	map.removeOverlay(label2);
		button=0;
		document.getElementById("add").value="New Ruler";
			dist=0;
}
} // This is actually the end of the add function

