为什么这个脚本在状态表列中放置了undefined?

时间:2016-05-13 19:38:53

标签: javascript html google-maps

 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>

脚本将提示用户按地址,城市,州,邮编和目的地输入起始位置。路线显示在地图上,脚本计算用户驾驶的每个州的里程数。然后将其放入一个表中,其中一列显示状态名称缩写,第二列显示该状态的距离。如果驾驶员从KY到TN,则计算每个州驾驶的里程数。我遇到的问题是,如果用户&#39;起始状态和目标状态是相同的,在表的状态列中它将显示未定义。里程计算得很好。是否有任何类型的工作可以使undefined成为起始状态或以前的状态?

2 个答案:

答案 0 :(得分:1)

您正在使用重复的ID。你永远不应该那样做。

您将内容附加到.state和.mile元素,这些元素看起来不存在。

编辑: 它正在使用css选择器。

如果您执行$(".foo").append("bar");,则将“bar”附加到class foo的元素。 如果您执行$("#foo").append("bar");,则将“bar”附加到id foo的元素。

在您的情况下,内容会附加到.state0.state1等(在i循环中使用变量for)。 因此,您可能需要使用<td class="state0"> <td class="state1">

在这种情况下,您可以使用<td id="state0"> <td id="state1">,因为它们是唯一ID,但您需要调整脚本。

答案 1 :(得分:0)

如果你问题中的代码来自相关问题:Google maps api v3 calculate mileage by state(它看起来像,但我没有做完整的比较)。

它在该问题的答案中特别指出(强调我的):

  

另一个注释:有一些国家边界穿过水体。 Google认为这些不在任何州,并且因此报告未定义为州名。

如果路线没有过渡状态,请使用路线服务返回的完整路线的距离。