Reputation:
I am developing a quizz application in vanilla JavaScript and in the interest of best practices, I want to ensure I follow the D.R.Y. principle.
I have five questions that I need to check answers for.
As a result, instead of using if
statements five times, I thought I could implement a switch
statement like so:
callback.js:
function submitAnswers() {
var total = 5;
var score = 0;
// Get User Input
var q1 = document.forms['quizForm']['q1'].value;
var q2 = document.forms['quizForm']['q2'].value;
var q3 = document.forms['quizForm']['q3'].value;
var q4 = document.forms['quizForm']['q4'].value;
var q5 = document.forms['quizForm']['q5'].value;
// Validation
for (i = 1; i <= total; i++) {
if (eval('q'+i) == null || eval('q'+i) == '') {
alert('You missed question '+ i);
return false;
}
}
// Set Correct Answers
var answers = ["d","b","c","a","b"];
// Check answers
switch (answers) {
case q1 == answers[0]:
score++;
break;
case q2 == answers[1]:
score++;
break;
case q3 == answers[2]:
score++;
break;
case q4 == answers[3]:
score++;
break;
case q5 == answers[4]:
score++;
break;
}
alert('You scored '+score+' out of ' +total);
}
This is the index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/index.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<script type="text/javascript" src="js/callback.js"></script>
<title>Quiz About the Wonderful World of Fungi</title>
</head>
<body>
<div id="container">
<header>
<h1>Quiz About the Wonderful World of Fungi</h1>
<p>Test your knowledge</p>
</header>
<section>
<div id="results"></div>
<form class="myForm" name="quizForm" onSubmit="return submitAnswers()">
<h3>1. Roughly how many species of organisms of the kingdom of Fungi have been identified, so far?</h3>
<input type="radio" name="q1" value="a" id="q1a">a. 2 Million<br>
<input type="radio" name="q1" value="b" id="q1b">b. 37,000<br>
<input type="radio" name="q1" value="c" id="q1c">c. 58,000<br>
<input type="radio" name="q1" value="d" id="q1d">d. 73,000<br>
<h3>2. The process of specifically using mushrooms to break down toxic chemicals and sequester heavy metals is known as:</h3>
<input type="radio" name="q2" value="a" id="q2a">a. Bioremediation<br>
<input type="radio" name="q2" value="b" id="q2b">b. Mushremediation<br>
<input type="radio" name="q2" value="c" id="q2c">c. Mycoremediation<br>
<input type="radio" name="q2" value="d" id="q2d">d. Chitinremediation<br>
<h3>3. The above-ground part of the mushroom that we typically associate with a mushroom is only a small part of the whole organism,
as most of it is underground. What is the primary role of this part of the whole organism?</h3>
<input type="radio" name="q3" value="a" id="q3a">a. Nutrient Absorptionn<br>
<input type="radio" name="q3" value="b" id="q3b">b. Protection<br>
<input type="radio" name="q3" value="c" id="q3c">c. Sexual Reproduction<br>
<input type="radio" name="q3" value="d" id="q3d">d. Oxygen Absorption<br>
<h3>4. What Is the primary role of a mushroom’s underground mycelium?</h3>
<input type="radio" name="q4" value="a" id="q4a">a. Nutrient Absorption<br>
<input type="radio" name="q4" value="b" id="q4b">b. Anchoring<br>
<input type="radio" name="q4" value="c" id="q4c">c. Asexual Reproduction<br>
<input type="radio" name="q4" value="d" id="q4d">d. Protection<br>
<h3>5. The largest living organism on earth is thought to be a mushroom (the honey fungus) and it is estimated to be what distance across?</h3>
<input type="radio" name="q5" value="a" id="q5a">a. 0.5 mile<br>
<input type="radio" name="q5" value="b" id="q5b">b. 2.4 miles<br>
<input type="radio" name="q5" value="c" id="q5c">c. 8 miles<br>
<input type="radio" name="q5" value="d" id="q5d">d. 0.7 mile<br>
<br><br>
<input type="submit" name="" value="Submit Answers">
</form>
</section>
<footer>
<p>Copyright © 2017, All Rights Reserved</p>
</footer>
</div>
</body>
</html>
Upon testing this, I continued to get an alert saying I have 0 out of 5 correct, even when choosing the correct answers.
Is the switch
statement not the best solution here? Am I applying it wrong?
Upvotes: 0
Views: 72
Reputation: 43
You can create a reusable function for this instead of switch statement, and use for loop to check every target value;
// Answers
var answers = ["a", "b", "c"]
// Correct increments
var correct = 0;
// checkAnswer Function
var checkAnswer = function(question, answer) {
if (question !== answer) {
return false;
}
return true;
}
var form = document.getElementById('form');
form.addEventListener('submit', function(e) {
e.preventDefault();
// Notice length - 1, because we have button element there
/**
* If you want to declare variable for each inputs, change
* e.target.length and e.target[i].value to your arrays of q/a
*/
for (var i = 0; i < e.target.length - 1; i++) {
if (checkAnswer(e.target[i].value, answers[i]) === false) {
alert('False answer')
// Right answer function here
} else {
correct++
alert('Right answer!')
// False answer here
}
}
alert('Your answer is ' + correct + ' correct out of ' + (e.target.length - 1) + ' questions!');
})
<form id="form">
<input type="text" id="q1">
<input type="text" id="q2">
<input type="text" id="q3">
<button type="submit">Submit answer</button>
</form>
Upvotes: 0
Reputation: 1073968
The switch
value must match one of the case expressions. answers
will never match q1 == answers[0]
or similar. If you changed it to switch (true)
the switch
would work, but you'd still only be checking one answer, not all five (and it's not a very good use of switch
).
If you use five different qX
variables, you'll need five different if
statements. But that's not what you should do. Instead, see ***
comments:
function submitAnswers() {
var total = 5;
var score = 0;
var i; // *** Note we declare `i` so it's not an implicit global
// Get User Input
// *** ...as an array
var responses = [];
for (i = 1; i <= 5; ++i) {
responses.push(document.forms['quizForm']['q' + i].value);
};
// Set Correct Answers
// *** Moved
var answers = ["d","b","c","a","b"];
// Validation and check answers both at once
for (i = 0; i < responses.length; ++i) {
// *** `value` is never `null`, we can just use ! here
if (!responses[i]) {
alert('You missed question '+ i);
return false;
}
// *** Check response
if (response[i] == answers[i]) {
++score;
}
}
alert('You scored '+score+' out of ' +total);
}
A couple of notes:
i
). If you don't, in loose mode you can end up creating global variables by mistake, which can be quite difficult to debug. More (in a post on my anemic little blog)*: The Horror of Implicit Globalseval
to form a variable name like q1
, q2
, etc., you probably want an array instead. There are valid use cases for eval
, but they're very few and far between.Upvotes: 1
Reputation: 8731
Simple method. Form an array with all chosen answers and compare iteratively using Array#every
var correctanswers = ["d","b","c","a","b"];
var choosenanswers = [q1,q2,q3,q4,q5];
var isallcorrect = choosenanswers.every(function(item,index){
return item == correctanswers[index];
});
console.log(isallcorrect);
Upvotes: 0