Home > Software engineering >  How to generate HTML code using Javascript and JSON?
How to generate HTML code using Javascript and JSON?

Time:11-28

I need to create a quiz by parsing a JSON file. The checked answers must be stored in the local storage.

The JSON code:

{
    "quiz": {
        "q1": {
            "question": "Which one is correct team name in NBA?",
            "options": [
                "New York Bulls",
                "Los Angeles Kings",
                "Golden State Warriros",
                "Huston Rocket"
            ],
            "answer": "Huston Rocket"
        },
        "q2": {
            "question": "'Namaste' is a traditional greeting in which Asian language?",
            "options": [
                "Hindi",
                "Mandarin",
                "Nepalese",
                "Thai"
            ],
            "answer": "Hindi"
        },
        "q3": {
            "question": "The Spree river flows through which major European capital city?",
            "options": [
                "Berlin",
                "Paris",
                "Rome",
                "London"
            ],
            "answer": "Berlin"
        },
        "q4": {
            "question": "Which famous artist had both a 'Rose Period' and a 'Blue Period'?",
            "options": [
                "Pablo Picasso",
                "Vincent van Gogh",
                "Salvador Dalí",
                "Edgar Degas"
            ],
            "answer": "Pablo Picasso"
        }
    }
}

The code is below:

<div id="container"></div>
    <input type ="submit" name ="submit" value = "Submit answers" onclick = "results()">
    <script>
        let data = {"quiz": {"q1": {"question": "Which one is correct team name in NBA?", "options": ["New York Bulls", "Los Angeles Kings", "Golden State Warriros", "Huston Rocket"], "answer": "Huston Rocket"}, "q2": {"question": "'Namaste' is a traditional greeting in which Asian language?", "options": ["Hindi", "Mandarin", "Nepalese", "Thai"], "answer": "Hindi"}, "q3": {"question": "The Spree river flows through which major European capital city?", "options": ["Berlin", "Paris", "Rome", "London"], "answer": "Berlin"}, "q4": {"question": "Which famous artist had both a 'Rose Period' and a 'Blue Period'?", "options": ["Pablo Picasso", "Vincent van Gogh", "Salvador Daly", "Edgar Degas"], "answer": "Pablo Picasso"}}};
        let list = document.createElement("ul");
        for (let questionId in data["quiz"]) {
            let item = document.createElement("node");
            let question = document.createElement("strong");
            question.innerHTML = questionId   ": "   data["quiz"][questionId]["question"];
            item.appendChild(question);
            list.appendChild(item);
            let sublist = document.createElement("ul");
            item.appendChild(sublist);
            for (let option of data["quiz"][questionId]["options"]) {
                item = document.createElement("input");
                item.type = "radio";
                item.name = data["quiz"][questionId];
                var label = document.createElement("label");
                label.htmlFor = "options";
                label.appendChild(document.createTextNode(data["quiz"][questionId]["options"]));
                var br = document.createElement('br');
                sublist.appendChild(item);
                document.getElementById("container").appendChild(label);
                document.getElementById("container").appendChild(br); 
            }                      
        }
        document.getElementById("container").appendChild(list);     
        function results () {
            var score = 0;
            if (data["quiz"][questionId]["answer"].checked) {
                score  ;
            }
        }
        localStorage.setItem("answers","score");
    </script>    

I should get this:

enter image description here

Instead I got this, no matter how many times I rewrite the code:

enter image description here

Whay am I doing wrong?

Thank you very much for your help,

Mary.

CodePudding user response:

You have a small error with document.createElement("node") - there is no tag node so appending other elements to that is also incorrect. The code could be simplified though as below ( the add to local storage will throw an error in the snippet though )

let data = {
  "quiz": {
    "q1": {
      "question": "Which one is correct team name in NBA?",
      "options": ["New York Bulls", "Los Angeles Kings", "Golden State Warriros", "Huston Rocket"],
      "answer": "Huston Rocket"
    },
    "q2": {
      "question": "'Namaste' is a traditional greeting in which Asian language?",
      "options": ["Hindi", "Mandarin", "Nepalese", "Thai"],
      "answer": "Hindi"
    },
    "q3": {
      "question": "The Spree river flows through which major European capital city?",
      "options": ["Berlin", "Paris", "Rome", "London"],
      "answer": "Berlin"
    },
    "q4": {
      "question": "Which famous artist had both a 'Rose Period' and a 'Blue Period'?",
      "options": ["Pablo Picasso", "Vincent van Gogh", "Salvador Daly", "Edgar Degas"],
      "answer": "Pablo Picasso"
    }
  }
};

// utility prototype to shuffle an array
Array.prototype.shuffle=()=>{
  let i = this.length;
  while (i > 0) {
    let n = Math.floor(Math.random() * i);
    i--;
    let t = this[i];
    this[i] = this[n];
    this[n] = t;
  }
  return this;
};


let list = document.createElement("ul");

Object.keys(data.quiz).forEach((q, index) => {
  // the individual record
  let obj = data.quiz[q];
  
  // add the `li` item & set the question number as data-attribute
  let question = document.createElement("li");
      question.textContent = obj.question;
      question.dataset.question = index   1;
      question.id = q;

  // randomise the answers
  obj.options.shuffle();

  // Process all the answers - add new radio & label
  Object.keys(obj.options).forEach(key => {
    let option = obj.options[key];
    let label = document.createElement('label');
        label.dataset.text = option;

    let cbox = document.createElement('input');
        cbox.type = 'radio';
        cbox.name = q;
        cbox.value = option;
        
    // add the new items
    label.appendChild(cbox);
    question.appendChild(label);
  });
  
  // add the question
  list.appendChild(question);
});

