      // Create our "tiny" marker icon
	function createIcon( icon_name )
	{
	        var iconi = new GIcon();
	        iconi.image = icon_name;
		//iconi.shadow = icon_name;
	        iconi.iconSize = new GSize(20, 20);
	        iconi.shadowSize = new GSize(20, 20);
	        iconi.iconAnchor = new GPoint(10, 10);
	        iconi.infoWindowAnchor = new GPoint(20, 1);
		return iconi;
	}

	var icon = createIcon( "http://labs.google.com/ridefinder/images/mm_20_red.png" );

        var crosshairicon = new GIcon();
        crosshairicon.image = "http://www.gps-waypoints.net/gps/images/crosshair.gif";
        crosshairicon.shadow = "http://www.gps-waypoints.net/gps/images/crosshair.gif";
        crosshairicon.iconSize = new GSize(8, 8);
        crosshairicon.shadowSize = new GSize( 8 , 8 );
        crosshairicon.iconAnchor = new GPoint(4, 4);
        crosshairicon.infoWindowAnchor = new GPoint(5, 1);

	var map;
        var markers = [];
        var points = [];
        var points_ids = [];
        var trackpoints = [];
	var count = 0;
	var typeId = null;
	var trackcount = 0;
	var trackcenter = 0;
	var centerMarker = null;
	

	var crosshairMarker;
        var playRoute_ = 1; // set to 0 to stop playing and centering on route
        var routeDelay = 4100;

	function clearPointsAndMarkers()
	{
		getMap().clearOverlays();                
        	markers = [];
	        points = [];
		points_ids = [];
	        trackpoints = [];
		count = 0;
		trackcount = 0;
		trackcenter = 0;
	}

	function getSelectedSelectOptions(select_id)
	{
	        var res = Array();
	        var el = document.getElementById(select_id);
        	for( i = 0 ; i < el.options.length ; i++)
	        {
        	        if ( el.options[i].selected )             
                	        res.push( el.options[i].value );
	        }
        	return res;
	}

	function getSelectedDropdownOption(select_id)
	{
	        var el = document.getElementById(select_id);
		if ( el != null )
	        {
			return el.value;
	        }
		return null;
	}

	function addCenterCrosshair()
	{
		if ( centerMarker != null ) {
			getMap().removeOverlay( centerMarker );
		}

		var center = getMap().getCenter();
                var point = new GLatLng( center.lat(), center.lng() );
                var icon = createIcon( "http://www.gps-waypoints.net/gps/images/crosshair_large.png" );
                icon.iconSize = new GSize(32, 32);
                centerMarker = new GMarker( point, icon );
                getMap().addOverlay( centerMarker );
	}

	function marshallWaypoints(json_response)
	{   
//	    clearPointsAndMarkers();

	    var el = document.getElementById("waypoint_count");
	    if ( el != null )
		    el.value = json_response['waypoints'].length;

	    var el = document.getElementById("json_response");
	    table =     '<table>';
	    alt = '';

	    // Loop all waypoints in JSON response
	    for(i = 0; i < json_response['waypoints'].length; i++)
	    {
		// FIXES IE BUG! IE JSON returns .length a wrong value and we need to check if array cell exists
		if ( json_response['waypoints'][i] == null ) continue;

	        //var icon  = '/gps/images/waypoint_types/'+json_response['waypoints'][i].type+'.jpg';
	        var icon  = '/gps/images/waypoint_types/default.jpg';
	        var id  = json_response['waypoints'][i].id;
	        var name = json_response['waypoints'][i].name + "<br><br>" +json_response['waypoints'][i].desc;
	        var text = '<a href="/gps/?page=show_one_waypoint&amp;id='+id+'">'+ name +' </a>';

	        createWaypoint2( json_response['waypoints'][i].latitude , json_response['waypoints'][i].longitude , text , icon , json_response['waypoints'][i].id );
	    }
	}

	function updateDownloadLink(downloadLinkID, type, fileformat,token)
	{
		var bounds = getMap().getBounds();
		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();
		if ( token == null || token == undefined ) token = "";

		  downloadEl = document.getElementById( downloadLinkID );

		  if ( downloadEl != null )
		  {
			if ( fileformat == null || fileformat == undefined )
				fileformat = "smart_csv";

			downloadEl.href="http://www.gps-waypoints.net/gps/generate_waypoint_file.php?mode=show_waypoints&fileformat="+fileformat+"&limit=yes&type=" + type + "&token="+token;
			downloadEl.href+="&lat_start="+sw.lat()+"&lat_end="+ne.lat()+"&lon_start="+sw.lng()+"&lon_end="+ne.lng();
		  }
	}

	function loadWaypoints(type, downloadLinkID , fileformat, callbackDone, token )
	{
		var bounds = getMap().getBounds();
		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();
		if ( token == null || token == undefined ) token = "";
		
		var downloadEl = null;

		// If we want to enable downloading, the downloadLinkID contains the id for link anchor 
		// The links href is changed to download url so user can load the points in map
		if ( downloadLinkID != null )
		{
			updateDownloadLink(downloadLinkID, type, fileformat,token);
		}

	        // Create "XMLHttpRequest" that is browser independent
	        // Internet Explorer
	        try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
	        catch(e)
	        {
	              try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
	              catch(oc) { xmlhttp = null; }
	        }
	        // Mozailla/Safari
	        if (!xmlhttp && typeof XMLHttpRequest != "undefined") { xmlhttp = new XMLHttpRequest(); }
	
	        var req_url="http://www.gps-waypoints.net/gps/generate_waypoint_file.php?mode=show_waypoints&fileformat=json&limit=yes&type=" + type + "&token="+token;
		req_url+="&lat_start="+sw.lat()+"&lat_end="+ne.lat()+"&lon_start="+sw.lng()+"&lon_end="+ne.lng();

		var e = document.getElementById("debugMessage");
//		if ( e!= null)
//			e.innerHTML = req_url;

	        xmlhttp.open('GET', req_url, true);
	        xmlhttp.onreadystatechange = function()
	        {
	            if (xmlhttp.readyState == 4)
	            {
	                // Callback code
			var response = '(' + xmlhttp.responseText + ')';
	                json_waypoints = eval(response);

			if ( typeId != parseInt(type) ){
//				alert("clearing " + typeId + " " + type);
				typeId = parseInt(type);
				clearPointsAndMarkers();
			}
	                marshallWaypoints(json_waypoints);
	                //initPoints();

			// If callback function for "done" is specified we call it
			if ( callbackDone != null )
				callbackDone();
	            }
	        }
	
	        xmlhttp.send(null);
	}


        function playRoute()
        {                     
                playRoute_ = 1;
                window.setTimeout( centerToTrack , routeDelay);

		// if controls are visible, then update button visibility
		if ( document.getElementById("map_controls") != null && 
			document.getElementById("map_controls").style.visibility == 'visible' )
		{
			if ( document.getElementById("play_button") != null )
		                document.getElementById("play_button").style.visibility = 'hidden';
			if ( document.getElementById("pause_button") != null )
		                document.getElementById("pause_button").style.visibility = 'visible';
		}
		updateSpeedValue();
        }

        function pauseRoute()
        {
                playRoute_ = 0;

		// if controls are visible, then update button visibility
		if ( document.getElementById("map_controls") != null && 
			document.getElementById("map_controls").style.visibility == 'visible' )
		{
			if ( document.getElementById("play_button") != null )
		                document.getElementById("play_button").style.visibility = 'visible';
			if ( document.getElementById("pause_button") != null )
		                document.getElementById("pause_button").style.visibility = 'hidden';
		}
        }

        function playRouteFaster()
        {
                if ( routeDelay >= 1000 ) routeDelay = routeDelay - 1000;
                updateSpeedValue();
        }

        function playRouteSlower()
        {         
                if ( routeDelay < 10000 ) routeDelay = routeDelay + 1000;
                updateSpeedValue();
        }

        function updateSpeedValue()
        {
                document.getElementById("play_speed").value = 10 - Math.round(routeDelay/1000);
        }

        function showControlButtons()
        {             
                document.getElementById("map_controls").style.visibility = 'visible';

                // if we are playing the route show pause button, and if we are in paused state
                // then show play button
                if ( playRoute_ == 0 )
                        document.getElementById("play_button").style.visibility = 'visible';
                else
                        document.getElementById("pause_button").style.visibility = 'visible';

                document.getElementById("map_controls_hidden").style.visibility = 'hidden';
        }

        function hideControlButtons()
        {             
                // Hide play/pause buttons
                document.getElementById("play_button").style.visibility = 'hidden';
                document.getElementById("pause_button").style.visibility = 'hidden';

                document.getElementById("map_controls").style.visibility = 'hidden';
                document.getElementById("map_controls_hidden").style.visibility = 'visible';
        }

	function centerMapTo(lat,lon)
	{
		map.panTo( new GLatLng(lat,lon,true) );
	}

	function centerMapAndZoomClose(lat,lon,zoom)
	{
		map.setCenter( new GLatLng(lat,lon,true) , zoom/*zoom*/, G_NORMAL_MAP /*G_HYBRID_MAP*/ );
	}


	// This function is used to center view to track
	function centerToTrack()
	{
          // if playing disabled, then don't center and don't register timeout timer
          if ( playRoute_ == 0 ) return;

	  // increase track center index by one. ( wrap to beginning when end has been reached. )
	  trackcenter = (trackcenter+1) % trackpoints.length;

	  map.panTo( trackpoints[trackcenter] );

	  map.removeOverlay( crosshairMarker  );
	  crosshairMarker = new GMarker( trackpoints[trackcenter], crosshairicon );
	  map.addOverlay( crosshairMarker );

	  // Reregister time out to eventually we will travel the whole route
	  window.setTimeout( centerToTrack , routeDelay);
	}

    function registerGEvent( source,event,listener)
    {
	return GEvent.addListener(source,event,listener);
    }

    function registerEvent( event,listener)
    {
	return registerGEvent( getMap(),event,listener);
    }

    function getMap()
    {
	return map;
    }

    function getGEvent()
    {
	return GEvent;
    }

    // Add new waypoint to map and arrays if it isn't already there
    function createWaypoint2( lat , lon ,text , icon_url, id )
    {
	// IE doesn't understand "indexOf" so we need to make this the hard way... grrr :(
	for( var i = 0 ; i < points_ids.length ; i++ )
	{
		if ( points_ids[i] == id ){
			return;
		}
	}
	createWaypoint( lat , lon ,text , icon_url );
	addMarkerToMap( markers[count-1] );
	points_ids.push( id );
    }

    function createWaypoint( lat , lon ,text , icon_url )
    {
	var m_icon = createIcon( icon_url );
	var point = new GLatLng( lat,lon,true );
	var marker = new GMarker(point, m_icon,false);
        GEvent.addListener(marker, "click", function()
        {
  	  marker.openInfoWindowHtml(text);
        });

	points[count] = point;
	markers[count] = marker;
	count++;
    }

    function createTrackpoint( lat , lon  )
    {
	var point = new GLatLng( lat,lon, true );
	trackpoints[trackcount] = point;
	trackcount++;
    }

    function initPoints()
    {
	getMap().clearOverlays();                
//	var mapp = getMap();
	if ( points.length > 0 )
	{
		// Loop all points and markers. add markers to map and
		// find min/max values for x and y.
		for( var i = 0 ; i < markers.length ; i++ )
		{
			addMarkerToMap( markers[i] );
			// mapp.addOverlay( markers[i] );
		}
	}
    }

    function addMarkerToMap( marker )
    {
	var mapp = getMap();
	mapp.addOverlay( marker );
    }

    var panorama = null;
    var panoramaTempLatLon = null;
    var panoramaCurrentYaw = 0;

    function showStreetViewInDiv(divId, lat, lon, bearing) {
      var pos = new GLatLng(lat,lon);
      var myPov = {yaw:bearing,pitch:0};
      panoramaOptions = { latlng:pos, pov:myPov };
      panorama = new GStreetviewPanorama(document.getElementById(divId), panoramaOptions);
      GEvent.addListener(panorama, "error", handleNoFlash);
      GEvent.addListener(panorama, "initialized", handleInitialized); 
      GEvent.addListener(panorama, "yawchanged", handleYawChange);
    }

    function handleYawChange(yaw){
                panoramaCurrentYaw = Math.round(yaw);
		setElementValue("currentYaw" , panoramaCurrentYaw );

		if ( (360-22.5) < panoramaCurrentYaw || panoramaCurrentYaw < (45-22.5) ){
			setElementValue("currentYawText" , "N" );
		} else if ( (45-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (90-22.5) ){
			setElementValue("currentYawText" , "NE" );
		} else if ( (90-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (135-22.5) ){
			setElementValue("currentYawText" , "E" );
		} else if ( (135-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (180-22.5) ){
			setElementValue("currentYawText" , "SE" );
		} else if ( (180-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (225-22.5) ){
			setElementValue("currentYawText" , "S" );
		} else if ( (225-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (270-22.5) ){
			setElementValue("currentYawText" , "SW" );
		} else if ( (270-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (315-22.5) ){
			setElementValue("currentYawText" , "W" );
		} else if ( (315-22.5) < panoramaCurrentYaw && panoramaCurrentYaw < (360-22.5) ){
			setElementValue("currentYawText" , "NW" );
		}
    }

    function handleInitialized(location) {
		panoramaTempLatLon = location.latlng;	
		setElementValue("currentLat" , panoramaTempLatLon.lat() );
		setElementValue("currentLon" , panoramaTempLatLon.lng() );
    }


    function getCurrentStreetViewLatLon(){
	if ( panoramaTempLatLon != null ) {
		var lat = panoramaTempLatLon.lat();
		var lon = panoramaTempLatLon.lng();
	}
    }

    function updateStreetViewLatLonToForm(){
	if ( panoramaTempLatLon != null ) {
		var lat = panoramaTempLatLon.lat();
		var lon = panoramaTempLatLon.lng();

                setFormValue("lat_degrees",lat);
                setFormValue("lon_degrees",lon);
                setFormValue("lat_minutes","");
                setFormValue("lat_seconds","");
                setFormValue("lon_minutes","");
                setFormValue("lon_seconds","");
                setFormValue("lat_kkj","");
                setFormValue("lon_kkj","");
	}
    }

    

    function handleNoFlash(errorCode) {
      if (errorCode == 600 ) {
	alert("No Panorama available.");
        return;
      } else if (errorCode == 603 ) {
        alert("Flash player not found. Panorama needs Flash player to work.");
        return;
      } 
    }  

    function showGoogleMap( map_name )
    {
      // if map element is not provided as parameter get the
      // default
      map = new GMap2( document.getElementById(map_name) );

	// Center to first point until we know any better ( google maps requires to be 
	// centered before overlays can be set.)
	var tmp;
	if ( points.length > 0 ) tmp = points[0];
	else if  ( trackpoints.length > 0 ) tmp = trackpoints[0];
	else{ tmp = new GLatLng( 62,24, true );}

     	map.setCenter( tmp , 6/*zoom*/, G_NORMAL_MAP /*G_HYBRID_MAP*/ );
	map.addMapType(G_SATELLITE_3D_MAP); // Add Google Earth plugin support

	map.addControl(new GSmallMapControl());
	map.addControl(new GMapTypeControl());


	var minX;
	var maxX;
	var minY;
	var maxY;

	if ( points.length > 0 )
	{
		minX = points[0].lng();
		maxX = points[0].lng();
		minY = points[0].lat();
		maxY = points[0].lat();
		// Loop all points and markers. add markers to map and
		// find min/max values for x and y.
		for( var i = 0 ; i < points.length ; i++ )
		{
			if ( points[i].lng() < minX ) minX = points[i].lng();
			if ( points[i].lng() > maxX ) maxX = points[i].lng();
			if ( points[i].lat() < minY ) minY = points[i].lat();
			if ( points[i].lat() > maxY ) maxY = points[i].lat();
			map.addOverlay( markers[i] );
		}
	}

	if ( trackpoints.length > 0 )
	{
		minX = trackpoints[0].lng();
		maxX = trackpoints[0].lng();
		minY = trackpoints[0].lat();
		maxY = trackpoints[0].lat();
		// Loop all trackpoints and find min/max values for x and y.
		for( var i = 0 ; i < trackpoints.length ; i++ )
		{
			if ( trackpoints[i].lng() < minX ) minX = trackpoints[i].lng();
			if ( trackpoints[i].lng() > maxX ) maxX = trackpoints[i].lng();
			if ( trackpoints[i].lat() < minY ) minY = trackpoints[i].lat();
			if ( trackpoints[i].lat() > maxY ) maxY = trackpoints[i].lat();
		}

		map.addOverlay( new GPolyline(trackpoints , "#ffffff" , 1 , 0.9 ) );

		// If track was available, then we register time out to center to track.
		// ( This starts the recentering process that follows through the whole track )
		window.setTimeout( centerToTrack , routeDelay);
	}


	if ( trackpoints.length > 0  ||  points.length > 0 )
	{

		// Calculate the deltaX and deltaY ( change in X axis between points that are most
		// a part )
		var deltaX = (maxX - minX)/2;
		var deltaY = (maxY - minY)/2;
		// Center to middle of waypoints
		map.setCenter( new GLatLng( minY + deltaY , minX + deltaX ) , 13/*zoom*/, G_NORMAL_MAP /*G_HYBRID_MAP*/ );

		// Set the zoom level so we can see all waypoints
		var bounds = map.getBounds();

		var safeCounter = 0;
		while ( bounds.getSouthWest().lng() > minX || bounds.getNorthEast().lng() < maxX ||
			bounds.getSouthWest().lat() > minY || bounds.getNorthEast().lat() < maxY )
		{
			// zoom out one step
			map.zoomOut();
			// get new bounds
			bounds = map.getBounds();
			safeCounter++;
			if ( safeCounter > 15 ) break;
		}
	} // End of auto zoom block
   }
