Adding score ++ to test questions

Hi, I`d like to add something like “you got 8 answers correct out of 10” to this code:

`


<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>Quiz with radio buttons</title>
    <style>
      label{ display: block; }
      input[type=submit]{ margin-top: 15px; }
    </style>
  </head>

  <body>
    <form>
      <div class="question">
        <p><strong>Q1</strong>: Mary is English. She was born in London</p>

        <label><input type="radio" name="one" value="a">Mary was born in England</label>
        <label><input type="radio" name="one" value="b">Mary, who is English, was born in London</label>
        <label><input type="radio" name="one" value="c">English Mary was born in London</label>
        <label><input type="radio" name="one" value="d">London Mary is English born</label>
      </div>

      <div class="question">
        <p><strong>Q2</strong>: Mary is English. She was born in London</p>

        <label><input type="radio" name="two" value="a">Mary was born in England</label>
        <label><input type="radio" name="two" value="b">Mary, who is English, was born in London</label>
        <label><input type="radio" name="two" value="c">English Mary was born in London</label>
        <label><input type="radio" name="two" value="d">London Mary is English born</label>
      </div>

      <input type="submit" />
      <input type="reset" value="Start again" />
    </form>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
      function clearAnswerImages(){
        $("img").each(function(){
          $(this).remove();
        })
      }

      function mark(el, status){
        var images = {
          correct: "http://www.littletherese.com/tick.jpg",
          incorrect: "http://www.littletherese.com/x.jpg",
          unanswered: "http://assets.altperks.com/shared/images/clickable/questionmark-15x15.gif",
        },
        img = new Image();
        img.src = images[status];
        el.append(img);
      }

      $("form").on("submit", function(e){
        e.preventDefault();
        clearAnswerImages();

        $questions = $(".question");
        $questions.each(function(){
          var answer = $(this).find("input:checked"),
              key = answer.attr("name"),
              val = answer.attr("value");

          if(answer.length === 0){
            mark($(this).find("p"), "unanswered");
          } else if (answers[key] !== val){
            mark(answer.parent(), "incorrect");   // I  changed this line
          } else {
            mark(answer.parent(), "correct");
          }
        });
      });

      $("input[type=reset]").on("click", function(){
        $("input:checked").each(function(){
          $(this).prop("checked", false);
        });

        clearAnswerImages();
      });

      var answers = {
        "one": "b",
        "two": "b"
      }
    </script>
  </body>
</html>


Thanks for any help.

Hi dubman,

You can do it like this:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>Quiz with radio buttons</title>
    <style>
      label{ display: block; }
      input[type=submit]{ margin-top: 15px; }
      #score{
        padding: 5px;
        margin: 15px 0 0 0;
      }
    </style>
  </head>

  <body>
    <form> 
      <div class="question">
        <p><strong>Q1</strong>: Mary is English. She was born in London</p>

        <label><input type="radio" name="one" value="a">Mary was born in England</label>
        <label><input type="radio" name="one" value="b">Mary, who is English, was born in London</label>
        <label><input type="radio" name="one" value="c">English Mary was born in London</label>
        <label><input type="radio" name="one" value="d">London Mary is English born</label>
      </div>

      <div class="question"> 
        <p><strong>Q2</strong>: Mary is English. She was born in London</p>

        <label><input type="radio" name="two" value="a">Mary was born in England</label>
        <label><input type="radio" name="two" value="b">Mary, who is English, was born in London</label>
        <label><input type="radio" name="two" value="c">English Mary was born in London</label>
        <label><input type="radio" name="two" value="d">London Mary is English born</label>
      </div>

      <input type="submit" />
      <input type="reset" value="Start again" /> 
    </form>

    <div id="score"></div>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script>
      function clearAnswerImages(){
        $("img").each(function(){
          $(this).remove();
        })
      }

      function mark(el, status){
        var images = {
          correct: "http://www.littletherese.com/tick.jpg",
          incorrect: "http://www.littletherese.com/x.jpg",
          unanswered: "http://assets.altperks.com/shared/images/clickable/questionmark-15x15.gif",
        }, 
        img = new Image();
        img.src = images[status];
        img.className = status;
        el.append(img);
      }

      function displayScore(){
        var numQuestions = $(".question").length,
            questionsCorrect = $("img.correct").length;

        $("#score").html("You got " + questionsCorrect + " out of " + numQuestions)
      }

      $("form").on("submit", function(e){
        e.preventDefault();
        clearAnswerImages();

        $questions = $(".question");
        $questions.each(function(){
          var answer = $(this).find("input:checked"),
              key = answer.attr("name"),
              val = answer.attr("value");

          if(answer.length === 0){ 
            mark($(this).find("p"), "unanswered");
          } else if (answers[key] !== val){
            mark(answer.parent(), "incorrect");   // I  changed this line
          } else {
            mark(answer.parent(), "correct");
          } 
        });

        displayScore()
      });

      $("input[type=reset]").on("click", function(){
        $("input:checked").each(function(){
          $(this).prop("checked", false);
        });

        clearAnswerImages();
      });

      var answers = {
        "one": "b",
        "two": "b"
      }
    </script>
  </body>
</html>

HTH

Brilliant! Thanks so much!

Sorry, one last thing. The reset button doesn’t clear the “score” field. How can I get all the fields to clear on reset? Thanks.

No probs :slight_smile:

Use the .html() method to set the div’s contents to that of an empty string.

Ok, I got it working with the last line of the code below:


