-1
 Below is the HTML and the JS. The script will prompt the user to enter a starting location by address,city,state,zip, and the same for the destination. the route shows on the map and the script calculates the mileage for each state the user drives in. Then puts it into a table with one column showing the State name Abbreviated, and the second column shows the distance for that state. If the driver goes from KY to TN the mileage is calculated for the number of miles driven in each state. The problem I am having is that if the users' starting state and destination state are the same, in the state column of the table it will display undefined. the miles calculate perfectly. Is there any kind of work around that would allow the undefined to be the starting state, or previous state?   

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="generator" content="CoffeeCup HTML Editor (www.coffeecup.com)">
    <meta name="dcterms.created" content="Tue, 03 May 2016 17:18:33 GMT">
    <meta name="description" content="">
    <meta name="keywords" content="">
    <title></title>

    <!--[if IE]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR KEY &callback=initMap"></script>
<body>
<div id="map" style="height:400px"></div>
<div id="status"></div> 
<div id="results"></div>
<div id="table"></div>


<div style=" text-align: left; text-indent: 0px; padding: 0px 0px 0px 0px; margin: 0px 0px 0px 0px;">
<table>
   <table width="40%" border="1" cellpadding="2" cellspacing="2" style="border-color: #000000; border-style: solid; background-color: #ffffff;">
      <tr valign="top">
         <td  style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="state1"><br />
         </td>
         <td style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="mile1"><br />
         </td>
         <tr valign="top">
         <td style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="state2"><br />
         </td>
         <td style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="mile2"><br />
         </td>
         <tr valign="top">
         <td style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="state3"><br />
         </td>
         <td style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="mile3"><br />
         </td>

         <tr valign="top">
         <td  style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="state4"><br />
         </td>
         <td style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="mile4"><br />
         </td>
         <tr valign="top">
         <td  style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="state5"><br />
         </td>
         <td  style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="mile5"><br />
         </td>
         <tr valign="top">
         <td  style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="state6"><br />
         </td>
         <td  style="border-color : #000000 #000000 #000000 #000000; border-style: solid;" class="mile6"><br />
         </td>




     </tr>

 </table>
</div>

</div>





<script>

var directionsRequest = {
  origin: "New York, NY", //default
  destination: "Los Angeles, LA", //default
  optimizeWaypoints: true,
  provideRouteAlternatives: false,
  travelMode: google.maps.TravelMode.DRIVING,
  drivingOptions: {
    departureTime: new Date(),
    trafficModel: google.maps.TrafficModel.PESSIMISTIC
  }
};

directionsRequest.origin = prompt("Enter your starting address");
directionsRequest.destination = prompt("Enter your destination address");

var starttime = new Date();

var geocoder  = new google.maps.Geocoder();
var startState;
var currentState;
var routeData;
var index = 0;
var stateChangeSteps = [];
var borderLatLngs = {};
var startLatLng;
var endLatLng;

directionsService = new google.maps.DirectionsService();
directionsService.route(directionsRequest, init);

function init(data){
    routeData = data;
    displayRoute();
    startLatLng = data.routes[0].legs[0].start_location;
    endLatLng = data.routes[0].legs[0].end_location;
    geocoder.geocode({location:data.routes[0].legs[0].start_location}, assignInitialState)

}

function assignInitialState(data){
    startState = getState(data);
    currentState = startState;
    compileStates(routeData);
}

function getState(data){
    for (var i = 0; i < data.length; i++) {
        if (data[i].types[0] === "administrative_area_level_1") {
            var state = data[i].address_components[0].short_name;
        }
    }
    return state;
}

function compileStates(data, this_index){
    if(typeof(this_index) == "undefined"){
        index = 1;
        geocoder.geocode({location:data.routes[0].legs[0].steps[0].start_location}, compileStatesReceiver);
    }else 
    {
        if(index >= data.routes[0].legs[0].steps.length){
            console.log(stateChangeSteps);
            index = 0;
            startBinarySearch();
            return;
        }
        setTimeout(function(){ 
                geocoder.geocode({location:data.routes[0].legs[0].steps[index].start_location}, compileStatesReceiver);
                $("#status").html("Indexing Step "+index+"...  "+data.routes[0].legs[0].steps.length+" Steps Total");
            }, 3000)
    }

}

