'I am having trouble with functions in Javascript quiz. How do I do it?
I am very new to coding and am stumped as to what to do next. I have 2 pages of JS, one for questions, one for functionality, and a very basic html. My questions are populating, randomizing, and the buttons are working with all text inside. I am trying to have the function handleAnswer take care of adding the score, deducting time if incorrect, and moving to the next question all in one shot. Is this possible? Also, why does it keep saying that correct and answers aren't defined? Any suggestions would be much appreciated as I have been staring at this for days now. THANKS!
Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz Page</title>
<link rel="stylesheet" href="quiz.css">
</head>
<body>
<nav>
<button id="highScore">Show Highscore</button>
<h2>Time: <span id="time">90</span></h2>
</nav>
<main>
<h1>The Coding Quiz</h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias animi ea corrupti maxime laborum, eligendi, ipsum veritatis molestiae dolorum quam asperiores, repellendus velit quis nesciunt.</p>
<p>Sunt velit deleniti ullam excepturi laborum maiores quisquam vero corrupti obcaecati cumque animi officiis praesentium sequi laudantium, inventore quis, distinctio nihil impedit atque, eaque aspernatur.</p>
<button id="start">Start Quiz</button>
</main>
<script src="questions.js"></script>
<script src="quiz.js"></script>
</body>
</html>
let qI = 0;
let clockId;
let time = 90;
let clock = document.getElementById('time');
let prompt = document.querySelector('main');
let randomQuestions = questions.sort(()=>Math.random()-.5);
let score = 0
document.getElementById('start').addEventListener('click', handleClick);
function handleClick() {
clockId = setInterval(handleTime, 1000);
handleQuestion();
// prompt.innerHTML = '';
};
function handleQuestion() {
if(qI < questions.length) {
let { question, answers, correct } = questions[qI];
prompt.innerHTML = `<h1>${question}</h1>`
answers.forEach((answer,i) => {
prompt.innerHTML += `<button onclick='handleAnswer("${correct}")'> ${answer} </button>`
});
}
};
function handleAnswer(correct) {
if (answer.correct) {
score ++;
}
};
function handleTime() {
time--;
time>0
? clock.innerHTML = time
: endGame();
};
function endGame() {
clearInterval(clockId);
time = 0;
clock.innerHTML = time;
}
let questions = [
{
question: 'Javascript is often mistaken for which programming language?',
answers: ['C++','Java','Python','React'],
correct: 'Java'
},
{
question: 'Which of the following is a Boolean?',
answers: ['==','===','!==','True'],
correct: 'True'
},
{
question: 'Which of the following starts a loop?',
answers: ['for','if','do it!','console.log'],
correct: 'for'
},
{
question: 'Which of the following operators returns as true only if both operands are true?',
answers: ['||','*','&&','!='],
correct: '&&'
},
{
question: 'Which is the correct way to write a binding?',
answers: ['tinyLittleDog','TinyLittleDog','TinylittleDog','TINYLITTLEDOG'],
correct: 'tinyLittleDog'
}
]
Solution 1:[1]
Well, about your question, I think you don't have an answer
variable inside handleAnswer
function.
function handleAnswer(correct) {
if (answer.correct) { <-- I think here you only need "correct"
score ++;
}
};
Also, when you add the button, you're passing if it's correct inside a string, "False" in javascript is true, because any non empty string is true.
<button onclick='handleAnswer("${correct}")'> ${answer} </button>
Feel free to ask any other question, happy to help :D
Solution 2:[2]
Also, why does it keep saying that correct and answers aren't defined?
Because, handleAnswer() doesn't know what answer and correct are. What I've done is, when looping through answers, create new button with innerText of possible answer and place it into prompt. Then add click events inside the forEach loop on every button, that will call the handleAnswer() function.
In the handleAnswer() function, what I've changed is it checks if passed answer and correct are the same, and increases the score according to the outcome, if the answer is incorrect, it will move on the next question without increasing the score.
In handleQuestion(), you weren't increasing the qI value, that's why the next question wouldn't pop up.
Here's the code:
let questions = [{
question: "Javascript is often mistaken for which programming language?",
answers: ["C++", "Java", "Python", "React"],
correct: "Java",
},
{
question: "Which of the following is a Boolean?",
answers: ["==", "===", "!==", "True"],
correct: "True",
},
{
question: "Which of the following starts a loop?",
answers: ["for", "if", "do it!", "console.log"],
correct: "for",
},
{
question: "Which of the following operators returns as true only if both operands are true?",
answers: ["||", "*", "&&", "!="],
correct: "&&",
},
{
question: "Which is the correct way to write a binding?",
answers: [
"tinyLittleDog",
"TinyLittleDog",
"TinylittleDog",
"TINYLITTLEDOG",
],
correct: "tinyLittleDog",
},
];
let qI = 0;
let clockId;
let time = 90;
let clock = document.getElementById("time");
let prompt = document.querySelector("main");
let randomQuestions = questions.sort(() => Math.random() - 0.5);
let score = 0;
document.getElementById("start").addEventListener("click", handleClick);
function handleClick() {
clockId = setInterval(handleTime, 1000);
handleQuestion();
// prompt.innerHTML = '';
}
function handleQuestion() {
if (qI < questions.length) {
let {
question,
answers,
correct
} = questions[qI];
// increase qI value so the next question can be displayed
qI++;
prompt.innerHTML = `<h1>${question}</h1>`;
answers.forEach((answer) => {
// create new button
let answerBtn = document.createElement("button");
answerBtn.innerText = answer;
// insert newly created button inside prompt div
prompt.appendChild(answerBtn);
// add click listeners to every created button
answerBtn.addEventListener("click", () => {
// pass answer and correct values so you can compare
handleAnswer(answer, correct);
});
});
} else {
// do this when the game is over, you can place this code into endGame() function as well
prompt.innerHTML = `
<p>The quiz is over!</p>
<p>Final score: ${score}</p>
<p>Time needed to complete: ${clock.innerText}</p>`;
endGame();
}
}
function handleAnswer(answer, correct) {
if (answer === correct) {
score++;
handleQuestion();
} else {
time -= 10; // time deduction
clock.innerHTML = time;
handleQuestion();
}
}
function handleTime() {
time--;
time > 0 ? (clock.innerHTML = time) : endGame();
}
function endGame() {
clearInterval(clockId);
time = 0;
clock.innerHTML = time;
}
<nav>
<button id="highScore">Show Highscore</button>
<h2>Time: <span id="time">90</span></h2>
</nav>
<main>
<h1>The Coding Quiz</h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias animi ea corrupti maxime laborum, eligendi, ipsum veritatis molestiae dolorum quam asperiores, repellendus velit quis nesciunt.</p>
<p>Sunt velit deleniti ullam excepturi laborum maiores quisquam vero corrupti obcaecati cumque animi officiis praesentium sequi laudantium, inventore quis, distinctio nihil impedit atque, eaque aspernatur.</p>
<button id="start">Start Quiz</button>
</main>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | thismarcoantonio |
Solution 2 | sanodzeg |