Akar Akar - 1 month ago 9
JSON Question

Why this number doesn't increment like it suppose to?

I'm trying to learn Javascript by creating a Quiz App like it's mentioned here: Learn Javascript Properly I have trouble trying to do the more advanced quiz, I'm using Handlebars as my templating engine. I've stored the questions in an external JSON file, and the inputs are just a bunch of radio buttons.

index.html:

<!DOCTYPE html>
<html>
<head>
<title>Quiz Application</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="container">
<div id="quiz">
</div>
<button id="next-question">Next Question</button>
</div>

<!-- Templates -->
<script id="titleTemplate" type="text/x-handlebars-template">
<div id="quiz-question">{{ title }}</div>
</script>
<script id="choicesTemplate" type="text/x-handlebars-template">
<div id="choices">
<form id="choicesForm">
{{#each choices}}
<div class="choice">
<input type="radio" name="choices" id="choice{{@index}}" value="{{ @index }}">
<label for="choice{{ @index }}" value="{{ @index }}">{{ this }}</label>
</div>
{{/each}}
</form>
</div>
</script>

<script type="text/javascript" src="js/jquery-3.1.0.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>


I've explained everything in the comments
app.js:

"use strict";
var Render = {
question: function(questions, currentIndex) {
var titleTemplate = Handlebars.compile($("#titleTemplate").html());
var choicesTemplate = Handlebars.compile($("#choicesTemplate").html());
var currentQuestion = questions[currentIndex];
Render.title(titleTemplate, currentQuestion);
Render.choices(choicesTemplate, currentQuestion);
},
title: function(titleTemplate, currentQuestion) {
$("#quiz").html(titleTemplate(currentQuestion));
},
choices: function(choicesTemplate, currentQuestion) {
$('#quiz-question').append(choicesTemplate(currentQuestion));
},
};

var Quiz = {
// Tracks the current questions
currentIndex: 0,

// The number of the correct answers
// I want to increment this when the user
// answers the correct question, for some reason it doesn't increment.
correctAnswers: 0,

// I first call this method to get the questions from JSON file
// since you can no longer have synchronous requests
getQuestions: function() {
$.getJSON('questions.json', Quiz.start);
},
// Starts the quiz
start: function(questions) {
// Check if the user is passed the last question
// in this case, if 6 > 5
if(Quiz.currentIndex + 1 > questions.length) {
Quiz.displayFinalScore(questions);
} else {
// Render the next question using the currentIndex
Render.question(questions, Quiz.currentIndex);
Quiz.handleQuestion(questions);
}
},

handleQuestion: function(questions) {
// Get's the correct answer from the JSON
var correctAnswer = questions[Quiz.currentIndex].correctAnswer;
// Check if the radio button is checked
if($("input[name=choices]:checked", "#choicesForm") == correctAnswer) {
// This doesn't increment like it suppose to
// It still stays at 0.
Quiz.correctAnswers += 1;
}

// Increment the index to change to the next question
Quiz.currentIndex += 1;
},
displayFinalScore: function(questions) {
// Simple console log
console.log("You have scored: " + Quiz.correctAnswers + " out of " + questions.length);
}
};

$(function() {
Quiz.getQuestions();
$("#next-question").on("click", Quiz.getQuestions);
})


As you can see I've explained in the comments, The problem is in incrementing the
correctAnswers
for some reason it doesn't get to the point where it compares both of the variables even if I choose the correct answer from the radio buttons.

questions.json:

[
{
"title":"When did the programming language C++ came out?",
"choices":[
1997,
1995,
2000,
1998
],
"correctAnswer":3
},
{
"title":"When Node.js came out?",
"choices":[
2010,
2011,
2009,
2006
],
"correctAnswer":2
},
{
"title":"What brand of laptop do I have?",
"choices":[
"HP",
"Acer",
"Dell",
"Lenovo"
],
"correctAnswer":0
},
{
"title":"How old am I?",
"choices":[
12,
20,
9,
16
],
"correctAnswer":3
},
{
"title":"How old is Google?",
"choices":[
12,
20,
18,
16
],
"correctAnswer":2
}
]

Answer

There are several issues with your code and they are:

  • In the start function you should change if condition expression to match array indexes, which in JavaScript are starting from 0 and the last element of array have index questions.length - 1.
  • In the start function you first render new question and then query DOM for selected element, which is already destroyed at this phase. So you need to first handleQuestion and only then render new one.
  • I also moved currentIndex increment code to the last step (after render)
  • Since handleQuestion should not be executed at the first render, I added this exotic Quiz.currentIndex && Quiz.handleQuestion(questions);, which actually means: "If currentIndex is 0, which in boolean expressions transforms to false, don't run the right part of boolean condition, which is Quiz.handleQuestion(questions)".
  • To fetch a numeric value of selected input, you should use parseInt($("input[name=choices]:checked", "#choicesForm").val(), 10)

The resulting code should look like this:

JavaScript

// Starts the quiz
start: function(questions) {
    // Check if the user is passed the last question
    // in this case, if 5 >= 5
    if(Quiz.currentIndex >= questions.length) {
        Quiz.displayFinalScore(questions);
    } else {
        Quiz.currentIndex && Quiz.handleQuestion(questions);
        // Render the next question using the currentIndex
        Render.question(questions, Quiz.currentIndex++);
    }
},

handleQuestion: function(questions) {
    // Get's the correct answer from the JSON
    var correctAnswer = questions[Quiz.currentIndex-1].correctAnswer;
    // Check if the radio button is checked
    if(parseInt($("input[name=choices]:checked", "#choicesForm").val(), 10) === correctAnswer) {
        // This doesn't increment like it suppose to
        // It still stays at 0.
        Quiz.correctAnswers +=  1;
    }
}

Live Demo

https://plnkr.co/edit/03IGvb6IZiw6QbziUpw6?p=preview

Comments