5
\$\begingroup\$

I struggled my way through the first quiz and here are the results. Since I have some experience in jQuery I really wanted to use only vanilla JavaScript. I know the code is pretty choppy and there is most likely a lot of room for improvement.

How can I make this code more succinct? What are some better practices that i can implement?

Here is a jsfiddle.

HTML:

<div id="wrapper">
    <div id="quiz">
         <h1>How well do you know Matt</h1>
    </div>
    <input type='submit' id='myBtn' value='' />
</div>

JavaScript:

var allQuestions = [
{
    question: "What is Matt favorite color?",
    choices: ["Blue", "Black", "Yellow", "Blank", "Clear" ],
    correctAnswer: 4
},
{
    question: "Who is Matt's Favorite fiction Author?",
    choices: ["Brennan Manning", "JD Salinger", "Stephen King", "Jack Kerouac"],
    correctAnswer: 3
},
{
    question: "What is Matt's favorite food?",
    choices: ["Pizza", "Wings", "Mexican", "Rally's"],
    correctAnswer: 0
}
];

var submitBtn = document.getElementById('myBtn');
var currentQuestion = 0;
var tally = 0;

var quizForm = document.getElementById('quiz');
var question;
var choices;
var radioButtons = document.getElementsByName('radioOption');
var index = 0;

function firstFunc() {
    if (currentQuestion === 0) {
        submitBtn.value = "Start Quiz";
    }
}

function askQuestion () {
    choices = allQuestions[currentQuestion].choices;
    question = allQuestions[currentQuestion].question;
    if (currentQuestion < allQuestions.length) {
        submitBtn.value = "Next";
        quizForm.innerHTML = "<h1>" + question + "</h1>";
        for (var i = 0; i < choices.length; i++) {
            quizForm.innerHTML += "<label><input type='radio' name='radioOption' value='" + choices[i] + "'/>" + choices[i] + "</label>";
        }
        if (currentQuestion == allQuestions.length - 1) {
            submitBtn.value = "Submit";
        } else if (currentQuestion > allQuestions.length - 1) {
            calcQuiz();
        }
    }
}

function lookForChecked() {

    if (radioButtons.length > 1) {

            var checked = false;
        for (var i = 0; i < radioButtons.length; i++) {
            var selection = radioButtons[i];

             if (selection.checked) {

                var index = [i];
                if (i === allQuestions[currentQuestion].correctAnswer) {
                    tally++;

                }
                if (currentQuestion < allQuestions.length -1) {
                    currentQuestion++;

                } else {
                    console.log('you have ended the quiz');
                    calcQuiz();
                   return false;
                }
                break;
            }
        }
        if ($('input[name="radioOption"]:checked').length < 1) {
            alert('Please Make a Selection');
        }
    }
        askQuestion();
}

function calcQuiz() {
    quizForm.innerHTML = "<h1>You have finished the quiz</h1><p class='total'>You scored a total of " + tally + " out of " + allQuestions.length + "</h1>";
    submitBtn.remove();
}
window.onload = firstFunc();
submitBtn.addEventListener('click', lookForChecked);
\$\endgroup\$
6
  • \$\begingroup\$ I hope you don't mind, I changed the link to your fiddle to a forked version using the jsfiddle option for jQuery version and removing the unused html. \$\endgroup\$
    – RobH
    Jul 31, 2015 at 14:55
  • \$\begingroup\$ Totally fine. First time posting to both jsfiddle and stackexchange. I suppose that is why jQuery was not working inherently when I did not include the link/html? \$\endgroup\$ Jul 31, 2015 at 15:00
  • \$\begingroup\$ Are you sure this code works? It seems that askQuestion() isn't invoked on page load. So the first question and its options aren't displayed \$\endgroup\$
    – hindmost
    Jul 31, 2015 at 15:34
  • \$\begingroup\$ I have an event handler on submitBtn. askQuestion() is not invoked on the page load. It is not invoked until the submitBtn is clicked, which directly invokes lookForChecked(), which directly invokes askQuestion() \$\endgroup\$ Jul 31, 2015 at 15:39
  • \$\begingroup\$ Why so complex? "Start Quiz" text is only used at the start until the button is clicked. So you can put it in HTML, then it will be replaced once lookForChecked is invoked. In this case you don't need to check radioButtons.length in lookForChecked(). \$\endgroup\$
    – hindmost
    Jul 31, 2015 at 15:49

1 Answer 1

3
\$\begingroup\$

Design

You could remake this using Object-Oriented-Programming. For example, you could make a Question object, like this.

function Question(description, choices, correctChoiceIndex) {
    this.description = description;
    this.choices = choices;
    this.correctChoiceIndex = correctChoiceIndex;
}

You could then extend it with some methods, like askQuestion. For example, you could do something like this (Using prompt and alert because I'm on mobile.)

Question.prototype.askQuestion = function() {
    return prompt("Choices:\n" + this.choices.join("\n"));
}

You could then supply an additional method, checkAnswer, to see if the user got the answer correct.

Question.prototype.checkAnswer = function() {
    if(parseInt(this.askQuestion(), 10) === this.correctChoiceIndex) {
        alert("You got the question right!");
    }
    else {
        alert("Sorry, wrong answer.");
    }
}

Nitpicks

Some of your naming is not great. For example, firstFunc is an awful name for a function. It doesn't describe the purpose of the function in any way.

Preferably, names for variables/functions/classes should exhibit the following characteristics:

  • Describe the variable/function/class in detail.
  • Not have unnecessary abbreviations.
  • Not be too short.
  • Not be too long. (Unless you're programming in .)

Most of your variable names exhibit these characteristics, I just saw a few, like submitBtn that could be expanded to something like submitButton.

Moving on, I saw this line I your code:

var index = [i]; 

It isn't used anywhere in it's scope, and even if it was used, it would serve no purpose at this point.

Finally, when using the increment, ++, and decrement, -- operators, remember the differences between how they're placed.

\$\endgroup\$
1
  • \$\begingroup\$ Definitely the most exciting part of programming to me is designing Objects to connect and form a solution. \$\endgroup\$
    – insidesin
    Jul 31, 2015 at 15:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.