Click here to Skip to main content
15,907,906 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello everyone
I am a new Javascript learner and I try to build a multiple choice quiz.
I have built a basic HTML , CSS and JS example. I pass 4 choice in an array, the right answer in another string variable and then I access the array with a for loop where I pass the values of the array into 4 different divs.
Finally I use an addEventListener and when I click on a different div a function that check if the answer is right or wrong and returns "right" or "wrong".
The code works fine but I would like someone to explain me how the loop behaves in relation with the addEventListener method.
Thank you in advance
<html>
  <head>
   <title>javascript test</title>
  </head>
   
  <body>
   <p>Which is the capital of France?</p>
   <div id="jstest1"></div>
   <div id="jstest2"></div>
   <div id="jstest3"></div>
   <div id="jstest4"></div>
   <style>
    p { font-size:20px;
	    width:400px;
		height:50px;
		border:1px dotted;
		}
    div {
	width:200px;
	height:150px;
	background-color:aliceblue;
	border:dotted 1px;
	margin:10 0 2 40;
	font-size:20px;
	}
	div:hover {background-color:yellow};
	
	</style>
	
	
	
   <script >
   let cities=["London","Paris","Berlin","Moscow"]
   let answer="Paris";
   for(let i=1;i<=4;i++){
   let box=document.querySelector("#jstest"+i); 
   box.innerText=cities[i-1];
   box.addEventListener("click",myfunction);
   function myfunction()
   {if (cities[i-1]===answer){
   box.style.backgroundColor="green";
   box.innerText="Right!";}
   else {box.innerText="Wrong!"
		 box.style.backgroundColor="red";}
	}}
   </script>


What I have tried:

I have Googled it but I got no information
Posted
Updated 21-Jan-23 5:32am
Comments
Member 15627495 19-Jan-23 16:18pm    
about the eventlisteners, as 'box' is allocated at each loop, it's a different element of the DOM. that the reason why it works well. 'box' is a new element every loops. then an eventlistener is created for each existing id and 'box'.
Member 15627495 19-Jan-23 16:29pm    
where you have some loss is the function myfunction() inside the for loop.
at every loop, the function is written, again and again, as advise : extract the function outside the loop.
It's tricky but out of logical.
with 200 cities in the array, the function is written 200 times, it's lot of weight for a simple 'good answer checking'.
Aristidis Tsirimiangos 20-Jan-23 4:59am    
Thank you so much for your answer!
I think that the function is invoked only if you "click", if you activate the "addEventListener", or am I wrong? I also noticed it does not work if the function it's not in the loop (local variables perhaps) .
Member 15627495 20-Jan-23 5:38am    
'Js' and 'dom build' have a own process with functions,
functions are executed a first time during 'dom build'( weird thing isn't it ? ), and after with existing events on a web page.

the eventlistener is added to your elements, it's part of the element like could be
'onLoad="func();" / onClick="otherFunc();"...'. it's same thing.
Aristidis Tsirimiangos 20-Jan-23 6:43am    
Thank you so much again! Do you recommend a book or a webpage for studying js a little more deeper?

1 solution

I think that the following was your question/request -

let cities=["London","Paris","Berlin","Moscow"]
   let answer="Paris";<

Your array consists of 4 possible answers of which Paris is the correct answer, this will be returned via your loop

for(let i=1;i<=4;i++){

Counter created of 4 for the 4 possible answers and 4 div's that will return which answer were selected

let box=document.querySelector("#jstest"+i);

link each div to the correct item in your cities array

box.addEventListener("click",myfunction);

Once an element containing an answer is clicked on, your function is invoked to compare the answer to correct or incorrect, make your label green or red based on the answer. We need to add some checks to see if a selection were made when submit button is clicked. I had a sample from a while back for this specific topic which might help you out, please change to suit your needs. You can also find more information/tutorials at Codefinity

Here's an example of how you could build a simple online quiz app using HTML, CSS, and JavaScript that quizzes users on the names of different cities of the world, with four possible answers but only one correct answer:

HTML:

<div id="quiz">
  <h1>Cities of the World Quiz</h1>
  <p id="question"></p>
  <form id="answers">
    <label><input type="radio" name="answer" value="1" /><span id="answer1"></span></label>
    <br>
    <label><input type="radio" name="answer" value="2" /><span id="answer2"></span></label>
    <br>
    <label><input type="radio" name="answer" value="3" /><span id="answer3"></span></label>
    <br>
    <label><input type="radio" name="answer" value="4" /><span id="answer4"></span></label>
    <br>
    <button id="submit" onclick="checkAnswer()">Submit</button>
  </form>
  <p id="result"></p>
</div>


CSS:

#quiz {
    width: 50%;
    margin: 0 auto;
    text-align: center;
}

.correct {
    color: green;
}

.incorrect {
    color: red;
}


JavaScript:

//Create the questions...
const questions = [
    {
        question: "What is the capital of France?",
        answers: {
            1: "Paris",
            2: "Rome",
            3: "Madrid",
            4: "Berlin"
        },
        correct: 1
    },
    {
        question: "What is the capital of Germany?",
        answers: {
            1: "Paris",
            2: "Rome",
            3: "Berlin",
            4: "Madrid"
        },
        correct: 3
    },
    {
        question: "What is the capital of Italy?",
        answers: {
            1: "Rome",
            2: "Paris",
            3: "Madrid",
            4: "Berlin"
        },
        correct: 1
    }
];

let currentQuestion = 0;

function setupQuestion() {
    document.getElementById("question").innerHTML = questions[currentQuestion].question;
    document.getElementById("answer1").innerHTML = questions[currentQuestion].answers[1];
    document.getElementById("answer2").innerHTML = questions[currentQuestion].answers[2];
    document.getElementById("answer3").innerHTML = questions[currentQuestion].answers[3];
    document.getElementById("answer4").innerHTML = questions[currentQuestion].answers[4];
}

//Start doing checks, i.e submitted, correct/incorrect, last question etc.
const submitBtn = document.getElementById("submit");
submitBtn.addEventListener("click", checkAnswer);

function checkAnswer() {
    let selected = document.querySelector('input[name="answer"]:checked');
    if (!selected) {
        alert("Please select an answer.");
        return;
    }
    let selectedAnswer = selected.value;
    if (selectedAnswer == questions[currentQuestion].correct) {
        document.getElementById("result").innerHTML = "Correct!";
        document.getElementById("result").classList.add("correct");
    } else {
        document.getElementById("result").innerHTML = "Incorrect";
        document.getElementById("result").classList.add("incorrect");
    }
    currentQuestion++;
    if (currentQuestion < questions.length) {
        setupQuestion();
    } else {
        alert("Quiz completed!");
    }
}


In this example, the addEventListener method is used to attach a click event to the submit button. When the button is clicked, the checkAnswer function is called. The function first checks if a radio button is selected, if not it will prompt the user to select an answer. Then it will check if the selected answer is correct or not. If the answer is correct, it will display "Correct!" with a green label and if the answer is not correct it will display "Incorrect" with red label, also it will increment the currentQuestion variable and check if there are more questions in the questions array if yes it will setup the next question if not it will display an alert message saying quiz completed.
 
Share this answer
 
v3
Comments
Aristidis Tsirimiangos 25-Jan-23 7:37am    
Dear Andre
Thank you very much for your long answer and example. Unfortunately it didn't work when I copied to my text editor but anyway you gave me brilliant ideas!
Andre Oosthuizen 25-Jan-23 11:25am    
Been a pleasure, happy coding.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900