Hi, I’m wondering if there’s a simple Javascript quiz that has, for example, 10 multiple choice questions, but on clicking the answer (from a dropdown menu) to each question, you would instantly see the result for that specific question, for example a (correct) tick, or (incorrect) x.
The idea being that you wouldn’t need to click a submit button to see the result.
Thanks.
There’s probably a way to do this with html/css where clicking on a choice will simply show/hide an X or tick mark.
Hi @dubman, are you asking for a tutorial or some sort of quiz generator? As @WebSteve, said, for the basics you don’t even need JS… for example:
.answer > :checked + label::after {
content: '\274C';
margin-left: 1em;
}
.answer > [data-correct]:checked + label::after {
content: '\2705';
}
<section class="question">
John, Paul, George and...
<div class="answer">
<input type="radio" name="answer-1" id="answer-1-1" data-correct="true">
<label for="answer-1-1">Ringo</label>
</div>
<div class="answer">
<input type="radio" name="answer-1" id="answer-1-2">
<label for="answer-1-2">Django</label>
</div>
<div class="answer">
<input type="radio" name="answer-1" id="answer-1-3">
<label for="answer-1-3">Rhino</label>
</div>
</section>
<section class="question">
Joey, Johnny, Dee Dee and...
<div class="answer">
<input type="radio" name="answer-2" id="answer-2-1">
<label for="answer-2-1">Timmy</label>
</div>
<div class="answer">
<input type="radio" name="answer-2" id="answer-2-2" data-correct="true">
<label for="answer-2-2">Tommy</label>
</div>
<div class="answer">
<input type="radio" name="answer-2" id="answer-2-3">
<label for="answer-2-3">Jimmy</label>
</div>
</section>
For more fine-grained control – e.g. disabling the radios for a checked answer – the essential JS would be to query for the answers, and add change event listeners like so:
const questions = document.querySelectorAll('.question')
function handleChange (event) {
// Update the UI here, such as disabling answers or
// displaying the correct answer in a fancier manner
const answers = event.currentTarget.querySelectorAll('input')
answers.forEach(answer => {
answer.disabled = true
})
}
questions.forEach(question => {
question.addEventListener('change', handleChange)
})
Out of curiousity, are you doing this for a homework assignment?
Cause… your description sounds awfully similar to several posts that happen roughly twice a year…
How would I implement the above piece of code. Is it php? Or does it go in the page Head?
Just wanted to improve a page so that a user could see the result of each answer individually
after clicking an option in the dropdown menu. My current solution of a submit button after each question is obviously not an ideal solution. I don’t necessarily need to set it up as a typical quiz, with a global result like “7 answers correct out of 10”
This is the page in question:
http://www.profesornativo.com/English_expressions.htm
Thanks
It’s CSS. It will go in your CSS file.
Ah so you already have the JS to check the answers:
f.onsubmit = function(){
checkAnswers({
question1: {answer: "c"},
question2: {answer: "c"},
question3: {answer: "b"},
question4: {answer: "c"},
question5: {answer: "a"},
question6: {answer: "b"},
question7: {answer: "a"},
question8: {answer: "b"},
question9: {answer: "c"},
question10: {answer: "a"}
})
return false;
}
You can just replace onsubmit
with onchange
then to get an immediate feedback – each time a change event occurs inside the form, it will propagate up to the form itself and your listener function will get called. This is also known as event bubbling:
Hi,
As m3g4p0p said, just swap out the submit listener for a change listener and you should be good.
However, I was a little surprised to look at the code and see that I wrote (at least) part of it.
It was probably fine back then, but has since seen a couple of iterations and could be improved a little.
The first thing is, don’t use tables for layouts. You have a list of questions, so it would make sense semantically to use an ordered list.
The JS logic could also be improved. Here’s a more up-to-date version with two questions (for demo purposes):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
.result {
display: inline-block;
height: 20px;
width: 20px;
}
.incorrect {
background: url(http://www.profesornativo.com/x.jpg);
background-repeat: no-repeat;
}
.correct {
background: url(http://www.profesornativo.com/tick.jpg);
background-repeat: no-repeat;
}
</style>
</head>
<body>
<ol>
<li>
<p>Spanish: Me lo contó un pajarito</p>
<p>
A little
<select name="question1">
<option value="na"></option>
<option value="a">birdie mentioned</option>
<option value="b">bird said to</option>
<option value="c">bird told</option>
</select>
me
<span class="result"></span>
</p>
</li>
<li>
<p>Spanish: A la más minima </p>
<p>
At the
<select name="question2">
<option value="na"></option>
<option value="a">fall of a leaf</option>
<option value="b">sound of a voice</option>
<option value="c">drop of a hat</option>
</select>
<span class="result"></span>
</p>
</li>
</ol>
<script>
const answers = {
question1: 'c',
question2: 'c',
}
function checkAnswer(select){
const correctAnswer = answers[select.name];
const selectedAnswer = select.options[select.selectedIndex].value;
const result = select.parentElement.querySelector('.result');
result.className = 'result';
if (selectedAnswer === correctAnswer) {
result.classList.add('correct');
} else {
result.classList.add('incorrect');
}
}
const selects = document.querySelectorAll('select');
[...selects].forEach((el) => {
el.addEventListener('change', () => {
checkAnswer(el);
});
});
</script>
</body>
</html>
Thanks James, your fully entitled to the credit for the code in question, and I see your current suggestion is exactly what I wanted!
And thanks to m3g4p0p, WebSteve and Gandalf - I will have a look at the suggestions!
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.