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:
Instead I got this, no matter how many times I rewrite the code:
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>