skip to Main Content

I’m starting to learn ajax and could use some help. I’m pulling data through API and I am getting a response in the console but can’t figure out how to properly target the response so I can fill a table.

How do I target the scores in the JSON response so the scores are put beneath every category? The scores are dynamic.

Form:

<form class="pagespeed">
  <input type="text" id="url" placeholder="Enter webpage URL" />
  <input type="button" value="Analyse Webpage" onclick="loadAnalysis()" />

  <div id="analysisTable"></div>
</form>

AJAX function:

 function loadAnalysis() {
    var xhttp = new XMLHttpRequest();
    var url = document.getElementById("url").value;
    if (url == "") {
      alert("Please enter URL");
      return;
    }
    xhttp.onreadystatechange = function() {
      if (this.readyState === 4 && this.status === 200) {
        var data = this.responseText;
        var jsonResponse = JSON.parse(data);
        console.log(jsonResponse["lighthouseResult"]);
        var table = document.createElement('table');
        table.setAttribute('class', 'result');
        var properties = ['performance', 'accessibility', 'best-practices', 'seo', 'pwa'];
        var capitalize = function(s) {
          return s.charAt(0).toUpperCase() + s.slice(1);
        }
        var tr = document.createElement('tr');
        for (var i = 0; i < properties.length; i++) {
          var th = document.createElement('th');
          th.appendChild(document.createTextNode(capitalize(properties[i])));
          tr.appendChild(th);
        }
        table.appendChild(tr);
        var tr, row;
        console.log("jsonResponse", jsonResponse);
        for (var r = 0; r < jsonResponse["lighthouseResult"].categories.length; r++) {
          tr = document.createElement('tr');
          row = jsonResponse["lighthouseResult"].categories[r];
          for (var i = 0; i < properties.length; i++) {
            var td = document.createElement('td');
            td.appendChild(document.createTextNode(row[properties[i]]));
            tr.appendChild(td);
          }
          table.appendChild(tr);
        }
        document.getElementById('analysisTable').appendChild(table);
      }
    };
    xhttp.open("GET", "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=" + encodeURIComponent(url) + "&key=AIzaSyDSNxhf0capOwppqlg9wZJUvzBewxf6mHU&strategy=mobile", true);
    xhttp.send();
  }

JSON response example:

{"lighthouseResult":{"categories":{"performance":{"score":1.0},"accessibility":{"score":0.9},"best-practices":{"score":0.92},"seo":{"score":0.7},"pwa":{"score":0.54}}}}

Sample:

//var data = this.responseText; //original
var data = '{"lighthouseResult":{"categories":{"performance":{"score":1.0},"accessibility":{"score":0.9},"best-practices":{"score":0.92},"seo":{"score":0.7},"pwa":{"score":0.54}}}}'

var jsonResponse = JSON.parse(data);
console.log(jsonResponse["lighthouseResult"]);
var table = document.createElement('table');
table.setAttribute('class', 'result');
var properties = ['performance', 'accessibility', 'best-practices', 'seo', 'pwa'];
var capitalize = function(s) {
  return s.charAt(0).toUpperCase() + s.slice(1);
}
var tr = document.createElement('tr');
for (var i = 0; i < properties.length; i++) {
  var th = document.createElement('th');
  th.appendChild(document.createTextNode(capitalize(properties[i])));
  tr.appendChild(th);
}
table.appendChild(tr);
var tr, row;
console.log("jsonResponse", jsonResponse);
for (var r = 0; r < jsonResponse["lighthouseResult"].categories.length; r++) {
  tr = document.createElement('tr');
  row = jsonResponse["lighthouseResult"].categories[r];
  for (var i = 0; i < properties.length; i++) {
    var td = document.createElement('td');
    td.appendChild(document.createTextNode(row[properties[i]]));
    tr.appendChild(td);
  }
  table.appendChild(tr);
}
document.getElementById('analysisTable').appendChild(table);
<div id="analysisTable"></div>

2

Answers


  1. It looks like you’re forgetting about the score property each section of your data has.

    td.appendChild(document.createTextNode(row[properties[i]]));
    

    should be

    td.appendChild(document.createTextNode(row[properties[i]].score));
    
    Login or Signup to reply.
  2. lighthouse.categories.length will be 0 because it addresses an object not an array.
    Use Object.keys to iterate over the keys.

    See the example underneath.
    We use Object.keys to iterate over every entry of category. Then the length returns one row.

    At last we target the property: jsonResponse["lighthouseResult"][categories[r]]; and append the score property.

    //var data = this.responseText; //original
    var data = '{"lighthouseResult":{"categories":{"performance":{"score":1.0},"accessibility":{"score":0.9},"best-practices":{"score":0.92},"seo":{"score":0.7},"pwa":{"score":0.54}}}}'
    
    var jsonResponse = JSON.parse(data);
    console.log(jsonResponse["lighthouseResult"]);
    var table = document.createElement('table');
    table.setAttribute('class', 'result');
    var properties = ['performance', 'accessibility', 'best-practices', 'seo', 'pwa'];
    var capitalize = function(s) {
      return s.charAt(0).toUpperCase() + s.slice(1);
    }
    var tr = document.createElement('tr');
    for (var i = 0; i < properties.length; i++) {
      var th = document.createElement('th');
      th.appendChild(document.createTextNode(capitalize(properties[i])));
      tr.appendChild(th);
    }
    table.appendChild(tr);
    var tr, row;
    console.log("jsonResponse", jsonResponse);
    
    var categories = Object.keys(jsonResponse["lighthouseResult"]);
    for (var r = 0; r < categories.length; r++) {
      tr = document.createElement('tr');
      row = jsonResponse["lighthouseResult"][categories[r]];
      for (var i = 0; i < properties.length; i++) {
        var td = document.createElement('td');
        td.appendChild(document.createTextNode(row[properties[i]].score));
        tr.appendChild(td);
      }
      table.appendChild(tr);
    }
    document.getElementById('analysisTable').appendChild(table);
    <div id="analysisTable"></div>

    With Object.keys there is room for code improvement. Look at this cleaned up example:

    //ES6 example
    //var data = this.responseText; //original
    const data = '{"lighthouseResult":{"categories":{"performance":{"score":1.0},"accessibility":{"score":0.9},"best-practices":{"score":0.92},"seo":{"score":0.7},"pwa":{"score":0.54}}}}'
    
    const jsonResponse = JSON.parse(data);
    
    const table = document.createElement('table');
    table.setAttribute('class', 'result');
    
    const capitalize = function(s) {
      return s.charAt(0).toUpperCase() + s.slice(1);
    }
    
    const trHeader = document.createElement('tr');
    //save the category names to an array using Object.keys
    const categories = jsonResponse["lighthouseResult"].categories;
    const categoriesKeys = Object.keys(jsonResponse["lighthouseResult"].categories);
    
    //use arrays forEach functions
    const trBody = document.createElement("tr");
    
    categoriesKeys.forEach( function(item) {
    
      const th = document.createElement('th');
      th.appendChild(document.createTextNode(capitalize(item)));
      trHeader.appendChild(th);
      
      const td = document.createElement('td');
    
      td.appendChild(document.createTextNode(categories[item].score));
      trBody.appendChild(td);  
      
    });
    
    table.appendChild(trHeader);
    table.appendChild(trBody);
    
    document.getElementById('analysisTable').appendChild(table);
    <div id="analysisTable"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search