View Full Version : Simple Unobtrusive JavaScript Quiz
oVTech
05-17-2011, 07:09 AM
I have come upon many threads that ask about how to implement a JS quiz. Just yesterday Bullant & I were offering different options to someone. Like everything else in the world there are many ways of doing this. Nevertheless, this is how I went about it.
I should mention to the newbies out there that JS quizes aren't made for serious testing, but just for fun. Just look at the code, and you will see what I mean.
Although this example might have a little more code than some other examples, one good thing about it is that it avoids global variables and it does not include any inline javascript.
Feel free to ask any questions and to suggest changes or addons. I would also like to see how someone else would implement such thing.
Here is the whole page
NOTE: This forum adds an extra line in my getTarget function so be aware when you cut and paste. Here is the line that the forum adds: "rel="nofollow". If you seen this anywhere in my code, just take it out. I am unable to take that piece of code out.
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SIMPLE UNOBTRUSIVE QUIZ JS</title>
<style type="text/css">
body {
background: #6d6d6d;
}
#page {
width: 962px;
padding: 2px;
margin: 22px auto;
}
#q {
border: 4px solid #6299C5;
padding: 0 8px;
background: #ededed;
-moz-box-shadow:0px 1px 8px #82ccc5;
-webkit-box-shadow:0px 1px 8px #82ccc5;
box-shadow:0px 1px 8px #82ccc5;
-o-box-shadow:0px 1px 8px #82ccc5;
}
#q h4 {
padding: 4px 8px;
border-left: 4px solid #6299C5;
}
#q #results {border: 2px solid #6299C5; padding:8px; display:none;}
div.quizQ {
border-bottom: 1px solid #bcbcbc;
background: #ededed;
padding: 12px;
margin: 0;
}
div.quizQ h3 {
margin-bottom: 8px;
}
#score {
background-color: #6299C5;
border: 1px solid #cdcdcd;
padding: 8px 10px;
color: #FFFFFF;
cursor: pointer;
font-weight: bold;
}
#h {
background-color: #6299C5;
border: 3px solid #cdcdcd;
padding: 8px 10px;
color: #FFFFFF;
font-weight: bold;
-moz-box-shadow:0px 1px 8px #82ccc5;
-webkit-box-shadow:0px 1px 8px #82ccc5;
box-shadow:0px 1px 8px #82ccc5;
-o-box-shadow:0px 1px 8px #82ccc5;
}
#c {
width: 777px;
border:1px solid #bebebe;
padding:6px;margin:0;
color:#dfdfdf;
font-family: "Courier New", Courier, monospace;
font-weight:bold;
font-style: italic;
}
</style>
<script type="text/javascript">
/* <![CDATA[ */
/*
-I am not putting a copyright on this, but I will
appreciate it if you left my nickname in the created by...
*/
///Simple-Unobtrusive-Quiz-JS created by oVTech
var Quiz = {
addEvent: function( elm, evType, fn ) {//(required)
if (elm.addEventListener) {
elm.addEventListener(evType, fn, false);
} else if (elm.attachEvent) {
elm.attachEvent('on' + evType, fn);
} else {
elm['on' + evType] = fn;
}
},
getTarget: function( e ) {//(required)
var target = window.event ? window.event.srcElement : e ? e.target : null;
if (!target){return false;}
while(target.nodeType!=1 && target.nodeName.toLowerCase()!='body'){
target=target.parentNode;
}
return target;
},
//Start Quiz
answers: [],
correctAnswers: ["a", "b", "c", "c", "a"],
initQuiz: function () {
var arrInp = document.getElementsByTagName('input');
Quiz.scoreIt = document.getElementById('score')
for (var i=0; i<arrInp.length; i++) {
if (arrInp[i].type.toLowerCase() == "radio") {
Quiz.addEvent( arrInp[i], 'click', Quiz.getAnswer);
}
}
},
getAnswer: function (e) {
var thisRadio = Quiz.getTarget(e);
var which = thisRadio.getAttribute("rel");
var val = thisRadio.getAttribute("value");
var group = thisRadio.getAttribute("name");
Quiz.recordAnswer( which, val, group )
},
recordAnswer: function (question, userAnswer, groupName) {
Quiz.answers[question] = userAnswer;
},
scoreQuiz: function () {
var totalCorrect = 0;
var totalIncorrect = 0;
var incorrect = [];
Quiz.f = document.getElementById('quizForm');
var els = Quiz.f.elements;
var quizWrap = document.getElementById('q');
var outputResults = document.getElementById('results');
for (var i = 0; i<Quiz.correctAnswers.length; ++i) {
if (Quiz.answers[i] == Quiz.correctAnswers[i]) {
++totalCorrect;
quizWrap.getElementsByTagName('h4')[i].style.backgroundColor = "#00CC33";
}
else {
++totalIncorrect;
quizWrap.getElementsByTagName('h4')[i].style.backgroundColor = "#FF0000";
}
}
outputResults.style.display = "block";
outputResults.innerHTML = "You scored " + totalCorrect + " out of " + Quiz.correctAnswers.length;
outputResults.innerHTML += ", which is " + Math.round(totalCorrect/Quiz.correctAnswers.length * 100) + "%.";
outputResults.innerHTML += "<br/>";
outputResults.innerHTML += "Total incorrect answers: " + totalIncorrect;
for ( var c=-1, k; k=els[++c]; ) {
if (els[c].type == 'radio') {
k.disabled = true;//(good idea to have this)
}
}
Quiz.scoreIt.disabled = true; //(required - without it bugs will crawl all over you)
Quiz.scoreIt.style.backgroundColor = "#92bbC5";
}
};
function loadEvnts() {
Quiz.initQuiz();
var scoreIt = document.getElementById('score');
Quiz.addEvent( scoreIt, 'click', Quiz.scoreQuiz);
}
Quiz.addEvent( window, 'load', loadEvnts);
/* ]]> */
</script>
</head>
<body>
<form action="#" method="post" id="quizForm">
<div id="page">
<h3 id="h">Simple Unobtrusive Javascript Quiz ... <em>by oVTech</em></h3>
<div id="q">
<p style="font-family: 'Courier New'; border-bottom: 1px dashed #888; margin: 4px;padding: 8px;">
<strong><u>Quick Notes:</u></strong> <br />
- Percentages are rounded up with round() - optionally you can use toFixed(1)<br />
- if you leave a radio button blank, then it counts as a wrong answer<br />
- After submition, radio buttons & submit button are disabled<br />
- Red & green colors let you know which questions you got incorrect and which ones correct<br />
- There is a results div at the end of the page<br />
</p>
<div class="quizQ">
<h4>1. Inside which HTML tag do we put JavaScript code?</h4>
<input type="radio" rel="0" value="a" name="grp0"/> <script> <br /> <!--Correct Answer: A-->
<input type="radio" rel="0" value="b" name="grp0"/> <javascript> <br />
<input type="radio" rel="0" value="c" name="grp0"/> <jscript> <br />
</div>
<div class="quizQ">
<h4>2. What is the correct syntax for referring to an external script called "xxx.js"?</h4>
<input type="radio" rel="1" value="a" name="grp1"/> <script type="text/javascript" href="xxx.js"> <br />
<input type="radio" rel="1" value="b" name="grp1"/> <script type="text/javascript" src="xxx.js"> <br /> <!--Correct Answer: B-->
<input type="radio" rel="1" value="c" name="grp1"/> <script type="text/javascript" name="xxx.js"> <br />
</div>
<div class="quizQ">
<h4>3. The external JavaScript file must contain the <script> tag.</h4>
<input type="radio" rel="2" value="a" name="grp2"/> True <br />
<input type="radio" rel="2" value="b" name="grp2"/> It is optional <br />
<input type="radio" rel="2" value="c" name="grp2"/> False <br /> <!--Correct Answer: C-->
</div>
<div class="quizQ">
<h4>4. How do you create a function?</h4>
<input type="radio" rel="3" value="a" name="grp3"/> function:fn()<br />
<input type="radio" rel="3" value="b" name="grp3"/> function=fn()<br />
<input type="radio" rel="3" value="c" name="grp3"/> function fn()<br /> <!--Correct Answer: C-->
</div>
<div class="quizQ">
<h4>5. How do you write a conditional statement for executing some code if "k" is NOT equal to 5?</h4>
<input type="radio" rel="4" value="a" name="grp4"/> if (k != 5)<br /> <!--Correct Answer: C-->
<input type="radio" rel="4" value="b" name="grp4"/> if(i = 5) <br />
<input type="radio" rel="4" value="c" name="grp4"/> if (i = !5)<br />
</div>
<div style="padding:8px 2px;background:#ededed;">
<br />
<input type ="button" id="score" value="Score Quiz" />
<br /><br />
<div id="results"></div>
</div>
</div>
<br />
<p id="c">
<strong> - </strong>Copyright (c) nobody 2010 -> until 11111100100.<br />
<strong> - </strong>Simple Unobtrusive JS Quiz created by <strong> - </strong> <em>oVTech.</em>
</p>
<br /> <br />
</div>
</form>
</body>
</html>
bullant
05-17-2011, 07:36 AM
Feel free to ask any questions and to suggest changes or addons. I would also like to see how someone else would implement such thing.
Yep agree that this would normally all be done server side in the "real world" but I guess it is a common assignment for students learning javascript.
Anyway just some food for thought:
1) In general, I like to code with the view of trying to keep future maintenance down to a minimum. Hence I would prefer to put all the questions and answers in an array and then create the html dynamically. I wouldn't want to have to edit the html manually every time the questions and answers change.
2) To increase useability I would have all the questions' options in a <label> so the user can click either the radio button or the text associated with it to select that answer.
Also, I copied and pasted your code into a html file and nothing happens when I click the "Score quiz" button in both IE9 and FF4.
Below is the demo (with a bonus question in the questions array :)) I posted in the other thread you referred to. It doesn't include inline scripting either.
Each row in the questions array contains the data for each question in the quiz. The first element in each row is the question itself. The second element is the option number for the correct answer to the question. The remaining elements are the options for that question.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title></title>
<style type="text/css">
fieldset {
width: 30%;
border: 1px solid green;
}
fieldset label {
display: block;
}
</style>
<script type="text/javascript">
var questions = [
['What colour is the sun?','1','Yellow','Green','Blue'],
['What is 2 x 3?','2',5,6,7,8],
['What is the 3rd letter in Codingforums','3','z','r','d','a','t']
];
function checkAnswers(){
var numCorrectAnswers = 0;
for(var i=0; i < questions.length; i++){
var radBtnsO = document.getElementsByName('q'+(i+1));
disableRadButtons(radBtnsO);
if(getAnswer(radBtnsO) == questions[i][1]){
++numCorrectAnswers;
radBtnsO[0].parentNode.parentNode.firstChild.style.backgroundColor = 'green';
} else {
radBtnsO[0].parentNode.parentNode.firstChild.style.backgroundColor = 'red';
}
}
alert('Total correct answers = '+numCorrectAnswers);
}
function getAnswer(radBtnsO){
for(var i=0; i < radBtnsO.length; i++){
if(radBtnsO[i].checked){return radBtnsO[i].value;}
}
return false;
}
function disableRadButtons(radBtnsO){
for(var i=0; i < radBtnsO.length; i++){
radBtnsO[i].disabled = true;
}
}
window.onload=function(){
fldQuestionsO = document.getElementById('fldQuestions');
for(i=0; i < questions.length; i++){
var newDiv = document.createElement('div');
var newPara = document.createElement('p');
newPara.appendChild(document.createTextNode('Q'+(i+1)+' '+questions[i][0]));
newDiv.appendChild(newPara);
//create the radio buttons for each question
var radValue = 1;
for(j=2; j < questions[i].length; j++) {
var newLabel = document.createElement('label');
var newRadBtn = document.createElement('input');
newRadBtn.setAttribute('type', 'radio');
newRadBtn.setAttribute('name', 'q'+(i+1));
newRadBtn.setAttribute('value', radValue++);
newLabel.appendChild(newRadBtn);
newLabel.appendChild(document.createTextNode(questions[i][j]));
newDiv.appendChild(newLabel);
}
fldQuestionsO.appendChild(newDiv);
}
document.getElementById('btnSubmit').onclick=checkAnswers;
}
</script>
</head>
<body>
<div>
<fieldset id="fldQuestions"></fieldset>
<button id="btnSubmit">Submit</button>
</div>
</body>
</html>
mllanapatriciac
05-17-2011, 11:51 AM
I have come upon many threads that ask about how to implement a JS quiz. Just yesterday Bullant & I were offering different options to someone. Like everything else in the world there are many ways of doing this. Nevertheless, this is how I went about it.
I should mention to the newbies out there that JS quizes aren't made for serious testing, but just for fun. Just look at the code, and you will see what I mean.
Although this example might have a little more code than some other examples, one good thing about it is that it avoids global variables and it does not include any inline javascript.
Feel free to ask any questions and to suggest changes or addons. I would also like to see how someone else would implement such thing.
Here is the whole page:
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SIMPLE UNOBTRUSIVE QUIZ JS</title>
<style type="text/css">
body {
background: #6d6d6d;
}
#page {
width: 962px;
padding: 2px;
margin: 22px auto;
}
#q {
border: 4px solid #6299C5;
padding: 0 8px;
background: #ededed;
-moz-box-shadow:0px 1px 8px #82ccc5;
-webkit-box-shadow:0px 1px 8px #82ccc5;
box-shadow:0px 1px 8px #82ccc5;
-o-box-shadow:0px 1px 8px #82ccc5;
}
#q h4 {
padding: 4px 8px;
border-left: 4px solid #6299C5;
}
#q #results {border: 2px solid #6299C5; padding:8px; display:none;}
div.quizQ {
border-bottom: 1px solid #bcbcbc;
background: #ededed;
padding: 12px;
margin: 0;
}
div.quizQ h3 {
margin-bottom: 8px;
}
#score {
background-color: #6299C5;
border: 1px solid #cdcdcd;
padding: 8px 10px;
color: #FFFFFF;
cursor: pointer;
font-weight: bold;
}
#h {
background-color: #6299C5;
border: 3px solid #cdcdcd;
padding: 8px 10px;
color: #FFFFFF;
font-weight: bold;
-moz-box-shadow:0px 1px 8px #82ccc5;
-webkit-box-shadow:0px 1px 8px #82ccc5;
box-shadow:0px 1px 8px #82ccc5;
-o-box-shadow:0px 1px 8px #82ccc5;
}
#c {
width: 777px;
border:1px solid #bebebe;
padding:6px;margin:0;
color:#dfdfdf;
font-family: "Courier New", Courier, monospace;
font-weight:bold;
font-style: italic;
}
</style>
<script type="text/javascript">
/* <![CDATA[ */
/*
-I am not putting a copyright on this, but I will
appreciate it if you left my nickname in the created by...
*/
///Simple-Unobtrusive-Quiz-JS created by oVTech
var Quiz = {
addEvent: function( elm, evType, fn ) {//(required)
if (elm.addEventListener) {
elm.addEventListener(evType, fn, false);
} else if (elm.attachEvent) {
elm.attachEvent('on' + evType, fn);
} else {
elm['on' + evType] = fn;
}
},
getTarget: function( e ) {//(required)
var target = window.event ? window.event.srcElement : e ? e.target : null;
if (!target){return false;}
while(target.nodeType!=1 && target.nodeName.toLowerCase()!='body'){
target=target.parentNode;
}
return target;
},
//Start Quiz
answers: [],
correctAnswers: ["a", "b", "c", "c", "a"],
initQuiz: function () {
var arrInp = document.getElementsByTagName('input');
Quiz.scoreIt = document.getElementById('score')
for (var i=0; i<arrInp.length; i++) {
if (arrInp[i].type.toLowerCase() == "radio") {
Quiz.addEvent( arrInp[i], 'click', Quiz.getAnswer);
}
}
},
getAnswer: function (e) {
var thisRadio = Quiz.getTarget(e);
var which = thisRadio.getAttribute("rel");
var val = thisRadio.getAttribute("value");
var group = thisRadio.getAttribute("name");
Quiz.recordAnswer( which, val, group )
},
recordAnswer: function (question, userAnswer, groupName) {
Quiz.answers[question] = userAnswer;
},
scoreQuiz: function () {
var totalCorrect = 0;
var totalIncorrect = 0;
var incorrect = [];
Quiz.f = document.getElementById('quizForm');
var els = Quiz.f.elements;
var quizWrap = document.getElementById('q');
var outputResults = document.getElementById('results');
for (var i = 0; i<Quiz.correctAnswers.length; ++i) {
if (Quiz.answers[i] == Quiz.correctAnswers[i]) {
++totalCorrect;
quizWrap.getElementsByTagName('h4')[i].style.backgroundColor = "#00CC33";
}
else {
++totalIncorrect;
quizWrap.getElementsByTagName('h4')[i].style.backgroundColor = "#FF0000";
}
}
outputResults.style.display = "block";
outputResults.innerHTML = "You scored " + totalCorrect + " out of " + Quiz.correctAnswers.length;
outputResults.innerHTML += ", which is " + Math.round(totalCorrect/Quiz.correctAnswers.length * 100) + "%.";
outputResults.innerHTML += "<br/>";
outputResults.innerHTML += "Total incorrect answers: " + totalIncorrect;
for ( var c=-1, k; k=els[++c]; ) {
if (els[c].type == 'radio') {
k.disabled = true;//(good idea to have this)
}
}
Quiz.scoreIt.disabled = true; //(required - without it bugs will crawl all over you)
Quiz.scoreIt.style.backgroundColor = "#92bbC5";
}
};
function loadEvnts() {
Quiz.initQuiz();
var scoreIt = document.getElementById('score');
Quiz.addEvent( scoreIt, 'click', Quiz.scoreQuiz);
}
Quiz.addEvent( window, 'load', loadEvnts);
/* ]]> */
</script>
</head>
<body>
<form action="#" method="post" id="quizForm">
<div id="page">
<h3 id="h">Simple Unobtrusive Javascript Quiz ... <em>by oVTech</em></h3>
<div id="q">
<p style="font-family: 'Courier New'; border-bottom: 1px dashed #888; margin: 4px;padding: 8px;">
<strong><u>Quick Notes:</u></strong> <br />
- Percentages are rounded up with round() - optionally you can use toFixed(1)<br />
- if you leave a radio button blank, then it counts as a wrong answer<br />
- After submition, the radio buttons & the submit button are disabled<br />
- Red & green colors let you know which questions you got incorrect and which ones correct<br />
- There is a results div at the end of the page with more information<br />
</p>
<div class="quizQ">
<h4>1. Inside which HTML tag do we put JavaScript code?</h4>
<input type="radio" rel="0" value="a" name="grp0"/> <script> <br /> <!--Correct Answer: A-->
<input type="radio" rel="0" value="b" name="grp0"/> <javascript> <br />
<input type="radio" rel="0" value="c" name="grp0"/> <jscript> <br />
</div>
<div class="quizQ">
<h4>2. What is the correct syntax for referring to an external script called "xxx.js"?</h4>
<input type="radio" rel="1" value="a" name="grp1"/> <script type="text/javascript" href="xxx.js"> <br />
<input type="radio" rel="1" value="b" name="grp1"/> <script type="text/javascript" src="xxx.js"> <br /> <!--Correct Answer: B-->
<input type="radio" rel="1" value="c" name="grp1"/> <script type="text/javascript" name="xxx.js"> <br />
</div>
<div class="quizQ">
<h4>3. The external JavaScript file must contain the <script> tag.</h4>
<input type="radio" rel="2" value="a" name="grp2"/> True <br />
<input type="radio" rel="2" value="b" name="grp2"/> It is optional <br />
<input type="radio" rel="2" value="c" name="grp2"/> False <br /> <!--Correct Answer: C-->
</div>
<div class="quizQ">
<h4>4. How do you create a function?</h4>
<input type="radio" rel="3" value="a" name="grp3"/> function:fn()<br />
<input type="radio" rel="3" value="b" name="grp3"/> function=fn()<br />
<input type="radio" rel="3" value="c" name="grp3"/> function fn()<br /> <!--Correct Answer: C-->
</div>
<div class="quizQ">
<h4>5. How do you write a conditional statement for executing some code if "k" is NOT equal to 5?</h4>
<input type="radio" rel="4" value="a" name="grp4"/> if (k != 5)<br /> <!--Correct Answer: C-->
<input type="radio" rel="4" value="b" name="grp4"/> if(i = 5) <br />
<input type="radio" rel="4" value="c" name="grp4"/> if (i = !5)<br />
</div>
<div style="padding:8px 2px;background:#ededed;">
<br />
<input type ="button" id="score" value="Score Quiz" />
<br /><br />
<div id="results"></div>
</div>
</div>
<br />
<p id="c">
<strong> - </strong>Copyright (c) nobody 2010 -> until 11111100100.<br />
<strong> - </strong>Simple Unobtrusive JS Quiz created by <strong> - </strong> <em>oVTech.</em>
</p>
<br /> <br />
</div>
</form>
</body>
</html>
Thank you very very very much! :) :thumbsup::D
mllanapatriciac
05-17-2011, 11:52 AM
Yep agree that this would normally all be done server side in the "real world" but I guess it is a common assignment for students learning javascript.
Anyway just some food for thought:
1) In general, I like to code with the view of trying to keep future maintenance down to a minimum. Hence I would prefer to put all the questions and answers in an array and then create the html dynamically. I wouldn't want to have to edit the html manually every time the questions and answers change.
2) To increase useability I would have all the questions' options in a <label> so the user can click either the radio button or the text associated with it to select that answer.
Also, I copied and pasted your code into a html file and nothing happens when I click the "Score quiz" button in both IE9 and FF4.
Below is the demo (with a bonus question in the questions array :)) I posted in the other thread you referred to. It doesn't include inline scripting either.
Each row in the questions array contains the data for each question in the quiz. The first element in each row is the question itself. The second element is the option number for the correct answer to the question. The remaining elements are the options for that question.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title></title>
<style type="text/css">
fieldset {
width: 30%;
border: 1px solid green;
}
fieldset label {
display: block;
}
</style>
<script type="text/javascript">
var questions = [
['What colour is the sun?','1','Yellow','Green','Blue'],
['What is 2 x 3?','2',5,6,7,8],
['What is the 3rd letter in Codingforums','3','z','r','d','a','t']
];
function checkAnswers(){
var numCorrectAnswers = 0;
for(var i=0; i < questions.length; i++){
var radBtnsO = document.getElementsByName('q'+(i+1));
disableRadButtons(radBtnsO);
if(getAnswer(radBtnsO) == questions[i][1]){
++numCorrectAnswers;
radBtnsO[0].parentNode.parentNode.firstChild.style.backgroundColor = 'green';
} else {
radBtnsO[0].parentNode.parentNode.firstChild.style.backgroundColor = 'red';
}
}
alert('Total correct answers = '+numCorrectAnswers);
}
function getAnswer(radBtnsO){
for(var i=0; i < radBtnsO.length; i++){
if(radBtnsO[i].checked){return radBtnsO[i].value;}
}
return false;
}
function disableRadButtons(radBtnsO){
for(var i=0; i < radBtnsO.length; i++){
radBtnsO[i].disabled = true;
}
}
window.onload=function(){
fldQuestionsO = document.getElementById('fldQuestions');
for(i=0; i < questions.length; i++){
var newDiv = document.createElement('div');
var newPara = document.createElement('p');
newPara.appendChild(document.createTextNode('Q'+(i+1)+' '+questions[i][0]));
newDiv.appendChild(newPara);
//create the radio buttons for each question
var radValue = 1;
for(j=2; j < questions[i].length; j++) {
var newLabel = document.createElement('label');
var newRadBtn = document.createElement('input');
newRadBtn.setAttribute('type', 'radio');
newRadBtn.setAttribute('name', 'q'+(i+1));
newRadBtn.setAttribute('value', radValue++);
newLabel.appendChild(newRadBtn);
newLabel.appendChild(document.createTextNode(questions[i][j]));
newDiv.appendChild(newLabel);
}
fldQuestionsO.appendChild(newDiv);
}
document.getElementById('btnSubmit').onclick=checkAnswers;
}
</script>
</head>
<body>
<div>
<fieldset id="fldQuestions"></fieldset>
<button id="btnSubmit">Submit</button>
</div>
</body>
</html>
Thank you, your help is very much appreciated. :D:):thumbsup::thumbsup:
bullant
05-17-2011, 12:03 PM
you're welcome :)
AndrewGSW
05-17-2011, 02:12 PM
Interesting, thank you :thumbsup:
Of course, I cheated
alert(Quiz.correctAnswers.join(','));
Could move the correctAnswers array into the scoreQuiz method as a private member variable
scoreQuiz: function () {
var totalCorrect = 0;
var totalIncorrect = 0;
var correctAnswers = ["a", "b", "c", "c", "a"];
var incorrect = [];
Quiz.f = document.getElementById('quizForm');
var els = Quiz.f.elements;
var quizWrap = document.getElementById('q');
var outputResults = document.getElementById('results');
for (var i = 0; i<correctAnswers.length; ++i) {
if (Quiz.answers[i] == correctAnswers[i]) {
but I only mention this out of academic interest :)
oVTech
05-17-2011, 02:45 PM
Also, I copied and pasted your code into a html file and nothing happens when I click the "Score quiz" button in both IE9 and FF4.
Bullant, for some reason when I paste the code here, this forums adds this line in my getTarget function: "rel="nofollow" . If you remove that line then it should work. I have tested in FF4, IE8 & Chrome.
If you see something else, please let me know! Thanks for the input.
oVTech
05-17-2011, 02:57 PM
2) To increase useability I would have all the questions' options in a <label> so the user can click either the radio button or the text associated with it to select that answer.
Yes, I definitely like this one :thumbsup: - Thanks!
bullant
05-17-2011, 02:59 PM
Bullant, for some reason when I paste the code here, this forums adds this line in my getTarget function: "rel="nofollow" . If you remove that line then it should work. I have tested in FF4, IE8 & Chrome.
If you see something else, please let me know! Thanks for the input.
hmmm....that's weird, it adding that extra bit of code :confused::confused:
It could be something to do with the editor you are using to write your code.
Anyway, yep, removing that extra code allows your code to work in IE9 as well. :)
oVTech
05-17-2011, 02:59 PM
Interesting, thank you :thumbsup:
Of course, I cheated
alert(Quiz.correctAnswers.join(','));
Could move the correctAnswers array into the scoreQuiz method as a private member variable
Why not! Sure... adding the correctAnswers array into the scoreQuiz method makes sense. Thanks for the input!
oVTech
05-17-2011, 03:05 PM
hmmm....that's weird, it adding that extra bit of code :confused::confused:
It could be something to do with the editor you are using to write your code.
Anyway, yep, removing that extra code allows your code to work in IE9 as well. :)
Actually I am using Notepad++ and the extra code isn't included in my code even after it is saved as an HTML file. I think this forum's editor adds this to prevent "follow" links - you know... for SEO purposes. I can't take it out because when I paste my code into this forum's editor, the "rel="nofollow" thing isn't there, but after I have saved the thread then it shows up. Anyway, thanks for the input.
bullant
05-18-2011, 12:12 AM
no problem :)
I wasn't saying your editor inserts that code, but there might be something in your code (visible or embedded) that causes the forum to add that code when you paste it in a thread.
I copy and paste code into threads often from either HTML-Kit or Netbeans and then edit it and I haven't experienced code being added to my posted coded.
mllanapatriciac
05-18-2011, 12:47 AM
I have come upon many threads that ask about how to implement a JS quiz. Just yesterday Bullant & I were offering different options to someone. Like everything else in the world there are many ways of doing this. Nevertheless, this is how I went about it.
I should mention to the newbies out there that JS quizes aren't made for serious testing, but just for fun. Just look at the code, and you will see what I mean.
Although this example might have a little more code than some other examples, one good thing about it is that it avoids global variables and it does not include any inline javascript.
Feel free to ask any questions and to suggest changes or addons. I would also like to see how someone else would implement such thing.
Here is the whole page
NOTE: This forum adds an extra line in my getTarget function so be aware when you cut and paste. Here is the line that the forum adds: "rel="nofollow". If you seen this anywhere in my code, just take it out. I am unable to take that piece of code out.
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SIMPLE UNOBTRUSIVE QUIZ JS</title>
<style type="text/css">
body {
background: #6d6d6d;
}
#page {
width: 962px;
padding: 2px;
margin: 22px auto;
}
#q {
border: 4px solid #6299C5;
padding: 0 8px;
background: #ededed;
-moz-box-shadow:0px 1px 8px #82ccc5;
-webkit-box-shadow:0px 1px 8px #82ccc5;
box-shadow:0px 1px 8px #82ccc5;
-o-box-shadow:0px 1px 8px #82ccc5;
}
#q h4 {
padding: 4px 8px;
border-left: 4px solid #6299C5;
}
#q #results {border: 2px solid #6299C5; padding:8px; display:none;}
div.quizQ {
border-bottom: 1px solid #bcbcbc;
background: #ededed;
padding: 12px;
margin: 0;
}
div.quizQ h3 {
margin-bottom: 8px;
}
#score {
background-color: #6299C5;
border: 1px solid #cdcdcd;
padding: 8px 10px;
color: #FFFFFF;
cursor: pointer;
font-weight: bold;
}
#h {
background-color: #6299C5;
border: 3px solid #cdcdcd;
padding: 8px 10px;
color: #FFFFFF;
font-weight: bold;
-moz-box-shadow:0px 1px 8px #82ccc5;
-webkit-box-shadow:0px 1px 8px #82ccc5;
box-shadow:0px 1px 8px #82ccc5;
-o-box-shadow:0px 1px 8px #82ccc5;
}
#c {
width: 777px;
border:1px solid #bebebe;
padding:6px;margin:0;
color:#dfdfdf;
font-family: "Courier New", Courier, monospace;
font-weight:bold;
font-style: italic;
}
</style>
<script type="text/javascript">
/* <![CDATA[ */
/*
-I am not putting a copyright on this, but I will
appreciate it if you left my nickname in the created by...
*/
///Simple-Unobtrusive-Quiz-JS created by oVTech
var Quiz = {
addEvent: function( elm, evType, fn ) {//(required)
if (elm.addEventListener) {
elm.addEventListener(evType, fn, false);
} else if (elm.attachEvent) {
elm.attachEvent('on' + evType, fn);
} else {
elm['on' + evType] = fn;
}
},
getTarget: function( e ) {//(required)
var target = window.event ? window.event.srcElement : e ? e.target : null;
if (!target){return false;}
while(target.nodeType!=1 && target.nodeName.toLowerCase()!='body'){
target=target.parentNode;
}
return target;
},
//Start Quiz
answers: [],
correctAnswers: ["a", "b", "c", "c", "a"],
initQuiz: function () {
var arrInp = document.getElementsByTagName('input');
Quiz.scoreIt = document.getElementById('score')
for (var i=0; i<arrInp.length; i++) {
if (arrInp[i].type.toLowerCase() == "radio") {
Quiz.addEvent( arrInp[i], 'click', Quiz.getAnswer);
}
}
},
getAnswer: function (e) {
var thisRadio = Quiz.getTarget(e);
var which = thisRadio.getAttribute("rel");
var val = thisRadio.getAttribute("value");
var group = thisRadio.getAttribute("name");
Quiz.recordAnswer( which, val, group )
},
recordAnswer: function (question, userAnswer, groupName) {
Quiz.answers[question] = userAnswer;
},
scoreQuiz: function () {
var totalCorrect = 0;
var totalIncorrect = 0;
var incorrect = [];
Quiz.f = document.getElementById('quizForm');
var els = Quiz.f.elements;
var quizWrap = document.getElementById('q');
var outputResults = document.getElementById('results');
for (var i = 0; i<Quiz.correctAnswers.length; ++i) {
if (Quiz.answers[i] == Quiz.correctAnswers[i]) {
++totalCorrect;
quizWrap.getElementsByTagName('h4')[i].style.backgroundColor = "#00CC33";
}
else {
++totalIncorrect;
quizWrap.getElementsByTagName('h4')[i].style.backgroundColor = "#FF0000";
}
}
outputResults.style.display = "block";
outputResults.innerHTML = "You scored " + totalCorrect + " out of " + Quiz.correctAnswers.length;
outputResults.innerHTML += ", which is " + Math.round(totalCorrect/Quiz.correctAnswers.length * 100) + "%.";
outputResults.innerHTML += "<br/>";
outputResults.innerHTML += "Total incorrect answers: " + totalIncorrect;
for ( var c=-1, k; k=els[++c]; ) {
if (els[c].type == 'radio') {
k.disabled = true;//(good idea to have this)
}
}
Quiz.scoreIt.disabled = true; //(required - without it bugs will crawl all over you)
Quiz.scoreIt.style.backgroundColor = "#92bbC5";
}
};
function loadEvnts() {
Quiz.initQuiz();
var scoreIt = document.getElementById('score');
Quiz.addEvent( scoreIt, 'click', Quiz.scoreQuiz);
}
Quiz.addEvent( window, 'load', loadEvnts);
/* ]]> */
</script>
</head>
<body>
<form action="#" method="post" id="quizForm">
<div id="page">
<h3 id="h">Simple Unobtrusive Javascript Quiz ... <em>by oVTech</em></h3>
<div id="q">
<p style="font-family: 'Courier New'; border-bottom: 1px dashed #888; margin: 4px;padding: 8px;">
<strong><u>Quick Notes:</u></strong> <br />
- Percentages are rounded up with round() - optionally you can use toFixed(1)<br />
- if you leave a radio button blank, then it counts as a wrong answer<br />
- After submition, radio buttons & submit button are disabled<br />
- Red & green colors let you know which questions you got incorrect and which ones correct<br />
- There is a results div at the end of the page<br />
</p>
<div class="quizQ">
<h4>1. Inside which HTML tag do we put JavaScript code?</h4>
<input type="radio" rel="0" value="a" name="grp0"/> <script> <br /> <!--Correct Answer: A-->
<input type="radio" rel="0" value="b" name="grp0"/> <javascript> <br />
<input type="radio" rel="0" value="c" name="grp0"/> <jscript> <br />
</div>
<div class="quizQ">
<h4>2. What is the correct syntax for referring to an external script called "xxx.js"?</h4>
<input type="radio" rel="1" value="a" name="grp1"/> <script type="text/javascript" href="xxx.js"> <br />
<input type="radio" rel="1" value="b" name="grp1"/> <script type="text/javascript" src="xxx.js"> <br /> <!--Correct Answer: B-->
<input type="radio" rel="1" value="c" name="grp1"/> <script type="text/javascript" name="xxx.js"> <br />
</div>
<div class="quizQ">
<h4>3. The external JavaScript file must contain the <script> tag.</h4>
<input type="radio" rel="2" value="a" name="grp2"/> True <br />
<input type="radio" rel="2" value="b" name="grp2"/> It is optional <br />
<input type="radio" rel="2" value="c" name="grp2"/> False <br /> <!--Correct Answer: C-->
</div>
<div class="quizQ">
<h4>4. How do you create a function?</h4>
<input type="radio" rel="3" value="a" name="grp3"/> function:fn()<br />
<input type="radio" rel="3" value="b" name="grp3"/> function=fn()<br />
<input type="radio" rel="3" value="c" name="grp3"/> function fn()<br /> <!--Correct Answer: C-->
</div>
<div class="quizQ">
<h4>5. How do you write a conditional statement for executing some code if "k" is NOT equal to 5?</h4>
<input type="radio" rel="4" value="a" name="grp4"/> if (k != 5)<br /> <!--Correct Answer: C-->
<input type="radio" rel="4" value="b" name="grp4"/> if(i = 5) <br />
<input type="radio" rel="4" value="c" name="grp4"/> if (i = !5)<br />
</div>
<div style="padding:8px 2px;background:#ededed;">
<br />
<input type ="button" id="score" value="Score Quiz" />
<br /><br />
<div id="results"></div>
</div>
</div>
<br />
<p id="c">
<strong> - </strong>Copyright (c) nobody 2010 -> until 11111100100.<br />
<strong> - </strong>Simple Unobtrusive JS Quiz created by <strong> - </strong> <em>oVTech.</em>
</p>
<br /> <br />
</div>
</form>
</body>
</html>
Thank you everyone for help. (:
Sciliano
05-19-2011, 01:29 PM
See, an AJAX alternative:
AJAX Self-Grading Multiple Choice Quiz (http://www.codingforums.com/showthread.php?t=103688)
Typical contents of the email sent upon completion and submission of the quiz:
Date Administered: Thursday, 05/19/2011
Student: Joe
ID: 12345
Course: 4th Period Geography
Quiz Name: Geography Quiz 1
Number of Questions: 5
Correct Answers: 3
Incorrect Answers: 2
Skipped Questions: 0
Score: 60%
Time Used: 01:15
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.