【问题标题】:Grab the value of a span element获取 span 元素的值
【发布时间】:2020-12-08 17:11:56
【问题描述】:

我最初提到 Get value of Span Text 是因为我试图获取 span 元素的文本值:

我尝试了文章中提到的内容,但除非我再次触发该操作,否则我所拥有的值将变为空白。这是我的代码:

let startInput, destInput, distance, facId, time, resultsObject;
let facilityArray = [];
let distanceArray = [];
let timeArray = [];
let sortArray = [];
let tempArray = [];
let slicedArray = [];
let inputVal = [];

// Set headers
const headers = {
  'QB-Realm-Hostname': 'xxxxxx.quickbase.com',
  'Authorization': 'QB-USER-TOKEN xxxxxxxxxxxxxxxxxxxxxxxx',
  'Content-Type': 'application/json'
}

// Call QB table and pull data from column facID 6, address 8
const body = {
  "from": "xxxxxxxx",
  "select": [6, 8],
  "options": {
    "skip": 0,
    "top": 0
  }
}

const generateHTML = () => {
  // Create xml request class
  const xmlHttp = new XMLHttpRequest();
  xmlHttp.open('POST', 'https://api.quickbase.com/v1/records/query', true);
  // Extract keys from headers
  for (const key in headers) {
    // Grab keys and values from the headers object
    xmlHttp.setRequestHeader(key, headers[key]);
  }
  xmlHttp.onreadystatechange = () => {
    if (xmlHttp.readyState === XMLHttpRequest.DONE) {
      const jsonObject = JSON.parse(xmlHttp.responseText);
      facId = jsonObject.data.map(e => e["6"].value);
      const addresses = jsonObject.data.map(e => e["8"].value);

      // Grab container div entry point in html
      let container = document.querySelector(".container-sm")

      // Create html elements dynamically based on length of addresses array
      for (let i = 0; i < addresses.length; i++) {
        let div = document.createElement("div");
        div.classList.add("d-inline-flex", "p-2", "mb-1");
        div.innerHTML =
          `<div class="container">
                        <div class="card" style="width: 20rem; height: fixed;">
                            <div class="card-body">
                                <input class="form-control" hidden readonly type="text" placeholder="Start Address" id="startaddress${i}">
                                <input class="form-control" hidden value="${inputVal.join('')}" type="text" placeholder="Destination Address" id="destaddress${i}">
                                <h6 class="card-title">Service Center - ${facId[i]}</h6>
                                <h6 class="card-title">Distance - <span id="distance${i}"></span></h6>
                                <h6 class="card-title">Drive Time - <span id="time${i}"></span></h6>
                            </div>
                        </div>
                    </div>`;

        container.appendChild(div);
        // Dynamically set input fields
        startInput = document.querySelector(`#startaddress${[i]}`);
        startInput.value = addresses[i];
        destInput = document.querySelector(`#destaddress${[i]}`).innerText;
        distance = document.querySelector(`#distance${i}`).innerText;
        time = document.querySelector(`#time${i}`).innerText;

        // Push return values to each array
        facilityArray.push(startInput.value);
        distanceArray.push(distance);
        timeArray.push(time);

        const getDistance = () => {

          // Create Google Maps distance service class
          const distanceService = new google.maps.DistanceMatrixService();
          // Add matrix settings
          distanceService.getDistanceMatrix({
              origins: [document.getElementById(`startaddress${[i]}`).value],
              destinations: [document.getElementById(`destaddress${[i]}`).value],
              travelMode: "DRIVING",
              unitSystem: google.maps.UnitSystem.IMPERIAL,
              durationInTraffic: true,
              avoidHighways: false,
              avoidTolls: false
            },

            // Set response and error capture
            (response, status) => {
              if (status !== google.maps.DistanceMatrixStatus.OK) {
                console.log('Error:', status);
                const message = document.querySelector("#message");
                message.innerHTML = `Error: ${status}. Please resubmit.`;
              } else {
                distanceResult = document.getElementById(`distance${[i]}`).innerHTML = `${response.rows[0].elements[0].distance.text}`;
                timeResult = document.getElementById(`time${[i]}`).innerHTML = `${response.rows[0].elements[0].duration.text}`;
                // Convert distanceResult to an integer and push to distanceArray
                intDistanceResult = parseInt(distanceResult.replace(/,/g, ''));
                // Push values to the sort array
                sortArray.push(intDistanceResult);
                sortArray.sort((a, b) => a - b);
              }
            });
        }
        getDistance();
      }
      // This is giving me the top three values, I need to find a way to return this in the html above
      slicedArray = (sortArray.slice(0, 3));
      console.log(slicedArray);
    }
  };
  // Send body request object to Quick Base via RESTful API
  quickBaseQuery = () => {
    xmlHttp.send(JSON.stringify(body));
  }
  // Combine search results from arrays into a new object
  resultsObject = Object.assign({}, [facilityArray, distanceArray, timeArray]);
  console.log(resultsObject);
}


