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.

3
  • Look the top answer here and then you'll be able to iterate the array. Commented Nov 16, 2017 at 21:31
  • 1
    data.js is not JSON, it's Javascript. You need to create a <script> element that loads it. Commented Nov 16, 2017 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 Commented Nov 16, 2017 at 21:39

2 Answers 2

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>

Sign up to request clarification or add additional context in comments.

2 Comments

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 getElementsByTagName always return a list, so you need [0] to access the first element. See developer.mozilla.org/en-US/docs/Web/API/Element/…
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>');

5 Comments

I just noticed that you already have this <script> tag in sample.html. So you shouldn't need to do anything special in app.js to use the variable.
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?
Give the tbody an ID, and use getElementById.
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?
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.