// add the list to the DOM
document.getElementById('container').appendChild(list);



// Process the checked radio buttons to determine score.
document.querySelector('input[type="button"]').addEventListener('click', e => {
  let score = 0;
  let keys = Object.keys(data.quiz);
  
  document.querySelectorAll('[type="radio"]:checked').forEach((radio, index) => {
    if( radio.value === data.quiz[ keys[index] ].answer ) score  ;
  });
  
  console.log('%d/%d', score, keys.length);
  localStorage.setItem("answers", score);
})
#container>ul>li {
  font-weight: bold
}

#container>ul>li>label {
  display: block;
  padding: 0.1rem;
  font-weight: normal;
}

#container>ul>li>label:after {
  content: attr(data-text);
}

#container>ul>li:before {
  content: 'Question 'attr(data-question)': ';
  color: blue
}
<div id="container"></div>
<input type="button" value="Submit answers" />

CodePudding user response:

You need to make minor changes to your nest loop so that the option labels are inserted in the correct location. See the code snippet where it is marked "remove" and "add" for the changes you need to make.

As @ProfessorAbronsius noted, there isn't an html tag called "node", though that won't stop your code from working.

let data = {"quiz": {"q1": {"question": "Which one is correct team name in NBA?", "options": ["New York Bulls", "Los Angeles Kings", "Golden State Warriros", "Huston Rocket"], "answer": "Huston Rocket"}, "q2": {"question": "'Namaste' is a traditional greeting in which Asian language?", "options": ["Hindi", "Mandarin", "Nepalese", "Thai"], "answer": "Hindi"}, "q3": {"question": "The Spree river flows through which major European capital city?", "options": ["Berlin", "Paris", "Rome", "London"], "answer": "Berlin"}, "q4": {"question": "Which famous artist had both a 'Rose Period' and a 'Blue Period'?", "options": ["Pablo Picasso", "Vincent van Gogh", "Salvador Daly", "Edgar Degas"], "answer": "Pablo Picasso"}}};


let list = document.createElement("ul");
for (let questionId in data["quiz"]) {
  let item = document.createElement("node");
  let question = document.createElement("strong");
  question.innerHTML = questionId   ": "   data["quiz"][questionId]["question"];
  item.appendChild(question);
  list.appendChild(item);
  let sublist = document.createElement("ul");
  item.appendChild(sublist);
  
  // The problem is here in this nested loop  
  
  for (let option of data["quiz"][questionId]["options"]) {

    item = document.createElement("input");
    item.type = "radio";
    item.name = data["quiz"][questionId];
    var label = document.createElement("label");
    label.htmlFor = "options";
    
    // remove 1 
    // label.appendChild(document.createTextNode(data["quiz"][questionId]["options"]));
    
    // add 1
    label.appendChild(document.createTextNode(option));
    
    var br = document.createElement('br');
    sublist.appendChild(item);
    
        
    // remove 2
    //document.getElementById("container").appendChild(label);
    //document.getElementById("container").appendChild(br);
    
    // add 2
    sublist.appendChild(label);
    sublist.appendChild(br);
    
  }
  
 
 
 
  
}
document.getElementById("container").appendChild(list);

function results() {
  var score = 0;
  if (data["quiz"][questionId]["answer"].checked) {
    score  ;
  }
}

// Removed because snippets don't allow localStorage
// localStorage.setItem("answers", "score");
<div id="container"></div>
<input type="submit" name="submit" value="Submit answers" onclick="results()">

CodePudding user response:

Here's the answer to your question. Please let me know if you have any issues.

<div id="container"></div>
<input type="submit" name="submit" value="Submit answers" onclick="results()">
<script>
  let data = {
    "quiz": {
      "q1": {
        "question": "Which one is correct team name in NBA?",
        "options": ["New York Bulls", "Los Angeles Kings", "Golden State Warriros", "Huston Rocket"],
        "answer": "Huston Rocket"
      },
      "q2": {
        "question": "'Namaste' is a traditional greeting in which Asian language?",
        "options": ["Hindi", "Mandarin", "Nepalese", "Thai"],
        "answer": "Hindi"
      },
      "q3": {
        "question": "The Spree river flows through which major European capital city?",
        "options": ["Berlin", "Paris", "Rome", "London"],
        "answer": "Berlin"
      },
      "q4": {
        "question": "Which famous artist had both a 'Rose Period' and a 'Blue Period'?",
        "options": ["Pablo Picasso", "Vincent van Gogh", "Salvador Daly", "Edgar Degas"],
        "answer": "Pablo Picasso"
      }
    }
  };
  data = data.quiz;
  let list = document.createElement("ul");
  for (let questionId in data) {
    let item = document.createElement("node");
    let question = document.createElement("strong");
    let i = Object.keys(data).indexOf(questionId)   1;
    question.innerHTML = "Question"   i   ": "   questionId["question"];
    item.appendChild(question);
    list.appendChild(item);
    let sublist = document.createElement("ul");
    item.appendChild(sublist);
    for (let option of data[questionId]["options"]) {
      item = document.createElement("input");
      item.type = "radio";
      item.name = questionId;
      var label = document.createElement("label");
      label.htmlFor = option;
      label.appendChild(document.createTextNode(option));
      var br = document.createElement('br');
      sublist.appendChild(item);
      sublist.appendChild(label);
      sublist.appendChild(br);
    }
  }
  document.getElementById("container").appendChild(list);

  function results() {
    var score = 0;
    if (data[questionId]["answer"].checked) {
      score  ;
    }
  }
  //localStorage.setItem("answers", "score");
</script>

  • Related