'Quiz questions don't appear unless function run in console
I am trying to make a quiz but none of the Javascript is running - the contents of the quiz don't appear on the page - unless I run startQuiz() in the Google Chrome console. Why aren't the questions and answers appearing when the page loads? This is also my first time creating a snippet of my code so apologies if I was not successful and I'll try again.
// Variables
const quizContainer = document.querySelector('.quiz');
const resultsContainer = document.querySelector('.results');
const submitButton = document.querySelector('.submit');
// 1. Use object literals for individual questions and an array to make it easy to loop over:
const myQuestions = [
{
question: "Which two sports did Indigenous people inspire?",
answers: {
a: "Hockey and soccer",
b: "Basketball and lacrosse",
c: "Hockey and lacrosse",
d: "Basketball and baseball"
},
correctAnswer: "a"
},
{
question: "What is a 'toque'?",
answers: {
a: "A hat",
b: "A scarf",
c: "A baseball cap",
d: "A shirt"
},
correctAnswer: "a"
},
{
question: "Which Canadian celebrity has the highest net worth?",
answers: {
a: "Justin Bieber",
b: "Drake",
c: "Jim Carrey",
d: "Celine Dion"
},
correctAnswer: "d"
},
{
question: "Aside from English and French, what is the most spoken language in Canada?",
answers: {
a: "Mandarin",
b: "Punjabi",
c: "Cantonese",
d: "Spanish"
},
correctAnswer: "a"
},
{
question: "Who was Canada's first female prime minister?",
answers: {
a: "Angela Merkel",
b: "Suzanne Rice",
c: "Joanna Cunningham",
d: "Kim Campbell"
},
correctAnswer: "d"
},
{
question: "Canada was the ___ country to legalise same-sez marriage." ,
answers: {
a: "1st",
b: "4th",
c: "7th",
d: "8th"
},
correctAnswer: "b"
},
{
question: "What percentage of Canada's population identifies as 'people of colour'?",
answers: {
a: "15",
b: "18",
c: "20",
d: "22"
},
correctAnswer: "d"
},
{
question: "Canada only has one official bilingual province. Which is it?",
answers: {
a: "Quebec",
b: "Ontario",
c: "New Brunswick",
d: "P.E.I"
},
correctAnswer: "c"
},
{
question: "What flavour of potato chips can only be found in Canada?",
answers: {
a: "Maple Bacon",
b: "Ketcup",
c: "Dill Pickle",
d: "Barbeque"
},
correctAnswer: "b"
},
{
question: "What is the most purchased grocery store item in Canada?",
answers: {
a: "McCain's French Fries",
b: "Kraft Dinner",
c: "Maple Syrup",
d: "Bagged Milk"
},
correctAnswer: "b"
}
];
// Functions
function startQuiz(){
// create output variable to store the HTML output (all Q&A)
const output = [];
// for each question... Use current value (currentQuestion) and index (questionNumber) as parameters:
myQuestions.forEach(
(currentQuestion, questionNumber) => {
// variable to store list of possible answer choices
const answers = [];
// and for each available choice ...
for(letter in currentQuestion.answers){
// add an HTML radio button WITH label so user can click anywhere on the text, not JUST radio button
answers.push(
`<label>
<input type="radio" name="question${questionNumber}" value="${letter}">
${letter}:
${currentQuestion.answers[letter]}
</label>`
);
}
// add this question and its answers to the output
output.push(
`<div class="question">${currentQuestion.question}</div>
<div class="answers">${answers.join('')}</div>`
);
}
);
// Combine output list into one string of HTML and put it on the page
quizContainer.innerHTML = output.join('');
}
function showResults(){
const answerContainers = quizContainer.querySelectorAll('.answers');
let numCorrect = 0;
myQuestions.forEach(
(currentQuestion, questionNumber) => {
// find selected answer in HTML
const answerContainer = answerContainers[questionNumber]; // 1. First, look in the right answer container for the current question
const selector = `input[name=question${questionNumber}]:checked`; // 2. Define a CSS selector `:checked` to find which radio button is checked
const userAnswer = (answerContainer.querySelector(selector) || {}).value; // 3. Use querySelecto to search for the just defined CSS selector to find the checked button. Get the value of that answer using .value
// if answer is correct
if(userAnswer === currentQuestion.correctAnswer){
numCorrect++;
}
else {
answerContainers[questionNumber].style.color = 'red';
}
});
// Show number of correct answers
resultsContainer.innerHTML = `You got ${numCorrect} out of ${myQuestions.length}`;
// Display quiz right away
startQuiz();
// On submit, show results
submitButton.addEventListener('click', showResults) }
;
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-family: 'Fraunces', serif;
}
.question{
font-weight: 500;
}
.answers{
margin-bottom: 30px;
display: block;
}
.submit{
font-size: 10px;
background-color: lightgray;
}
<!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">
<link rel="stylesheet" href="index.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@100;200;400&display=swap" rel="stylesheet">
<title>Quiz</title>
</head>
<body>
<h1>Easy Canada Quiz</h1>
<div class="quiz"></div>
<button class="submit">Submit</button>
<div class="results"></div>
<script src="index.js"></script>
</body>
</html>
Solution 1:[1]
If I see correctly you are closing your showResults function too late.
Move } from here:submitButton.addEventListener('click', showResults) }
And put it after this:resultsContainer.innerHTML = You got ${numCorrect} out of ${myQuestions.length};
You called startQuiz inside showResults. That's the reason why it didn't call itself on start.
Solution 2:[2]
Call function on submit button <button class="submit" onclick="showResults();">Submit</button>
Change Position on startQuiz() function
submitButton.addEventListener('click', showResults) }
// Display quiz right away
startQuiz();
// Variables
const quizContainer = document.querySelector('.quiz');
const resultsContainer = document.querySelector('.results');
const submitButton = document.querySelector('.submit');
// 1. Use object literals for individual questions and an array to make it easy to loop over:
const myQuestions = [
{
question: "Which two sports did Indigenous people inspire?",
answers: {
a: "Hockey and soccer",
b: "Basketball and lacrosse",
c: "Hockey and lacrosse",
d: "Basketball and baseball"
},
correctAnswer: "a"
},
{
question: "What is a 'toque'?",
answers: {
a: "A hat",
b: "A scarf",
c: "A baseball cap",
d: "A shirt"
},
correctAnswer: "a"
},
{
question: "Which Canadian celebrity has the highest net worth?",
answers: {
a: "Justin Bieber",
b: "Drake",
c: "Jim Carrey",
d: "Celine Dion"
},
correctAnswer: "d"
},
{
question: "Aside from English and French, what is the most spoken language in Canada?",
answers: {
a: "Mandarin",
b: "Punjabi",
c: "Cantonese",
d: "Spanish"
},
correctAnswer: "a"
},
{
question: "Who was Canada's first female prime minister?",
answers: {
a: "Angela Merkel",
b: "Suzanne Rice",
c: "Joanna Cunningham",
d: "Kim Campbell"
},
correctAnswer: "d"
},
{
question: "Canada was the ___ country to legalise same-sez marriage." ,
answers: {
a: "1st",
b: "4th",
c: "7th",
d: "8th"
},
correctAnswer: "b"
},
{
question: "What percentage of Canada's population identifies as 'people of colour'?",
answers: {
a: "15",
b: "18",
c: "20",
d: "22"
},
correctAnswer: "d"
},
{
question: "Canada only has one official bilingual province. Which is it?",
answers: {
a: "Quebec",
b: "Ontario",
c: "New Brunswick",
d: "P.E.I"
},
correctAnswer: "c"
},
{
question: "What flavour of potato chips can only be found in Canada?",
answers: {
a: "Maple Bacon",
b: "Ketcup",
c: "Dill Pickle",
d: "Barbeque"
},
correctAnswer: "b"
},
{
question: "What is the most purchased grocery store item in Canada?",
answers: {
a: "McCain's French Fries",
b: "Kraft Dinner",
c: "Maple Syrup",
d: "Bagged Milk"
},
correctAnswer: "b"
}
];
// Functions
function startQuiz(){
// create output variable to store the HTML output (all Q&A)
const output = [];
// for each question... Use current value (currentQuestion) and index (questionNumber) as parameters:
myQuestions.forEach(
(currentQuestion, questionNumber) => {
// variable to store list of possible answer choices
const answers = [];
// and for each available choice ...
for(letter in currentQuestion.answers){
// add an HTML radio button WITH label so user can click anywhere on the text, not JUST radio button
answers.push(
`<label>
<input type="radio" name="question${questionNumber}" value="${letter}">
${letter}:
${currentQuestion.answers[letter]}
</label>`
);
}
// add this question and its answers to the output
output.push(
`<div class="question">${currentQuestion.question}</div>
<div class="answers">${answers.join('')}</div>`
);
}
);
// Combine output list into one string of HTML and put it on the page
quizContainer.innerHTML = output.join('');
}
function showResults(){
const answerContainers = quizContainer.querySelectorAll('.answers');
let numCorrect = 0;
myQuestions.forEach(
(currentQuestion, questionNumber) => {
// find selected answer in HTML
const answerContainer = answerContainers[questionNumber]; // 1. First, look in the right answer container for the current question
const selector = `input[name=question${questionNumber}]:checked`; // 2. Define a CSS selector `:checked` to find which radio button is checked
const userAnswer = (answerContainer.querySelector(selector) || {}).value; // 3. Use querySelecto to search for the just defined CSS selector to find the checked button. Get the value of that answer using .value
// if answer is correct
if(userAnswer === currentQuestion.correctAnswer){
numCorrect++;
}
else {
answerContainers[questionNumber].style.color = 'red';
}
});
// Show number of correct answers
resultsContainer.innerHTML = `You got ${numCorrect} out of ${myQuestions.length}`;
// On submit, show results
submitButton.addEventListener('click', showResults) }
// Display quiz right away
startQuiz();
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-family: 'Fraunces', serif;
}
.question{
font-weight: 500;
}
.answers{
margin-bottom: 30px;
display: block;
}
.submit{
font-size: 10px;
background-color: lightgray;
}
<!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">
<link rel="stylesheet" href="index.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@100;200;400&display=swap" rel="stylesheet">
<title>Quiz</title>
</head>
<body>
<h1>Easy Canada Quiz</h1>
<div class="quiz"></div>
<button class="submit" onclick="showResults();">Submit</button>
<div class="results"></div>
<script src="index.js"></script>
</body>
</html>
Solution 3:[3]
You should probably either call startQuiz in a start button or when the window is loaded.
You can do this by:
Calling when whole site is loaded:
<body onload="startQuiz();"> ...
You can also do it by putting it in a start button:
@import url('https://fonts.googleapis.com/css2?family=Oxygen&display=swap');
.optionalbtnstyling {
/*optional styling*/
padding: 10px;
font-size: 25px;
background: none;
transition: 1.7s;
font-family: 'Oxygen', sans-serif;
border: 2px solid #0c0c0c;
}
.optionalbtnstyling:hover {
/*more optional styling*/
background: #0c0c0c;
color: #f0f0f0;
}
<button type="button" onclick="startQuiz();" class="optionalbtnstyling">Start Quiz</button>
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 | Pavel Schiller |
| Solution 2 | Lalji Tadhani |
| Solution 3 | ethry |
