javascript - 无法使用 Google 距离矩阵读取未定义的属性 'text'

标签 javascript jquery html google-api

下面的代码计算用户给出的两个地址之间的距离。

当用户像这样提交表单时,它就会起作用:

$("#distance_form").submit(function (e) {
  e.preventDefault();
  calculateDistance();
});

但是,我希望代码能够在不提交表单的情况下运行,因此我使用了以下代码:

  function executeCalculation(){
    calculateDistance();
  }
    // Get all input fields.
  var inputs = document.querySelectorAll('.form-control');

  function checkInputs() {
    var allFilled = true;

    // If any of the inputs is not filled, we won't show the alert.
    for (var i = 0; i < inputs.length; i++) {
      if (inputs[i].value === '') {
        allFilled = false;
      }
    }

    // If all input fields have been filled.
    if (allFilled) {
      executeCalculation();
    }
  }

  // Check all inputs after losing focus on any input.
  for (var i = 0; i < inputs.length; i++) {
    inputs[i].addEventListener('focusout', checkInputs, );
  }

我不明白为什么当我使用上面的代码执行 calculateDistance() 函数时,它会显示:

enter image description here enter image description here

我正在以不同的方式执行相同的功能。

我做错了什么?

$(function () {
  // add input listeners
  google.maps.event.addDomListener(window, "load", function () {
    var from_places = new google.maps.places.Autocomplete(
      document.getElementById("from_places")
    );
    var to_places = new google.maps.places.Autocomplete(
      document.getElementById("to_places")
    );
    google.maps.event.addListener(from_places, "place_changed", function () {
      var from_place = from_places.getPlace();
      var from_address = from_place.formatted_address;
      $("#origin").val(from_address);
    });
    google.maps.event.addListener(to_places, "place_changed", function () {
      var to_place = to_places.getPlace();
      var to_address = to_place.formatted_address;
      $("#destination").val(to_address);
    });
  });
  // calculate distance
  function calculateDistance() {
    var origin = $("#origin").val();
    var destination = $("#destination").val();
    var service = new google.maps.DistanceMatrixService();
    service.getDistanceMatrix(
      {
        origins: [origin],
        destinations: [destination],
        travelMode: google.maps.TravelMode.DRIVING,
        unitSystem: google.maps.UnitSystem.IMPERIAL, // miles and feet.
        // unitSystem: google.maps.UnitSystem.metric, // kilometers and meters.
        avoidHighways: false,
        avoidTolls: false
      },
      callback
    );
  }
  // get distance results
  function callback(response, status) {
    if (status != google.maps.DistanceMatrixStatus.OK) {
      $("#result").html(err);
    } else {
      var origin = response.originAddresses[0];
      var destination = response.destinationAddresses[0];
      if (response.rows[0].elements[0].status === "ZERO_RESULTS") {
        $("#result").html(
          "Better get on a plane. There are no roads between " +
          origin +
          " and " +
          destination
        );
      } else {
        var distance = response.rows[0].elements[0].distance;
        var duration = response.rows[0].elements[0].duration;

        console.log(distance, duration);
        var distance_in_kilo = distance.value / 1000; // the kilom
        var distance_in_mile = distance.value / 1609.34; // the mile
        var duration_text = duration.text;
        var duration_value = duration.value;
        $("#in_mile").text(distance_in_mile.toFixed(2));
        $("#in_kilo").text(distance_in_kilo.toFixed(2));
        $("#duration_text").text(duration_text);
        $("#duration_value").text(duration_value);
        $("#from").text(origin);
        $("#to").text(destination);
      }
    }
  }
  // print results on submit the form
  function executeCalculation(){
    calculateDistance();
  }
    // Get all input fields.
  var inputs = document.querySelectorAll('.form-control');

  function checkInputs() {
    var allFilled = true;

    // If any of the inputs is not filled, we won't show the alert.
    for (var i = 0; i < inputs.length; i++) {
      if (inputs[i].value === '') {
        allFilled = false;
      }
    }

    // If all input fields have been filled.
    if (allFilled) {
      executeCalculation();
    }
  }

  // Check all inputs after losing focus on any input.
  for (var i = 0; i < inputs.length; i++) {
    inputs[i].addEventListener('focusout', checkInputs, );
  }
});
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <link rel="stylesheet" href="style.css" />
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
    crossorigin="anonymous" />

<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
  crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
    crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
    crossorigin="anonymous"></script>
</head>

<body>

<form id="distance_form">
  <div class="form-group"><label>Origin: </label> <input class="form-control" id="from_places" placeholder="Enter a location" />
    <input id="origin" name="origin" required="" type="hidden" /></div>

  <div class="form-group"><label>Destination: </label> <input class="form-control" id="to_places" placeholder="Enter a location" />
    <input id="destination" name="destination" required="" type="hidden" /></div>
  <input class="btn btn-primary" type="submit" value="Calculate" id="cal" />
</form>

<div id="result">
  <ul class="list-group">
    <li class="list-group-item d-flex justify-content-between align-items-center" id="in_mile">Distance In Mile
      :</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="in_kilo">Distance is
      Kilo:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="duration_text">IN TEXT:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="duration_value">IN
      MINUTES:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="from">FROM:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="to">TO:</li>
  </ul>
