Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Jimmy Mannan
Jimmy Mannan
5,201 Points

Javascript quiz for times table

I am trying to make a times table quiz for my kid with my limited js knowledge(I guess that would be evident from the code below that I have patched together)

<div class="container">
  <h1>Tables</h1>
  <div id="ready"> </div>
  <div id="quiz"></div>
  <input type="text" id="ans" onkeypress="handle(event)"></input>
  <div id="feedback">Press Enter after writing your answer</div>
  <button id="subBtn">Submit</button>
  <div id="result"></div>
<div id="log"> </div>
</div>
</body>
//document.getElementById("ready").innerHTML="Ready to Practice!!";
var score = 0;
var counter;

var answer = document.getElementById('ans');
var subBtn = document.getElementById('subBtn');
var arr1 = [6,7,8,9,12,13,14,15,16,17,18,19]; // arr1[Math.floor(Math.random() * arr1.length)];
var rayanswer;


subBtn.addEventListener('click', function() {evalAnswer();}, false);
 function questions(){
 times = arr1[Math.floor(Math.random() * arr1.length)]; 
 toMult = Math.floor(Math.random() * 7) + 3;//Math.floor(Math.random()*(max-min+1)) + min; max=9, min =3
    answer.value = '';
    document.getElementById("quiz").innerHTML= "What is " + times +  " X " + toMult + " ?";
 }
questions();

for(counter =1; counter <=5; counter++) {

    function handle(e){
    if(e.keyCode === 13){
      rayanswer = parseInt(answer.value);
       counter ++;     
      if (rayanswer == times * Number(toMult)) {
        score++;
        document.getElementById('feedback').innerHTML=rayanswer + " is correcto";
      }
      else {
            document.getElementById('feedback').innerHTML=rayanswer + " is wrongesta";
      }

questions();
    }
  }

    function evalAnswer() {
    if (score >= 5){
        document.getElementById('result').innerHTML = score + "goodwork"; }
        else {
            document.getElementById('result').innerHTML= score + "keep trying";
        }
    }

after the answer is entered, I would like next question to load but I cant figure out how to do that.

2 Answers

Henrik Hansen
Henrik Hansen
23,176 Points

Right after your feedback output, you should repeat the steps where you create and output a new question. (Put those lines in a function and call that from your handler) Declare your variables in the beginning of your file, and assign it the html elements that you use in your program. It is easier to read, code and it is more efficient for memory and performance.

Jimmy Mannan
Jimmy Mannan
5,201 Points

Thanks a lot Henrik, I was at it for hours and wasnt getting anywhere, now there is some progress. "Right after your feedback output, you should repeat the steps where you create and output a new question. (Put those lines in a function and call that from your handler)" -- did this and the questions are getting refreshed. When i declared the random number vars in the beginning, they were not changing with each question so I have kept them in the function. "and assign it the html elements that you use in your program. " I am not sure what this means. Can you explain a bit please.

Now the questions are getting refreshed and scoring is also being done but the counter is not working. I think it is because the program stays in the handle loop and is not reaching the counter. When i tried to move the questions() out of the loop, new questions were not coming. If you have time to go through the updated code, any suggestions ow I can break out of the loop after every question and increase the counter. Thanks again for your help

Henrik Hansen
Henrik Hansen
23,176 Points

What I meant was that you save the elements in variables, instead of having javascript find them several times.

// first you save the element to a variable:
var feedbackDiv = document.getElemtentById("feedback");

//then you use the var in your loop or elsewhere:
for (var i = 0; i < questions.length; i++) { 
  feedbackDiv.innerHTML = "some feedback";
}

Finding elements by ID is pretty cheap compared to finding elements by tag or class, but this is still a better way to go since you don't have to use the findElement...()-function many times in your loop.

Here is one way to do it. As always, there are probably better ways.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Times Table Quiz</title>
<style type="text/css">
span.correct {
    color: blue;
}
span.wrong {
    color: red;
}
</style>
</head>

<body>
<div class="container">
  <h2>Times Table Quiz</h2>
  <div id="ready"></div>
  <div id="quiz"></div>
  <input type="text" id="answer" value=""></input>
  <div id="feedback"></div>
  <button id="subBtn">Start Over</button>
  <div id="result"></div>
<div id="log"> </div>
</div>

<script>
var score = 0;
var counter = 0;
var answer = document.getElementById('answer');
var subBtn = document.getElementById('subBtn');
var result = document.getElementById('result');
var feedback = document.getElementById('feedback');
var quiz = document.getElementById('quiz');
var rayanswer = "";
var answers = "";
var arr1 = [6,7,8,9,12,13,14,15,16,17,18,19]; 
var times;
var toMult;
var promptText = "<i>Press Enter to check answer,<br />Start Over to clear results, or<br />q to quit and show score</i>";

subBtn.addEventListener("click", function() {
    startOver();
});

answer.addEventListener("keydown", function (e) {
    if (e.keyCode === 13) {  //checks whether the pressed key is "Enter"
        evaluateAnswer();
    }
});

function showQuestion() {
    answer.value = "";
    feedback.innerHTML = promptText;
    times = arr1[Math.floor(Math.random() * arr1.length)];              
    toMult = Math.floor(Math.random() * 7) + 3;
    quiz.innerHTML= "What is " + times +  " x " + toMult + " ?";
}

function evaluateAnswer() {
    var response;
    var entry = answer.value;
    if (entry == "q") {
        quitQuiz(); 
        exit(0);
    }

    rayanswer = parseInt(entry);
    if (rayanswer == "" || rayanswer == "undefined" || rayanswer == null) {
        feedback.innerHTML = "Please enter an answer or q to quit";
    } else if (isNaN(rayanswer)) {
        feedback.innerHTML = "Please enter a number for your answer or q to quit";
    //here the next question should load after pressing enter and input box has to be blank again
    } else if (rayanswer == times * Number(toMult)) {
        score++;
        counter++;
        response ="<span class='correct'>Correct: " + times + " x " + toMult + " = " + rayanswer + "!</span>";
    } else {
        response ="<span class='wrong'>Wrong: " + times + " x " + toMult + " != " + rayanswer + ", it is " + times * toMult + "</span>";
        counter++;
    }
    answers = response + "<br />" + answers;
    result.innerHTML = answers;
    answer.value = "";
    showQuestion();
}

function startOver() {
    result.innerHTML = "";
    counter = 0;
    score = 0;
    answer.value = "";
    answer.focus();
    answers = "";
    showQuestion();
}

function quitQuiz() {
    var output = "Score: " + score + " out of " + counter + ", or " + Math.round(score / counter * 100) + "%";
    if (counter > 0) {
        if (score / counter > 0.8) {
             output += " Good work"; 
        } else {
             output += " Keep trying"; 
        }
        result.innerHTML = output + "<br />" + result.innerHTML;
    } else {
        result.innerHTML = "You haven't tried yet.";
        answer.value = "";
    }
}

showQuestion();
</script>
</body>
</html>