   /**
    * Submit the driving directions request
    * The load event handler calls jumpInMyCar() when this returns
    */ 
    function generateRoute() {

      directions.load("from: " + from + " to: " + to, { preserveViewport: true, getSteps: true });
    }
 
   /**
    * GDirections object used to submit driving direction requests.
    */
    var directions;

   /**
    * The GRoute we are following extracted from the directions response.
    */
    var route;

   /**
    * It turns out that the polyline generated for a driving directions
    * route normally has a lot of repeated vertices. This causes problems
    * when trying to determine how close we are to the next vertex, so it's
    * better to collapse these duplicated vertices out.
    *
    * The array of route vertices with duplicates removed.
    */
    var vertices;

   /**
    * Array that maps the polyline vertex indices to the
    * index of the same point in the vertices array.
    *
    * For example, if the polyline vertices are
    * [a, a, b, c, d, d, e], the vertices array will be
    * [ a, b, c, d, e ] and the vertexMap array will be
    * [ 1, 1, 2, 3, 4, 4, 5 ].
    */
    var vertexMap;

   /**
    * Array that contains the index in the vertices array of
    * the point at the start of the n'th step in the route
    */
    var stepToVertex;

   /**
    * An array that gives the route step number that each
    * point in the vertices array is part of.
    */
    var stepMap;

   /**
    * The current position of the panorama and vehicle marker.
    */
    var currentLatLng;

   /**
    * Metadata for the current panorama including the list of
    * available links, loaded using GStreetviewClient.
    */
    var panoMetaData;

   /**
    * boolean flag set when we are so close to the next vertex that we should
    * check links in the panoramas we load for the next turning we need.
    */
    var close = false;

   /**
    * The direction in degrees from our current location to the next
    * vertex on the route. Used to select the most suitable link to follow.
    */
    var bearing;

   /**
    * The direction from the next vertex on the route to the vertex
    * after that. Used when we are close to a vertex and are looking
    * for links that represent the next turn we need to make.
    */
    var nextBearing;

   /**
    * The index of the vertex we are heading towards on the route in the
    * vertices array.
    */
    var nextVertexId;

   /**
    * GLatLng of the vertex we are heading towards on the route.
    */
    var nextVertex;

   /**
    * An array that at any time contains the GLatLng of each vertex
    * from the start of the current route step to the next vertex
    * ahead of our current position. This is used to work out how
    * far we are along the current step.
    */
    var progressArray;

   /**
    * The distance in meters covered by traversing the points in the
    * progressArray. By subtracting the distance from our current location
    * to the next vertex from this value we find how far along the step
    * we are, and use this to update the progress bar.
    */
    var progressDistance;

   /**
    * Index of the route step we are currently on.
    */
    var currentStep;

   /**
    * The marker on our map that shows the current location. For IE6 this
    * is a standard red maps pushpin. For all other browsers it is a
    * directional arrow.
    */
    var carMarker;

   /**
    * A copy of the current step index used to unhighlight the previously
    * highlighted step in the textual driving directions when the
    * current step changes.
    */
    var selectedStep = null;

   /**
    * boolean flag indicating whether we are currently driving (automatically
    * following) links, or are stationary.
    */
    var driving = false;

  /**
   * Id of the timer that adds a delay between following each link to give the
   * panorama time to load. We need this to cancel the timer if the user clicks
   * Stop while we are waiting to follow the next link.
   */
    var advanceTimer = null;
    
  /**
   * Delay in seconds between following each link.
   */
    var advanceDelay = 1;
    

   /**
    * It's too far to walk on your own
    */ 
    function jumpInMyCar() {
	    
      /* Extract the one and only route from this response */
      route = directions.getRoute(0);

      /* Simplify the list of polyline vertices by removing duplicates */
      //collapseVertices(directions.getPolyline());

      /* Center the map on the start of the route at street level */
      //map.setCenter(vertices[0], 16);

      /* Display the textual driving directions */
      renderTextDirections();

      /* Begin checking the Street View coverage along this route */
      //checkCoverage(0);
    }


   /**
    * Because we want to be highlight text directions steps and make them clickable
    * we must render them ourselves rather than let GDirections do so as normal.
    */
    function renderTextDirections() {

      /* Get the addresses to display at the start and end of the directions */
      var startAddress = route.getStartGeocode().address;
      var   endAddress = route.getEndGeocode().address;

      /* Write the start address title, marker, and summary */
      var html  =  getDirectionsWaypointHtml(startAddress, "A");
          html +=  getDivHtml("summary", "", route.getSummaryHtml(),"");

      /* Build up the textual directions step by step */
      for (var n = 0; n < route.getNumSteps(); n++) {
        html += '<a onclick="selectStep(' + n + ')">';
        html += getDivHtml("step" + n, "dstep", route.getStep(n).getDescriptionHtml(),route.getStep(n).getDistance());
        html += '</a>';
      }

      /* Write the end address title and marker */
      html += getDirectionsWaypointHtml(endAddress, "B");

      /* Fill in the div on the page with the generated HTML */
      document.getElementById("directions").innerHTML = html;

      /* Set the icons used in the address blocks using the appropriate
       * technique for the browser to preserve PNG transparency */
      setWaypointIcon('A');
      setWaypointIcon('B');
      
    }

   /**
    * Generate the HTML of the header and footer of each set of textual directions
    * @param {String} address The address of this endpoint
    * @param {String} letter The letter to display in the marker
    *     (A at the start, B at the end)
    * @return {String} the generated HTML 
    */
    function getDirectionsWaypointHtml(address, letter) {
     var content = getDivHtml('letter' + letter, 'letterIcon', "","");
         content += '<span class="waypointAddress">' + address + '</span>';
      return getDivHtml("wayPoint" + letter, "waypoint", content,"");
    }

   /**
    * Set the icons used in the textual directions address blocks
    * using the appropriate technique for the browser to preserve
    * PNG transparency
    */
    function setWaypointIcon(letter) {
      var png = 'http://maps.google.com/intl/en_us/mapfiles/icon_green' + letter + '.png';
      /*@cc_on @*/
      /*@if (@_jscript_version < 5.7)
      document.getElementById('letter' + letter).style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + png + '", sizingMethod="scale");';
      return;
      /*@end @*/ 
      document.getElementById('letter' + letter).style.backgroundImage = 'url(' + png + ')';
    }

   /**
    * Utility function to wrap content in a div tags
    * @param {String} id The id attribute value for this div element
    * @param {String} cssClass The class attribute value for this div element
    * @param {String} content The HTML content to wrap in this div element
    * @return {String} the HTML of the generated div element 
    */
    function getDivHtml(id, cssClass, content,cus_dist) {
	    if (typeof(cus_dist.html) == 'undefined')
	        format_dist = '';
	    else
	        format_dist = ' ('+cus_dist.html+') ';
	    
      var div = "<div";
      if (id != "") {
        div += ' id="' + id + '"';
      }

      if (cssClass != "") {
        div += ' class="' + cssClass + '"';
      }

      div += '>' + content + format_dist + '</div>';
      return div;
    }

