patternjavascriptMinor
Multiple-choice quiz
Viewed 0 times
choicequizmultiple
Problem
I have been working on improving my javascript skills, mainly "namespacing" and the best practices used by js developers. I would like to know how I can improve this code and any tips that may help me along the way. Below is the specific code I am working with and there is a working fiddler also.
Just to note, I only want to use straight javascript and not jQuery for this.
```
var quiz = window.quiz || {};
(function(ns) {
var currentIndex = 0;
var parent, back, next;
var selectedChoices = [];
ns.version = '1.0.0';
ns.author = 'Anonymous Hands';
ns.parentId = function(id) { parent = document.getElementById(id); };
ns.nextButtonId = function(id) { next = document.getElementById(id); next.onclick = moveNext; };
ns.backButtonId = function(id) { back = document.getElementById(id); back.onclick = moveBack; };
ns.questions = [];
ns.render =
function() {
renderQuestion(0);
};
//Pass results and missed questions?
ns.onComplete = function(results){};
function moveNext(){
saveState();
if (!atEnd()){
currentIndex++;
renderQuestion(currentIndex);
restoreState();
return;
}
renderComplete();
}
function moveBack(){
saveState();
if(!atBeginning()){
currentIndex--;
renderQuestion(currentIndex);
restoreState();
}
}
function renderQuestion(index){
clearParent();
var questionNum = index + 1;
var node = ns.questions[index];
var questionNumDiv = makeElement({type: "div", class: "question-number" ,html: questionNum});
var questionText = makeElement({type: "div", class: "question-text" ,html: node.question});
var choicesDiv = makeElement({type: "div", class: "choices"});
var l = node.choices.length;
for(var i = 0; i = ns.questions.length - 1) ? true : false;
}
function getTotalCorrect(){
var correct = 0;
var l = ns.questions.length;
for(var i = 0; i < l; i++){
if (ns.questions[i].anwser === selectedChoices[i].
Just to note, I only want to use straight javascript and not jQuery for this.
```
var quiz = window.quiz || {};
(function(ns) {
var currentIndex = 0;
var parent, back, next;
var selectedChoices = [];
ns.version = '1.0.0';
ns.author = 'Anonymous Hands';
ns.parentId = function(id) { parent = document.getElementById(id); };
ns.nextButtonId = function(id) { next = document.getElementById(id); next.onclick = moveNext; };
ns.backButtonId = function(id) { back = document.getElementById(id); back.onclick = moveBack; };
ns.questions = [];
ns.render =
function() {
renderQuestion(0);
};
//Pass results and missed questions?
ns.onComplete = function(results){};
function moveNext(){
saveState();
if (!atEnd()){
currentIndex++;
renderQuestion(currentIndex);
restoreState();
return;
}
renderComplete();
}
function moveBack(){
saveState();
if(!atBeginning()){
currentIndex--;
renderQuestion(currentIndex);
restoreState();
}
}
function renderQuestion(index){
clearParent();
var questionNum = index + 1;
var node = ns.questions[index];
var questionNumDiv = makeElement({type: "div", class: "question-number" ,html: questionNum});
var questionText = makeElement({type: "div", class: "question-text" ,html: node.question});
var choicesDiv = makeElement({type: "div", class: "choices"});
var l = node.choices.length;
for(var i = 0; i = ns.questions.length - 1) ? true : false;
}
function getTotalCorrect(){
var correct = 0;
var l = ns.questions.length;
for(var i = 0; i < l; i++){
if (ns.questions[i].anwser === selectedChoices[i].
Solution
I tend to use a lot of Java best practices in my JavaScript code. The biggest issue I see is the lack of extensible classes/methods. The methods are procedural and only seem to be broken into new methods because they are repeatable. The class as a whole violates the single responsibility principle because it has to handle the entire widget from modifying input (also bad practice), parsing the input, managing the question state, and appending the view. By following SRP your code will become much easier to read, maintain, and extend. I'm not going to comment on your grammatical issues but you should definitely set up Sonar to scan your code if you haven't already.
So how it could be improved?
I would start be making a new class called Question that could take a single question model and display it on the page. Then create a Questionnaire class that can take a questionnaire model (metadata & list of questions) and handle the state transitions until all questions have been answered. Questionnaire will have to instantiate a new Question object inside a div.
I create the classes this way which allows the class to maintain scope.
There are then two ways the state transitions could be handled. POST the answer after every question and store the values at the server or store each question result in the Questionnaire and POST at the end. Don't store the answers in the code because anyone that knows how to access and read the code could cheat. Either way you choose make sure that each class knows as little about each other as possible. Question should know nothing about Questionnaire and Questionnaire should only know that is has a list of questions to loop through and use accessor methods to get the value from.
So how it could be improved?
I would start be making a new class called Question that could take a single question model and display it on the page. Then create a Questionnaire class that can take a questionnaire model (metadata & list of questions) and handle the state transitions until all questions have been answered. Questionnaire will have to instantiate a new Question object inside a div.
I create the classes this way which allows the class to maintain scope.
function Question(divId, question) {
// private variables
var myVar;
// this is a public method
this.getAnswer = function() {
}
// this is a private method
function renderChoice() {
}
function init() {
// build the view
}
// this method call initializes the class like a constructor
// so the caller doesn't have to initialize
init();
}There are then two ways the state transitions could be handled. POST the answer after every question and store the values at the server or store each question result in the Questionnaire and POST at the end. Don't store the answers in the code because anyone that knows how to access and read the code could cheat. Either way you choose make sure that each class knows as little about each other as possible. Question should know nothing about Questionnaire and Questionnaire should only know that is has a list of questions to loop through and use accessor methods to get the value from.
Code Snippets
function Question(divId, question) {
// private variables
var myVar;
// this is a public method
this.getAnswer = function() {
}
// this is a private method
function renderChoice() {
}
function init() {
// build the view
}
// this method call initializes the class like a constructor
// so the caller doesn't have to initialize
init();
}Context
StackExchange Code Review Q#27808, answer score: 2
Revisions (0)
No revisions yet.