function compileStatesReceiver(response){
      state = getState(response);
      console.log(state);
      if(state != currentState){
            currentState = state;
            stateChangeSteps.push(index-1);
      }
      index++; 
      compileStates(routeData, index);

    }



var stepIndex = 0;
var stepStates = [];
var binaryCurrentState = "";
var stepNextState;
var stepEndState;
var step;

var myLatLng = {lat:39.8282, lng:-98.5795};
var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: myLatLng
  });

function displayRoute() {
  directionsDisplay = new google.maps.DirectionsRenderer();
  directionsDisplay.setMap(map);
  directionsDisplay.setDirections(routeData);
}

var orderedLatLngs = [];
function startBinarySearch(iterating){
    if(stepIndex >= stateChangeSteps.length){
        for(step in borderLatLngs){
            for(state in borderLatLngs[step]){
                for(statename in borderLatLngs[step][state]){
                    (JSON.stringify(borderLatLngs[step][state][statename],null, 4));
                   orderedLatLngs.push([borderLatLngs[step][state][statename], statename]); 
                }
            }
        }
        compileMiles(true);
        return;
//$("#results").append("<br>Cross into "+statename+" at "+

    }
    step = routeData.routes[0].legs[0].steps[stateChangeSteps[stepIndex]];
    console.log("Looking at step "+stateChangeSteps[stepIndex]);
    borderLatLngs[stepIndex] = {};
    if(!iterating){
        binaryCurrentState = startState;
    }
    geocoder.geocode({location:step.end_location}, 
        function(data){
            if(data === null){
                setTimeout(function(){startBinarySearch(true);}, 6000);
            }else{
                stepNextState = getState(data);
                stepEndState = stepNextState;
                binaryStage2(true);
            }
        });
}

var minIndex;
var maxIndex;
var currentIndex;
function binaryStage2(init){
    if (typeof(init) != "undefined"){   

        minIndex = 0;
        maxIndex  = step.path.length - 1;    
    }
    if((maxIndex-minIndex)<2){
        borderLatLngs[stepIndex][maxIndex]={};
        borderLatLngs[stepIndex][maxIndex][stepNextState]=step.path[maxIndex];
        var marker = new google.maps.Marker({
            position: borderLatLngs[stepIndex][maxIndex][stepNextState],
            map: map,
        });
        if(stepNextState != stepEndState){
            minIndex = maxIndex;
            maxIndex = step.path.length - 1;
            binaryCurrentState = stepNextState;
            stepNextState = stepEndState;

        }else{
            stepIndex++;
            binaryCurrentState = stepNextState;
            startBinarySearch(true);
            return;
        }
    }
    console.log("Index starts: "+minIndex+" "+maxIndex);
    console.log("current state is "+binaryCurrentState);
    console.log("next state is "+ stepNextState);
    console.log("end state is "+ stepEndState);

    currentIndex = Math.floor((minIndex+maxIndex)/2);
    setTimeout(function(){
                geocoder.geocode({location:step.path[currentIndex]}, binaryStage2Reciever);
                $("#status").html("Searching for division between "+binaryCurrentState+" and "+stepNextState+" between indexes "+minIndex+" and "+maxIndex+"...") 
            }, 3000);


}

function binaryStage2Reciever(response){
    if(response === null){
        setTimeout(binaryStage2, 6000);
    }else{
        state = getState(response)
        if(state == binaryCurrentState){
            minIndex = currentIndex +1; 
        }else{
            maxIndex = currentIndex - 1
            if(state != stepNextState){
                stepNextState = state;
            }
        }
        binaryStage2();
    }
}

var currentStartPoint;
var compileMilesIndex = 0;
var stateMiles = {};
var trueState;
function compileMiles(init){
        if(typeof(init)!= "undefined"){
            currentStartPoint = startLatLng;
            trueState = startState;    
        }
        if(compileMilesIndex == orderedLatLngs.length){
            directionsRequest.destination = endLatLng;
        }else{
            directionsRequest.destination = orderedLatLngs[compileMilesIndex][0];
        }
        directionsRequest.origin = currentStartPoint;
        currentStartPoint = directionsRequest.destination;
        directionsService.route(directionsRequest, compileMilesReciever)


}