</div>

    
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAsuza67QeCTz8WQg9BJYGgMyiz0f8IT2M&libraries=places&language=en"></script>
</body>

</html>

出于显而易见的原因,一旦我弄清楚了这一点,API key 就会被删除。

最佳答案

您在接收到输入上的 focusout DOM 事件后调用 checkInputs,这还为时过早。本地理定位 API 完成将值解析为实际地址时,应该调用它。

事实上,您已经监听了 place_changed API 事件,因此从那里调用 checkInputs 应该可以完成这项工作:

$(function () {
  // add input listeners
  google.maps.event.addDomListener(window, "load", function () {
    var from_places = new google.maps.places.Autocomplete(
      document.getElementById("from_places")
    );
    var to_places = new google.maps.places.Autocomplete(
      document.getElementById("to_places")
    );
    google.maps.event.addListener(from_places, "place_changed", function () {
      var from_place = from_places.getPlace();
      var from_address = from_place.formatted_address;
      $("#origin").val(from_address);
      checkInputs();
    });
    google.maps.event.addListener(to_places, "place_changed", function () {
      var to_place = to_places.getPlace();
      var to_address = to_place.formatted_address;
      $("#destination").val(to_address);
      checkInputs();
    });
  });
  // calculate distance
  function calculateDistance() {
    var origin = $("#origin").val();
    var destination = $("#destination").val();
    var service = new google.maps.DistanceMatrixService();
    service.getDistanceMatrix(
      {
        origins: [origin],
        destinations: [destination],
        travelMode: google.maps.TravelMode.DRIVING,
        unitSystem: google.maps.UnitSystem.IMPERIAL, // miles and feet.
        // unitSystem: google.maps.UnitSystem.metric, // kilometers and meters.
        avoidHighways: false,
        avoidTolls: false
      },
      callback
    );
  }
  // get distance results
  function callback(response, status) {
    if (status != google.maps.DistanceMatrixStatus.OK) {
      $("#result").html(err);
    } else {
      var origin = response.originAddresses[0];
      var destination = response.destinationAddresses[0];
      if (response.rows[0].elements[0].status === "ZERO_RESULTS") {
        $("#result").html(
          "Better get on a plane. There are no roads between " +
          origin +
          " and " +
          destination
        );
      } else {
        var distance = response.rows[0].elements[0].distance;
        var duration = response.rows[0].elements[0].duration;

        var distance_in_kilo = distance.value / 1000; // the kilom
        var distance_in_mile = distance.value / 1609.34; // the mile
        var duration_text = duration.text;
        var duration_value = duration.value;
        $("#in_mile").text(distance_in_mile.toFixed(2));
        $("#in_kilo").text(distance_in_kilo.toFixed(2));
        $("#duration_text").text(duration_text);
        $("#duration_value").text(duration_value);
        $("#from").text(origin);
        $("#to").text(destination);
      }
    }
  }
  // print results on submit the form
  function executeCalculation(){
    calculateDistance();
  }
    // Get all input fields.
  var inputs = document.querySelectorAll('.form-control');

  function checkInputs() {
    var allFilled = true;

    // If any of the inputs is not filled, we won't show the alert.
    for (var i = 0; i < inputs.length; i++) {
      if (inputs[i].value === '') {
        allFilled = false;
      }
    }

    // If all input fields have been filled.
    if (allFilled) {
      executeCalculation();
    }
  }
});
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <link rel="stylesheet" href="style.css" />
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS"
    crossorigin="anonymous" />

<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
  crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
    crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
    crossorigin="anonymous"></script>
</head>

<body>

<form id="distance_form">
  <div class="form-group"><label>Origin: </label> <input class="form-control" id="from_places" placeholder="Enter a location" />
    <input id="origin" name="origin" required="" type="hidden" /></div>

  <div class="form-group"><label>Destination: </label> <input class="form-control" id="to_places" placeholder="Enter a location" />
    <input id="destination" name="destination" required="" type="hidden" /></div>
  <input class="btn btn-primary" type="submit" value="Calculate" id="cal" />
</form>

<div id="result">
  <ul class="list-group">
    <li class="list-group-item d-flex justify-content-between align-items-center" id="in_mile">Distance In Mile
      :</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="in_kilo">Distance is
      Kilo:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="duration_text">IN TEXT:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="duration_value">IN
      MINUTES:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="from">FROM:</li>
    <li class="list-group-item d-flex justify-content-between align-items-center" id="to">TO:</li>
  </ul>
</div>

    
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAsuza67QeCTz8WQg9BJYGgMyiz0f8IT2M&libraries=places&language=en"></script>
</body>

</html>

关于javascript - 无法使用 Google 距离矩阵读取未定义的属性 'text',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54271983/

相关文章:

html - 根据条件设置 div 标签高度

javascript - 在 karma 环境中的 Blob 中使用 importsScripts

Javascript:通过 animation.width() 倒计时

javascript - 正则表达式获取两个字符串之间的所有字符串

javascript - 如何在我的 DataTable 上方添加额外的输入?

html - CSS-删除 hr 标签空间不起作用

javascript - 如果我有一串 HTML 代码,如何使用 JQuery 来解析它?

javascript - jquery添加的内容在提交后被清除

javascript - 将一组没有标记且随机 <br> 的段落包装在 p 标签中

php - 将 jQuery 数组发送到 PHP 帖子?