$("input[type=reset]").on("click", function(){
        $("input:checked").each(function(){
          $(this).prop("checked", false);
          $('#score').empty(); //I inserted this line
        });

I ran the complete javascript code through JSHint and got a few “missing semi-colons”
one of which was after a curly brace }; I thought there shouldn’t be semi-colons after a curly brace?
I also got some “undefined variables”, but I think this isn’t a problem?

Anyway, I’m delighted with the help. Thank you!

Hi,

Yeah .empty() will do the job just as well.

Regarding the missing semi-colons: they are all valid (i.e. JSHint is correct).
The one after the curly brace is a variable declaration and is necessary.

Regarding the undefined variables:
$ - you can ignore or alternatively add this at the top of the script file:

/*global $:false */

This declares to JSHint that $ is a global variable, and the false indicates that it should not be overridden.

The missing var before $questions was a mistake. Good catch.

Sorry, I don’t know how to fix that “missing var before $questions”. Now, after updating the code, JSHint gives me 2 errors:
One undefined variable
47 $questions
48 $questions

JSHint code:


   /*global $:false */
  function clearAnswerImages(){
        $("img").each(function(){
          $(this).remove();
        });
      }

      function mark(el, status){
        var images = {
          correct: "http://www.littletherese.com/tick.jpg",
          incorrect: "http://www.littletherese.com/x.jpg",
          unanswered: "http://assets.altperks.com/shared/images/clickable/questionmark-15x15.gif",
        }, 
        img = new Image();
        img.src = images[status];
        img.className = status;
        el.append(img);
      }

      function displayScore(){
        var numQuestions = $(".question").length,
            questionsCorrect = $("img.correct").length;

        $("#score").html("You got " + questionsCorrect + " out of " + numQuestions);
      }

      $("form").on("submit", function(e){
        e.preventDefault();
        clearAnswerImages();
        
        $questions = $(".question");
        $questions.each(function(){
          var answer = $(this).find("input:checked"),
              key = answer.attr("name"),
              val = answer.attr("value");

          if(answer.length === 0){ 
            mark($(this).find("p"), "unanswered");
          } else if (answers[key] !== val){
            mark(answer.parent(), "incorrect");   // I  changed this line
          } else {
            mark(answer.parent(), "correct");
          } 
        });

        displayScore();
      });

      $("input[type=reset]").on("click", function(){
        $("input:checked").each(function(){
          $(this).prop("checked", false);
          $('#score').empty(); //I inserted this line
        });

        clearAnswerImages();
      });

      var answers = {
        "one": "b",
        "two": "b"
      };
    

That’s easy :slight_smile:
Change this:

$questions = $(".question");

To this:

var $questions = $(".question");

Done! The code is clean now in JsHint. I notice that the reset button clears answers and “score”, *but in the case that “submit” is pressed, without having answered any questions, the result is “You got 0 correct out of 10”, and in this case, pressing “reset” doesn’t clear the score message. I can understand the logic of it (I think…), but I’m wondering how reset could clear the “0 correct” message as well.
This is the clean code.



<script>
     /*global $:false */
  function clearAnswerImages(){
        $("img").each(function(){
          $(this).remove();
        });
      }
      

      function mark(el, status){
        var images = {
          correct: "http://www.littletherese.com/tick.jpg",
          incorrect: "http://www.littletherese.com/x.jpg",
          unanswered: "",
        }, 
        img = new Image();
        img.src = images[status];
        img.className = status;
        el.append(img);
      }

      function displayScore(){
        var numQuestions = $(".question").length,
            questionsCorrect = $("img.correct").length;

     $("#score").html("You got " + questionsCorrect + " out of " + numQuestions);
      }

      $("form").on("submit", function(e){
        e.preventDefault();
        clearAnswerImages(); 

       var $questions = $(".question");
        $questions.each(function(){
          var answer = $(this).find("input:checked"),
              key = answer.attr("name"),
              val = answer.attr("value");

          if(answer.length === 0){ 
            mark($(this).find("p"), "unanswered");
          } else if (answers[key] !== val){
            mark(answer.parent(), "incorrect");   // I  changed this line
          } else {
            mark(answer.parent(), "correct");
          } 
        });

        displayScore();
      });

      $("input[type=reset]").on("click", function(){
        $("input:checked").each(function(){
          $(this).prop("checked", false);
          $('#score').empty(); //I inserted this line          
        });

        clearAnswerImages(); 
      });

       var answers = { 
        "one": "b",
        "two": "c", 
        "three": "a",
        "four": "c",
        "five": "b",
        "six": "c",
        "seven": "a",
        "eight": "a",
        "nine": "b",
        "ten": "c",
                                                
      }; 
    </script>

Thanks.

Hi,

This is your click handler for the reset button:

$("input[type=reset]").on("click", function(){
  $("input:checked").each(function(){
    $(this).prop("checked", false);
    $('#score').empty();
  });

  clearAnswerImages(); 
});

You need to move the call to empty, outside of the loop to reset the checkboxes.

You can also simplify the loop to this:

$("input:checked").prop("checked", false);

which gives you:

$("input[type=reset]").on("click", function(){
  $("input:checked").prop("checked", false);
  $('#score').empty(); //I inserted this line      
  clearAnswerImages(); 
});

HTH

Also


function clearAnswerImages(){
        $("img").each(function(){
          $(this).remove();
        });
      }

could simply be


function clearAnswerImages(){
        $("img").remove();
}

Use each() only if your each-thingies are boxes or something holding many other child-thingies and you need multiple variables set for every each-thingie-box so that you can run multiple listeners/functions/cookoffs/whatever. Remember that in jQuery if you say $(‘some thing’) you’re always getting an object with a list of thingies (even if it’s a list of one), so any jQuery function you tack on to that $(‘thingie’) will automatically be done to each thingie in your list of thingies.

Thanks poes, good catch.

Thanks Pullo and Poes! It works great now!