function compileMilesReciever(data){
    if(data===null){
        setTimeout(compileMiles, 6000);
    }else{


        if(compileMilesIndex == orderedLatLngs.length){
            stateMiles[stepEndState]=data.routes[0].legs[0].distance["text"];


var txt = "";
var i = 0;
for(state in stateMiles)
{
   i++;
   $("#results").append            

   $(".state"+i).append(state);
   $(".mile"+i).append(stateMiles[state]);


} 




                      var endtime = new Date();
            totaltime = endtime - starttime;
            //$("#results").append("<br><br>Operation took "+Math.floor(totaltime/60000)+" minute(s) and "+(totaltime%60000)/1000+" second(s) to run.");
            return;
        }else{
            stateMiles[trueState]=data.routes[0].legs[0].distance["text"];
        }
        trueState = orderedLatLngs[compileMilesIndex][1];
        compileMilesIndex++;
        setTimeout(compileMiles, 3000);
    }

}










</script>



<script>

</script>




</script>





</head>

</script>



  </body>
</html>

The script will prompt the user to enter a starting location by address,city,state,zip, and the same for the destination. the route shows on the map and the script calculates the mileage for each state the user drives in. Then puts it into a table with one column showing the State name Abbreviated, and the second column shows the distance for that state. If the driver goes from KY to TN the mileage is calculated for the number of miles driven in each state. The problem I am having is that if the users' starting state and destination state are the same, in the state column of the table it will display undefined. the miles calculate perfectly. Is there any kind of work around that would allow the undefined to be the starting state, or previous state?

Bryan Hughes
  • 23
  • 1
  • 8
  • It would be helpful if you indicated where your code came from. – geocodezip May 13 '16 at 19:55
  • The code came from your post in the question Google maps api 3 calculate mileage by state. Your code is beautifully written. The problem that I'm having is not regarding the issues of crossing state borders that run through bodies of water, I understand that. But if I put in 2 locations within the same state i.e start point Lexington,ky and end point louisville,ky I get undefined where it should say KY. the mileage calculates perfectly. – Bryan Hughes May 13 '16 at 20:13
  • That isn't my code/post. The posted code/HTML does not work as posted. Please provide a [Minimal, Complete, Tested and Readable example](http://stackoverflow.com/help/mcve) that demonstrates the issue. The simplest fix is If the route doesn't transition states, use the distance of the complete route returned by the directions service. – geocodezip May 13 '16 at 20:25

2 Answers2

1

You are using duplicate ID's. You should never ever ever do that.

You're appending content to .state and .mile element which looks like do not exist.

EDIT: It's using css selectors.

If you do $(".foo").append("bar"); then you append "bar" to an element with class foo. If you do $("#foo").append("bar"); then you append "bar" to an element with id foo.

In your case content is appended to .state0, .state1 etc (using variable i inside a for loop). So you probably need to use <td class="state0"> <td class="state1">

In that case you can use <td id="state0"> <td id="state1"> as they are unique id's, but you need to adjust your script.

yezzz
  • 2,990
  • 1
  • 10
  • 19
  • can you explain or give me an example? , I'm trying to learn JS. – Bryan Hughes May 13 '16 at 20:20
  • added some info, but be aware stackoverflow is not a code writing service. Learn step by step, not by copying a large chunk of code and then try to fix it – yezzz May 13 '16 at 21:03
0

If the code in your question came from the related question: Google maps api v3 calculate mileage by state (which it looks like, but I didn't do a full compare).

It specifically states in the answer to that question (emphasis mine):

One other note: There are a few state borders that run through bodies of water. Google considers these to be not located in any state, and so reports undefined as the state name.

If the route doesn't transition states, use the distance of the complete route returned by the directions service.

Community
  • 1
  • 1
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • I'm very new to JS, but trying my best to learn it. Can you give me an example and maybe explain how that works, so I can better understand it? – Bryan Hughes May 13 '16 at 20:37
  • I have supplied the full working example. Would I use an IF statement to clarify start and end state are the same, with a variable like sameState? – Bryan Hughes May 14 '16 at 14:52