form.addEventListener("submit", (e) => {
  e.preventDefault();
  const patientAddressInput = document.querySelector("#patientaddress");
  inputVal.push(patientAddressInput.value);
  // Call The generateHTML function only after the user enters a value
  generateHTML();
  quickBaseQuery();
  // let disableButton = document.querySelector("#submit");
  // submit.disabled = true;
  let resetButton = document.querySelector("#refresh");
  resetButton.addEventListener("click", () => location.reload());
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">

<body>
  <div class="container-sm mt-3">
    <form class="form mb-3" id="form">
      <div class="card">
        <div class="card-body">
          <div class="input-group">
            <div class="input-group-prepend">
              <span class="input-group-text">Patient Destination</span>
            </div>
            <input class="form-control" type="text" placeholder="Enter Zip Code" class="patientaddress" id="patientaddress" required>
            <div class="input-group-prepend">
              <span class="input-group-text" id="message"></span>
            </div>
          </div>
          <hr>
          <button class="btn btn-primary mt-2" type="submit" id="submit">Submit</button>
          <button class="btn btn-outline-success mt-2 ml-3" type="reset" value="Reset" id="refresh">Clear Destination</button>
        </div>
      </div>
    </form>
  </div>
  <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&key=[API_KEY]"></script>
  <script type="text/javascript" src="main.js"></script>
</body>

我在设施对象中填充了设施、距离和时间数组,但只有设施数据在第一次提交表单时传入。我创建了一个resultsObject,我正在传递facilityArraydistanceArraytimeArray 的值。在第一次提交时,我拥有所有 15 个地址值,因为我的

quickBaseQuery = () => {
    xmlHttp.send(JSON.stringify(body));
}

函数正在发送 http 请求标头,因此所有数据都会在表单提交后立即进入。似乎这一切都是同时触发的(设施、时间和距离被填充),但显然不是。我想同时返回标头结果以及距离和时间,以便返回仅在一定范围内的距离结果。

这是我的控制台日志:

您将看到对象内部(在控制台中)array[0] 中的设施值在第一次提交时返回,但距离和时间的前 15 个结果为空,直到第二次提交制成。所以现在我有一个对象,其 array[0] 有 30 个地址,其中 15 个重复,array[1] 有 15 个空距离和 15 个填充距离,然后 array[2] 有 15 个空驱动时间和 15 个填充驱动时间。如何让每个数组的所有 15 个结果同时返回?我最终想要对结果进行排序,以便返回我的 html 中最近的 3 个位置,而不是全部 15 个结果。

【问题讨论】:

  • 你的 HTML 在哪里?
  • sn-p 会有所帮助
  • 我的错。刚刚添加了 HTML。
  • 要么创建一个重现您的确切问题的 sn-p,要么只共享相关代码。要创建一个 sn-p,请单击编辑,然后单击 &lt;&gt; 按钮,并在那里添加您的代码。这个 sn-p 应该会重现您的问题。
  • 这听起来像是一个异步问题。查看您的代码 - xmlHttp 请求 API 有点过时 - fetch api 总体上更容易使用,并且执行 await/async 的语法更容易。如果它正在抓取空白,是它在它有一个值之前抓取了字段的值......这可能发生在 eventListener 调用周围,然后在等待响应之前继续......虽然代码笔给了我错误您的代码 - 说“Google Maps JavaScript API 错误:InvalidKeyMapError”所以我无法直接测试。

标签: javascript html


【解决方案1】:

你的

resultsObject = Object.assign({}, [facilityArray, distanceArray, timeArray]);
console.log(resultsObject);

实际上在之前触发

xmlHttp.onreadystatechange

即使它位于较低的位置。

这就是第二次出现这些值的原因。您的 Object.assign 基本上分配了空数组,然后您的 onreadystatechange 触发。

您需要将Object.assign 移动到onreadystatechange,使用Promiseasync / awaitfetch API,因为您支持的浏览器基本相同。

【讨论】:

  • 谢谢,ColdHands。我不得不重写其中一些并弄清楚如何实现 fetch 和 async/await,但它按预期工作。
  • @Ang 我很高兴我能帮上忙。
猜你喜欢
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 2020-08-02
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
相关资源
最近更新 更多