0

I am trying a JavaScript challenge but get stuck badly. The requirement is not to modify any other files except app.js and no library (i.e. no JQuery etc.)

Here is the file system:

css
  bootstrap.min.css
image
  1.gif
  2.gif
  3.gif
  4.gif
  5.gif
js
  app.js
json
  data.js
sample.html

Here is the sample.html:

<!doctype>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<title>Sample</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<div class="container">
  <h2>Only Pure JavaScript</h2>
  <div class="contents">
    <table class="table">
      <thead>
        <tr>
          <th>Id</th>
          <th>Image</th>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>
  </div>
</div>
<script src="json/data.js"></script>
<script src="js/app.js"></script>
</body>
</html>

Here is the data.js:

var sample_data = [
  {
    "id": "5",
    "name": "name #5",
    "thumbnailUrl": "image/5.gif",
    "price": 170
  },
  {
    "id": "1",
    "name": "name #1",
    "thumbnailUrl": "image/1.gif",
    "price": 170
  },
  {
    "id": "2",
    "name": "name #2",
    "thumbnailUrl": "image/2.gif",
    "price": 270
  },
  {
    "id": "8",
    "name": "name #8",
    "thumbnailUrl": "image/8.gif",
    "price": 70
  },
  {
    "id": "10",
    "name": "name #10",
    "thumbnailUrl": "image/10.gif",
    "price": 170
  },
]

And this is what I have in app.js currently:

var jsonFile = "json/data.js";
var len = sample_data.length;
// document.write('len: ' + len + "<br>");

var table = document.createElement('table');
var body = document.createElement('tbody');


for (var i = 0; i < len; i++) {
    var tr = document.createElement('tr');
    var td = document.createElement('td');
    var s = sample_data[i];

    document.write('id: ' + s.id + "<br>");

    td.innerHTML = s.id;
    tr.appendChild(td);

    td = document.createElement('td');
    document.write('name: ' + s.name + "<br>");
    td.innerHTML = s.name;
    tr.appendChild(td);

    td = document.createElement('td');
    document.write('thumbnailUrl: ' + s.thumbnailUrl + "<br>");
    td.innerHTML = s.thumbnailUrl;
    tr.appendChild(td);

    td = document.createElement('td');
    document.write('price: ' + s.price + "<br>");
    td.innerHTML = s.price;
    tr.appendChild(td);

    body.appendChild(tr);
}

table.appendChild(body);

I've spent so much time and tried 4 different ways and this one attached is the closest I can get (it shows correctly with document.write). Seriously, without any library or changes in the html page, it is hard for me. Any help or direction of where to look for information will be greatly appreciated. Remember, only app.js can be changed for this.

ian0411
  • 4,115
  • 3
  • 25
  • 33
  • Look the top answer [here](https://stackoverflow.com/questions/5235321/how-do-i-load-a-javascript-file-dynamically?answertab=votes#tab-top) and then you'll be able to iterate the array. – César David Castro Valencia Nov 16 '17 at 21:31
  • 1
    `data.js` is not JSON, it's Javascript. You need to create a ` – Barmar Nov 16 '17 at 21:35
  • In `sample.html` there is already a script element pointing to `json/data.js`, which means that `sample_data` is already available as a global variable in `app.js` – Maluen Nov 16 '17 at 21:39

2 Answers2

2

Do you really need document.write ? Replace it with a simple console.log if you only need it for debugging purposes.

Moreover doesn't look like you are appending the table element anywhere. Add document.body.appendChild(table) at the end of app.js.

However from your sample.html I can see you already have an existing TBODY element, thus you most likely want to add the values to that existing table.

Instead of doing

var body = document.createElement('tbody');

you can reference the existing element with

var body = document.getElementsByTagName('tbody')[0]

at that point you can remove the table variable completely.

var jsonFile = "json/data.js";
var len = sample_data.length;
// document.write('len: ' + len + "<br>");

var body = document.getElementsByTagName('tbody')[0];


for (var i = 0; i < len; i++) {
    var tr = document.createElement('tr');
    var td = document.createElement('td');
    var s = sample_data[i];

    //console.log('id: ' + s.id);

    td.innerHTML = s.id;
    tr.appendChild(td);

    td = document.createElement('td');
    //console.log('name: ' + s.name);
    td.innerHTML = s.name;
    tr.appendChild(td);

    td = document.createElement('td');
    //console.log('thumbnailUrl: ' + s.thumbnailUrl);
    td.innerHTML = s.thumbnailUrl;
    tr.appendChild(td);

    td = document.createElement('td');
    //console.log('price: ' + s.price);
    td.innerHTML = s.price;
    tr.appendChild(td);

    body.appendChild(tr);
}
<!doctype>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<title>Sample</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
</head>
<body>
<div class="container">
  <h2>Only Pure JavaScript</h2>
  <div class="contents">
    <table class="table">
      <thead>
        <tr>
          <th>Id</th>
          <th>Image</th>
          <th>Name</th>
          <th>Price</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>
  </div>
</div>
<script>
var sample_data = [
  {
    "id": "5",
    "name": "name #5",
    "thumbnailUrl": "image/5.gif",
    "price": 170
  },
  {
    "id": "1",
    "name": "name #1",
    "thumbnailUrl": "image/1.gif",
    "price": 170
  },
  {
    "id": "2",
    "name": "name #2",
    "thumbnailUrl": "image/2.gif",
    "price": 270
  },
  {
    "id": "8",
    "name": "name #8",
    "thumbnailUrl": "image/8.gif",
    "price": 70
  },
  {
    "id": "10",
    "name": "name #10",
    "thumbnailUrl": "image/10.gif",
    "price": 170
  },
]
</script>
<script src="js/app.js"></script>
</body>
</html>
Maluen
  • 1,753
  • 11
  • 16
  • So just change `var body = document.getElementsByTagName('tbody')[0];` and it worked. I actually tried that many times but didn't include the `[0]` in the back. Why this is needed since there is only one `tbody` tag? Won't missing index imply the first tag found? Again, thank you so much. – ian0411 Nov 17 '17 at 02:06
  • 1
    @ian0411 `getElementsByTagName` always return a list, so you need [0] to access the first element. See https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName – Maluen Nov 17 '17 at 10:32
1

data.js is Javascript, not JSON. To load it, create a <script> element that points to it.

After the line:

var jsonFile = "json/data.js";

Put the line:

document.write('<scr' + 'ipt src="' + jsonFile + '"></script>');
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I just noticed that you already have this ` – Barmar Nov 17 '17 at 17:06
  • The problem is that you're never appending the new table to the body. I wonder why you're creating a new table, don't you just want to fill in the body of the table that's already in `sample.html`? – Barmar Nov 17 '17 at 17:07
  • Give the tbody an ID, and use `getElementById`. – Barmar Nov 17 '17 at 17:13
  • `document.querySelector()` is a good one which make it shorter. But is there a better way to replace my `for` loop to make it shorter? – ian0411 Nov 17 '17 at 17:27
  • 1
    Instead of using lots of `createElement` and `appendChild`, you could concatenate strings into HTML text, and then assign to `body.innerHTML`. But your method is much safer, as you don't have to worry about quoting issues. – Barmar Nov 17 '17 at 17:35