The Dead Man
The Dead Man

Reputation: 5566

How to create quiz result's with jquery

I have a simple quiz which contains just six questions using jquery, everything works perfect,

Here is jsfiddle: quiz demo

The final result UI looks like this

enter image description here

I want the final result's checkboxes to be checked based on questions the user got it right Let's assume the user got 4 questions right the final UI should look like this

enter image description here

Here is my solution

// JavaScript Document
$(document).ready(function() {
  "use strict";

  var questions = [{
      question: "Whois usa president?",
      choices: ['Trump', 'Biden'],
      correctAnswer: 0
    }, {
      question: "What is the capital of Australia?",
      choices: ["Melbourne", "Sydney", ],
      correctAnswer: 1
    }, {
      question: "Who is the prime minister of the U.K.?",
      choices: ['Tony Blair', 'Kane'],
      correctAnswer: 0
    }, {
      question: "What is the first perfect number?",
      choices: [38, 6, 0],
      correctAnswer: 0
    },
    {
      question: "two plus 1?",
      choices: [1, 2, 3],
      correctAnswer: 1
    },
    {
      question: "Is kenyain africa?",
      choices: ['Yes', 'No'],
      correctAnswer: 0
    }
  ];

  var questionCounter = 0; //Tracks question number
  var selections = []; //Array containing user choices
  var quiz = $('.content'); //Quiz div object

  // Display initial question
  displayNext();

  // Click handler for the 'next' button
  $('#next').on('click', function(e) {
    e.preventDefault();

    // Suspend click listener during fade animation
    if (quiz.is(':animated')) {
      return false;
    }
    choose();

    // If no user selection, progress is stopped
    if (isNaN(selections[questionCounter])) {
      $('#warning').text('Please make a selection!');
    } else {
      questionCounter++;
      displayNext();
      $('#warning').text('');
    }
  });

  // Click handler for the 'prev' button
  $('#prev').on('click', function(e) {
    e.preventDefault();

    if (quiz.is(':animated')) {
      return false;
    }
    choose();
    questionCounter--;
    displayNext();
  });

  // Click handler for the 'Start Over' button
  $('#start').on('click', function(e) {
    e.preventDefault();

    if (quiz.is(':animated')) {
      return false;
    }
    questionCounter = 0;
    selections = [];
    displayNext();
    $('#start').hide();
  });

  // Creates and returns the div that contains the questions and 
  // the answer selections
  function createQuestionElement(index) {
    var qElement = $('<div>', {
      id: 'question'
    });

    var header = $('<h2>Question ' + (index + 1) + ':</h2>');
    qElement.append(header);

    var question = $('<p>').append(questions[index].question);
    qElement.append(question);

    var radioButtons = createRadios(index);
    qElement.append(radioButtons);
    // this is new
    var warningText = $('<p id="warning">');
    qElement.append(warningText);

    return qElement;

  }

  // Creates a list of the answer choices as radio inputs
  function createRadios(index) {
    var radioList = $('<ul>');
    var item;
    var input = '';
    for (var i = 0; i < questions[index].choices.length; i++) {
      item = $('<li>');
      input = '<input type="checkbox" name="answer" value=' + i + ' />';
      input += questions[index].choices[i];
      item.append(input);
      radioList.append(item);
    }
    return radioList;
  }

  // Reads the user selection and pushes the value to an array
  function choose() {
    selections[questionCounter] = +$('input[name="answer"]:checked').val();
  }

  // Displays next requested element
  function displayNext() {
    quiz.fadeOut(function() {
      $('#question').remove();

      if (questionCounter < questions.length) {
        var nextQuestion = createQuestionElement(questionCounter);
        quiz.append(nextQuestion).fadeIn();
        if (!(isNaN(selections[questionCounter]))) {
          $('input[value=' + selections[questionCounter] + ']').prop('checked', true);
        }

        // Controls display of 'prev' button
        if (questionCounter === 1) {
          $('#prev').show();
        } else if (questionCounter === 0) {

          $('#prev').hide();
          $('#next').show();
        }
      } else {
        var scoreElem = displayScore();
        quiz.append(scoreElem).fadeIn();
        $('#next').hide();
        $('#prev').hide();
        $('#start').show();
      }
    });
  }

  // Computes score and returns a paragraph element to be displayed
  function displayScore() {
    console.log(selections);
    var score = $('<h3>', {
      id: 'question'
    });
    $("#result-input").removeClass('hide-input');
    $("#result-input").addClass('show-input');
    var numCorrect = 0;
    for (var i = 0; i < selections.length; i++) {
      if (selections[i] === questions[i].correctAnswer) {
        numCorrect++;
      }
    }
    // Calculate score and display relevant message
    var percentage = numCorrect / questions.length;
    if (percentage >= 0.9) {
      score.append('Incredible! You got ' + numCorrect + ' out of ' +
        questions.length + ' questions right!');
    } else if (percentage >= 0.7) {
      score.append('Good job! You got ' + numCorrect + ' out of ' +
        questions.length + ' questions right!');
    } else if (percentage >= 0.5) {
      score.append('You got ' + numCorrect + ' out of ' +
        questions.length + ' questions right.');
    } else {
      score.append('You only got ' + numCorrect + ' out of ' +
        questions.length + ' right. Want to try again?');
    }
    return score;
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="content container-fluid" id="quiz">
  <button class="btn btn-primary" id="next">Next</button>
  <button class="btn btn-info" id="prev">Prev</button>
  <button class="btn btn-default" id="start">Start Over</button> //checkboxes inputs for the final results
  <ul id="result-input" class="hide-input">
    <li><input type="checkbox" name="answer" value="0">1</li>
    <li><input type="checkbox" name="answer" value="1">2</li>
    <li><input type="checkbox" name="answer" value="2">3</li>
    <li><input type="checkbox" name="answer" value="3">4</li>
    <li><input type="checkbox" name="answer" value="4">5</li>
    <li><input type="checkbox" name="answer" value="5">6</li>
  </ul>
</section>

What do I need to do to achieve what I want? any help or suggestions will be appreciated

Upvotes: 0

Views: 694

Answers (2)

Pianoman
Pianoman

Reputation: 58

You would have to add an else to your if statement inside the for loop. Then, inside the else statement, add a class to the checkbox $(checkbox[i]).addClass(‘wrongAnswer’);

Using CSS, you can style the checkboxes with that class .wrongAnswer to have a minus in it.

Upvotes: 0

Pianoman
Pianoman

Reputation: 58

Inside your displayScore() function, you can select the whole collection of results checkboxes and save them as a variable. Like this: var checkbox = $('#result-input li').children();

Then, inside your loop that checks to see if the answers are correct and nested inside your if statement, select a single checkbox from your collection using your iterator variable (i) and set its property to checked. Like this: $(checkbox[i]).prop('checked', true);

Here is the updated function:

  // Computes score and returns a paragraph element to be displayed
  function displayScore() {
  console.log(selections);
    var score = $('<h3>',{id: 'question'});
    $("#result-input").removeClass('hide-input');
    $("#result-input").addClass('show-input');
    var numCorrect = 0;
    // Selects collection of checkboxes
    var checkbox = $('#result-input li').children();
    for (var i = 0; i < selections.length; i++) {
      if (selections[i] === questions[i].correctAnswer) {
        numCorrect++;
        // Selects single checkbox and sets it to checked if answer is correct.
        $(checkbox[i]).prop('checked', true);
      }
    }
    // Calculate score and display relevant message
    var percentage = numCorrect / questions.length;
    if (percentage >= 0.9){
        score.append('Incredible! You got ' + numCorrect + ' out of ' +
                 questions.length + ' questions right!');
    }

    else if (percentage >= 0.7){
        score.append('Good job! You got ' + numCorrect + ' out of ' +
                 questions.length + ' questions right!');
    }

    else if (percentage >= 0.5){
        score.append('You got ' + numCorrect + ' out of ' +
                 questions.length + ' questions right.');
    }

    else {
        score.append('You only got ' + numCorrect + ' out of ' +
                 questions.length + ' right. Want to try again?');
    }
    return score;
  }
});

So really, you can achieve this with just 2 added lines of code.

Some further suggestions I would make to improve your app:

  1. For the questions, make the options radio buttons instead of checkboxes since checkboxes allow the user to select multiple questions.
  2. When user clicks "Start Over" button, hide the results checkboxes.

Upvotes: 2

Related Questions