Tutorial: Easy jQuery-Based Quiz

March 16, 2012 | 7 comments

In this tutorial I’ll show you how to create your own interactive quiz using jQuery/JSON and CSS. View the demo or download the source files.

Part One: the HTML

A nested <ol>, input.submit, and p.feedback inside a div#quiz. The rel attribute of div#quiz is important, more on that later. The question <li>s have unique ids (q1, q2 etc) while the answer <li>s within each question have classes (a1, a2, etc) that are repeated per question.

<div id="quiz" rel="key">
  <ol>
    <li id="q1">At viverra sapien dignissim eget, vel tristique nibh posuere in? At viverra sapien dignissim eget, vel tristique nibh posuere in? At viverra sapien dignissim eget, vel tristique nibh posuere in?
      <ol>
        <li>
          <label>
            <input type="radio" name="q1">
            Morbi rutrum tempor nulla Morbi rutrum tempor nulla Morbi rutrum tempor nulla Morbi rutrum tempor nulla Morbi rutrum tempor nulla</label>
        </li>
        <li>
          <label>
            <input type="radio" name="q1">
            Donec congue accumsan turpis</label>
        </li>
        <li>
          <label>
            <input type="radio" name="q1">
            Mauris fermentum elit et ipsum pellentesque mattis.</label>
        </li>
      </ol>
    </li>
    <li id="q2">At tempor eros, at dignissim risusvel urna fringilla varius?
      <ol>
        <li>
          <label>
            <input type="radio" name="q2">
            Proin at eros enim</label>
        </li>
        <li>
          <label>
            <input type="radio" name="q2">
            Etiam eget diam odio</label>
        </li>
        <li>
          <label>
            <input type="radio" name="q2">
            Vestibulum viverra leo</label>
        </li>
      </ol>
    </li>
    <li id="q3">Cursus ut hendrerit turpis suscipit risus imperdiet quis adipiscing dui porttitor est sagittis vel malesuada neque pretium?
      <ol>
        <li>
          <label>
            <input type="radio" name="q3">
            Sed nec mauris id elit condimentum</label>
        </li>
        <li>
          <label>
            <input type="radio" name="q3">
            Praesent cursus lorem </label>
        </li>
        <li>
          <label>
            <input type="radio" name="q3">
            Nullam tempus velit quis</label>
        </li>
        <li>
          <label>
            <input type="radio" name="q3">
            Curabitur in tellus quis neque pulvinar faucibus.</label>
        </li>
      </ol>
    </li>
  </ol>
  <input type="button" value="Submit">
  <p class="feedback"></p>
</div>

Part Two: the JSON

Create a simple JSON file containing the answers to each question. Having this in a separate file makes the quiz scalable.

{
	"key": {
		"q1": "a3",
		"q2": "a2",
		"q3": "a1"
	}
}

Part Three: the JavaScript

First, let’s add our script tags. You can either put all your script in the HTML file or in a separate JS file.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
//Fun stuff goes here
</script>

Next, let’s set some variables. I find it’s a good idea to pull out the paths to file folders as variables, both because you might use them repeatedly, and because they might change during the course of development.

var imgpath = "images/";
var jsonpath = "json/";
var jsonfile = "";

Now we need to initialize some things in the $(document).ready() function. While creating the quiz, I soon remembered the browser’s tendency to remember the checked or disabled status of inputs even after a refresh, so let’s reset those to not checked or disabled. Let’s bind our checkQuiz() function to the click of the submit button (and prevent the default action, just in case). We’ll also grab the rel attribute value from div#quiz and put it in the jsonfile so we know we’re getting the right answer key for this particular quiz.

$(document).ready(function(){
	$("input[type='radio']").attr("disabled", false);
	$("input[type='radio']").attr("checked", false);
	$(".submit").click(function(e){
		e.preventDefault();
		checkQuiz();
	});
	jsonfile = $("#quiz").attr("rel")+".json";
});

We also need a function to get our answer key JSON file, and execute a callback once the file has finished loading (or throw an error if it fails to load). When we call the getData() function, we’ll execute all our quiz-checking logic in the callback — after all, we can’t check the quiz until we have all the answers.

function getData(update){
	$.getJSON(jsonpath+jsonfile, function(json){
		update(json);
	}).error(function(){alert("error");});
}

