Reputation: 35
I have built a small interactive quiz section for my website, but I know it could be structured better. Each question will have three possible answers. The way I have it set up right now, I need a unique identifier for each of the possible answers. This quickly adds up multiple questions x 3 unique ID's. Can I pass the specific through my function instead of an ID?
<a class="toggle" href="#exampleQ" id="dropQ01" onclick="setCorrect('dropQ01', '#f9a81d')">
<b>Answer Ones</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ02" onclick="setWrong('dropQ02', '#f9a81d')">
<b>Answer 2</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ03" onclick="setWrong('dropQ03', '#f9a81d')">
<b>Answer 3</b>
</a>
When the options are clicked they change color.
Wrong Answer function:
var countX = 1;
function setWrong(btn, color) {
var property = document.getElementById(btn);
if (countX == 0) {
property.style.backgroundColor = "#f9a81d"
countX = 1;
} else {
property.style.backgroundColor = "#ff0033"
countX = 1;
}
}
Correct answer function.
var countC = 1;
function setCorrect(btn, color) {
var property = document.getElementById(btn);
if (countC == 0) {
property.style.backgroundColor = "#f9a81d"
countC = 1;
} else {
property.style.backgroundColor = "#00933B"
countC = 1;
}
}
If anybody sees some ways I can improve this code to be more efficient I would really appreciate it. Thank you.
Upvotes: 2
Views: 92
Reputation: 2926
Yes, we can pass the this
in the HTML mark-up but for a scalable, less redundant code, we can add the event listeners to the anchor tags after the DOM is loaded - this way you will have the this
pointing to the anchor tag also you now have an event
that you can use to maybe event.preventDefault();
to stop having that hash value appended in the url-
var allAnchors = document.querySelectorAll('#dropQ03, #dropQ02, #dropQ01');
var countX = 0,
countC = 0;
var eventListener = function (event) {
var Id = this.id;
if (Id == "dropQ03" || Id == 'dropQ02') {
if (countX == 0) {
this.style.backgroundColor = "#f9a81d"
countX = 1;
} else {
this.style.backgroundColor = "#ff0033"
countX = 1;
}
} else {
if (countC == 0) {
this.style.backgroundColor = "#f9a81d"
countC = 1;
} else {
this.style.backgroundColor = "#00933B"
countC = 1;
}
}
}
for (var i = 0; i < allAnchors.length; i++) {
allAnchors[i].addEventListener('click', eventListener);
}
<a class="toggle" href="#exampleQ" id="dropQ01" >
<b>Answer Ones</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ03" >
<b>Answer 3</b>
</a>
<a class="toggle" href="#exampleQ" id="dropQ02">
<b>Answer 3</b>
</a>
Upvotes: 0
Reputation: 12909
I agree with Dan Mullin's suggestion of using this
in answer to your specific question of how to avoid having to explicitly pass each ID.
In terms of overall structure you still have a lot of duplication between setCorrect and setWrong as well as the fact that implementing these per answer element has the unfortunate side effect of exposing the correct answers in the markup. Here's a quick little implementation that uses an answer key object with key/value pairs that map to the IDs of the answer elements.
const answerKey={Q01: 'a', Q02: 'd', Q03: 'b'}
let correctCount = 0;
let incorrectCount = 0;
function checkAnswer(event) {
const [question, answer] = event.target.id.split('_');
const correct = answerKey[question] === answer;
if (correct) {
event.target.style.backgroundColor = "green";
correctCount += 1;
document.getElementById('correct-count').innerHTML = correctCount;
} else {
event.target.style.backgroundColor = "red";
incorrectCount +=1;
document.getElementById('incorrect-count').innerHTML = incorrectCount;
}
}
const answers = document.querySelectorAll('.toggle');
answers.forEach(toggle => toggle.addEventListener("click", (e) => checkAnswer(e), false));
<p>Correct: <span id="correct-count">0</span></p>
<p>Incorrect: <span id="incorrect-count">0</span></p>
<h2>Question 1</h2>
<a class="toggle" href="#exampleQ" id="Q01_a">
Answer 1
</a>
<a class="toggle" href="#exampleQ" id="Q01_b">
Answer 2
</a>
<a class="toggle" href="#exampleQ" id="Q01_c">
Answer 3
</a>
<h2>Question 2</h2>
<a class="toggle" href="#exampleQ" id="Q02_a">
Answer 1
</a>
<a class="toggle" href="#exampleQ" id="Q02_b">
Answer 2
</a>
<a class="toggle" href="#exampleQ" id="Q02_c">
Answer 3
</a>
<a class="toggle" href="#exampleQ" id="Q02_d">
Answer 4
</a>
<a class="toggle" href="#exampleQ" id="Q02_e">
Answer 5
</a>
Upvotes: 0
Reputation: 4435
Drop the id and set your onclick
events like this:
<a class="toggle" href="#exampleQ" onclick="setCorrect(this, '#f9a81d')">
Doing it this way sends the element itself to the function.
Wrong answer function:
var countX = 1;
function setWrong(btn, color) {
if (countX == 0) {
btn.style.backgroundColor = "#f9a81d"
countX = 1;
} else {
btn.style.backgroundColor = "#ff0033"
countX = 1;
}
}
Correct answer function
var countC = 1;
function setCorrect(btn, color) {
if (countC == 0) {
btn.style.backgroundColor = "#f9a81d"
countC = 1;
} else {
btn.style.backgroundColor = "#00933B"
countC = 1;
}
}
Upvotes: 1