Now to the brains of the operation. In the checkQuiz() function, we first remove the submit button, so users don’t try to submit their answers twice. Then we call the getData() function and in the callback, execute the following:

  1. Put the answer key object from the JSON into a new object called ans and create an empty result object.
  2. Loop through the questions and populate the result object with the questions (key) and the corresponding answers the user selected (value).
  3. Also in the questions loop, use the ans object to add circle images to indicate correct answers.
  4. Still in the loop, compare the values from ans and result to see which questions were answered correctly and incorrectly and add respective classes.
  5. After the loop, build the appropriate feedback message based on the number of correctly answered questions. Show the feedback message.
function checkQuiz(){
	$(".submit").remove();
	getData(function(data){
		var ans = data.key;
		var result = {};
		$(".question").each(function(){
			var _q = $(this).attr("id");
			var _a = $("#"+_q+" input:checked").closest("li").attr("class");
			result[_q] = _a;
			$("#"+_q+" ."+ans[_q]).append("<img src='"+imgpath+"circle.png' class='png_bg' alt='correct answer'>");
			if(ans[_q]==_a){
				$(this).addClass("correct");
			}else{
				$(this).addClass("wrong");
			}
		});
		var fdbck = "You got "+$(".correct").length+" out of "+$(".question").length+" correct. "
		if($(".correct").length==0){
			fdbck += "Better luck next time.";
		}else if($(".correct").length>$(".question").length/2){
			fdbck += "Good job!";
		}else{
			fdbck += "Not bad.";
		}
		$(".feedback").text(fdbck);
		$(".feedback").show();
	});
}

Part Four: the CSS

Just a little bit of formatting and we’re good to go. It’s probably best to remove the numbers on the nested <ol>s since they distract from the affordance of the inputs. Also we need to add our correct and wrong images as backgrounds on the .correct and .wrong <li>s. And some absolute positioning on the circle image helps us to display it right over the indicated radio button.

#quiz>ol {
	padding: 0 0 10px;
	margin: 0;
}
#quiz>ol>li {
	margin: 0 0 0 20px;
}
#quiz li img {
	vertical-align: middle;
}
#quiz ol ol {
	list-style-type: none;
	margin: 0;
	padding: 8px 15px 10px 0;
}
#quiz ol ol li {
	position: relative;
	margin: 0 0 0 -4px;
	padding: 2px 0 5px 4px;
	line-height: 18px;
	clear: left;
}
#quiz ol input {
	margin: 3px 4px;
}
#quiz ol ol li img {
	position: absolute;
	left: 0;
	top: 0;
}
.correct {
	background: url(images/right.png) right center no-repeat;
}
.wrong {
	background: url(images/wrong.png) right center no-repeat;
}
.feedback {
	font-weight: bold;
	color: #006600;
	display: none;
}

And that’s all! Here are the links to the demo and source files.

7 Responses to “Tutorial: Easy jQuery-Based Quiz”

  • Von says:

    Nice tutorial, how about the json data is coming from the mysql value?

  • Karl says:

    i there i am having a issue i cant for the life of me figure out.

    The quiz is working when testing offline but when it goes to the live site a get an “error” pop up when submitting answers

    Has anyone else got this? Any help would be appreciated

  • Jemmima says:

    Hello,

    Thank you for publishing this tutorial. I am trying to build a quiz for an app I am building in Dreamweaver and I have been consulting your code to try and learn how to approach it. I am having some trouble running your source code however, nothing happens when I click the submit button. This also happens when I try to run the code independently in my browser. Do you have any pointers/advice?

    Thanks in advance,

    Jemmima

  • John says:

    If you wanted to have a single question per page, how would you go about making the modification?

  • Tracy says:

    Hey Meredith,

    Thanks for this simple and lightweight quiz. I am trying your demo and after I take the quiz and press submit – nothing happens. Could you advise as to how to make it so that there is feedback?

    Thanks!

  • Amit Rajput says:

    This is a nicely prepared article. Thanks for sharing

  • Amit Rajput says:

    Hi
    The quiz worked on local machine perfectly.
    But on server it is throwing error, when it reaches line

    $.getJSON(jsonpath + jsonfile, function (json) {

    Any suggestion?

    >> Karl,

    >>The quiz is working when testing offline but when it goes to the live >>site a get an “error” pop up when submitting answers

Leave a Reply