diff --git a/src/index.js b/src/index.js index 9258781..3755ebf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,249 +1,282 @@ -var responseCount, currentQuestion, options, -questions, responses, quizData, question, j, -$question, $resetButton, isQuestionAnswered +let options = {url: `data/quiz.json? ${Date.now()}`} -responseCount = 0 -currentQuestion = 0 -options = { - url: 'data/quiz.json?' + Date.now() +function loadResponses() { + let quizData + try { + quizData = JSON.parse(localStorage.getItem('quiz')) || {responses: [], responseCount: 0, currentQuestion: 0} + } catch (e) {} + return quizData } -$.ajax({ - url: options.url -}).done(function(data) { - questions = data.questions +function saveResponses(responses, responseCount, currentQuestion) { + let quizData = {responses, responseCount, currentQuestion} + localStorage.setItem('quiz', JSON.stringify(quizData)) +} - // Load data from past reponses - try { - quizData = JSON.parse(localStorage.getItem('quiz')) - responses = quizData.responses || [] - currentQuestion = quizData.currentQuestion || -1 - responseCount = quizData.responseCount || -1 - } catch (e) {} +function appendProgressBar() { + $('body') + .append(`
+
 
+
`) +} - if (quizData == null) { - quizData = { - responses: [] - } - responses = quizData.responses +function appendTitle(title) { + $('#quiz') + .append(`

${title}

+
`) +} + +function buildInput(i, type, options, responses) { + let input + switch (type) { + + // Multiple options + case 'checkbox': + case 'radio': + input = '
' + options.forEach((option, j) => { + let checked = responses[i] && responses[i].indexOf(option.label) !== -1 ? 'checked' : '' + + input += `
+
+ + +
+
` + }) + input += '
' + break + + // Set of inputs (composed response) + case 'inputs': + input = '' + options.forEach((option, j) => { + let value = responses[i] ? responses[i][j] : '' + + input += ` + + + + + ` + }) + input += '
+ +
 
' + break + + // Default: simple input + default: + let value = responses[i] ? responses[i] : '' + + input = `
+ +
` } + return input +} +function appendQuestion(i, question, input) { + const $question = $(`
+
+
${question.problem}
+
+
+ ${input} +
+
` + ).css('display', 'none') - // Append the progress bar to DOM - $('body') - .append('
' + - '
 
' + - '
') + $('#quiz-form') + .append($question) +} - // Append title and form to quiz - $('#quiz') - .append('

' + data.title + '

') - .append('
') +function showCurrentQuestion(currentQuestion) { + $('#quiz-form') + .find(`#question-${currentQuestion}`) + .css('display', 'block') +} - // For each question of the json, - for (var i = 0; i < data.questions.length; i++) { - question = data.questions[i] +function updateProgressBar(responseCount, questions) { + $('#progress') + .css('width', (responseCount / questions.length * 100) + '%') +} - if (question.input === undefined) { - question.input = { - type: 'input' +function checkAllQuestionsAnswered(responseCount, questions) { + if (responseCount === questions.length) { + $('#submit-response').css('display', 'none') + $('#quiz').append('
Thank you for your responses.

') + $('#quiz').append('') + } +} + +function addResetButton() { + const $resetButton = $('') + $resetButton.on('click', function() { + localStorage.removeItem('quiz') + location.reload(); + }) + $('#quiz').append($resetButton) +} + +function putResponsesIntoArray(question, $inputs, responses, currentQuestion) { + let result = responses.map(item => item) + + switch (question.input.type) { + case 'checkbox': + case 'radio': + result[currentQuestion] = [] + $(`[name=${$inputs.attr('name')}]:checked`).each((i, input) =>{ + result[currentQuestion].push(input.value) + }) + if (result[currentQuestion].length === 0) { + result[currentQuestion] = null } - } + break + case 'inputs': + result[currentQuestion] = [] + $inputs.each((i, input) => { + result[currentQuestion].push(input.value) + }) + break + default: + result[currentQuestion] = $inputs.val() + } + return result +} - // Construct the input depending on question type +function getResponseCount(responses, questions) { + let responseCount = 0 + responses.forEach((response, i) => { + let question = questions[i] switch (question.input.type) { - - // Multiple options case 'checkbox': case 'radio': - var input = '
' - for (j = 0; j < question.input.options.length; j++) { - var option = question.input.options[j] - var type = question.input.type - - if (!!responses[i] && responses[i].indexOf(option.label) !== -1) { - var checked = 'checked' - } else { - var checked = '' - } - - input += '
' + - '
' + - '' + - '' + - '
' + - '
' - } - input += '
' - break - - // Set of inputs (composed response) case 'inputs': - var input = '' - for (j = 0; j < question.input.options.length; j++) { - var option = question.input.options[j] - var type = 'checkbox' - - if (!!responses[i]) { - var value = responses[i][j] - } else { - var value = '' - } - - input += '' + - '' + - '' + - '' + - '' + - '' + if (response && response.join('')) { + responseCount++ } - input += '
' + - '' + - '
 
' break - - // Default: simple input default: - if (!!responses[i]) { - var value = responses[i] - } else { - var value = '' + if (response) { + responseCount++ } - var input = '
' + - '' + - '
' } + }) + return responseCount +} - $question = $('
' + - '
' + - '
' + question.problem + '
' + - '
' + - '
' + - input + - '
' + - '
' - ).css('display', 'none') +function isArray(obj) { + return Object.prototype.toString.call(obj) === '[object Array]' +} + +function checkIfQuestionAnswered(responses, currentQuestion) { + let isQuestionAnswered = !responses[currentQuestion] ? false : true + + if (responses[currentQuestion] && responses[currentQuestion].length && isArray(responses[currentQuestion])) { + responses[currentQuestion].forEach((response) => { + if (!response) { + isQuestionAnswered = false + } + }) + } + return isQuestionAnswered +} - $('#quiz-form') - .append($question) +function displayNextQuestion(currentQuestion) { + let result = currentQuestion + $('#quiz-form') + .find(`#question-${result}`).css('display', 'none') + result++ + + $('#quiz-form') + .find(`#question-${result}`).css('display', 'block') + return result +} + +function checkForFinalMessage(responseCount, questions) { + if (responseCount === questions.length) { + $('#submit-response').css('display', 'none') + $('#quiz').append(`
Thank you for your responses.

+ `) + } +} + +$.ajax({ + url: options.url +}).done((data) => { + const { questions , title} = data; + + // Load data from past reponses + let quizData = loadResponses() + let {currentQuestion=0, responseCount=0, responses=[]} = quizData + + // Append the progress bar to DOM + appendProgressBar() + + // Append title and form to quiz + appendTitle(title) + + // For each question of the json, + questions.forEach((question, i) => { + const {input: {type= 'input', options=[]} = {}, problem} = question + + if (question.input === undefined) { + question.input = { + type: 'input' + } + } + + // Construct the input depending on question type + let input = buildInput(i, type, options, responses) + appendQuestion(i, question, input) // Show current question - $('#quiz-form') - .find('#question-' + currentQuestion) - .css('display', 'block') + showCurrentQuestion(currentQuestion) // Update progress bar - $('#progress') - .css('width', (responseCount / questions.length * 100) + '%') - } + updateProgressBar(responseCount, questions) + }) // Add button to submit response $('#quiz') .append('') // Is case all questions have been responded - if (responseCount === questions.length) { - $('#submit-response').css('display', 'none') - $('#quiz').append('
Thank you for your responses.

') - $('#quiz').append('') - } + checkAllQuestionsAnswered(responseCount, questions) // Add a reset button that will redirect to quiz start - $resetButton = $('') - $resetButton.on('click', function() { - localStorage.removeItem('quiz') - location.reload(); - }) - $('#quiz').append($resetButton) + addResetButton() // Actions on every response submission - $('#submit-response').on('click', function() { - var $inputs = $('[name^=question_' + currentQuestion + ']') - var question = questions[currentQuestion] + $('#submit-response').on('click', () => { + + const $inputs = $(`[name^=question_${currentQuestion}]`) + let question = questions[currentQuestion] // Behavior for each question type to add response to array of responses - switch (question.input.type) { - case 'checkbox': - case 'radio': - responses[currentQuestion] = [] - $('[name=' + $inputs.attr('name') + ']:checked').each(function(i, input) { - responses[currentQuestion].push(input.value) - }) - if (responses[currentQuestion].length === 0) { - responses[currentQuestion] = null - } - break - case 'inputs': - responses[currentQuestion] = [] - $inputs.each(function(i, input) { - responses[currentQuestion].push(input.value) - }) - break - default: - responses[currentQuestion] = $inputs.val() - } + responses = putResponsesIntoArray(question, $inputs, responses, currentQuestion) // Set the current responses counter - var responseCount = 0 - for (i = 0; i < responses.length; i++) { - question = questions[i] - switch (question.input.type) { - case 'checkbox': - case 'radio': - case 'inputs': - if (!!responses[i] && !!responses[i].join('')) { - responseCount++ - } - break - default: - if (!!responses[i]) { - responseCount++ - } - } - } + let responseCount = getResponseCount(responses, questions) // Update progress bar - $('#progress') - .css('width', (responseCount / questions.length * 100) + '%') + updateProgressBar(responseCount, questions) // Check if question had a valid answer - isQuestionAnswered = true - if (!responses[currentQuestion]) { - isQuestionAnswered = false - } - if (!!responses[currentQuestion] && !!responses[currentQuestion].length) { - for (j = 0; j < responses[currentQuestion].length; j++) { - if (!responses[currentQuestion][j]) { - isQuestionAnswered = false - } - } - } - - if (!isQuestionAnswered) { + if (!checkIfQuestionAnswered(responses, currentQuestion)) { // Alert user of missing response alert('You must give a response') } else { // Display next question - $('#quiz-form') - .find('#question-' + currentQuestion).css('display', 'none') - currentQuestion = currentQuestion + 1 - - $('#quiz-form') - .find('#question-' + currentQuestion).css('display', 'block') - + currentQuestion = displayNextQuestion(currentQuestion) + // If it was the las question, display final message - if (responseCount === questions.length) { - $('#submit-response').css('display', 'none') - $('#quiz').append('
Thank you for your responses.

') - $('#quiz').append('') - } + checkForFinalMessage(responseCount, questions) } // Save current state of the quiz - quizData.responses = responses - quizData.responseCount = responseCount - quizData.currentQuestion = currentQuestion - localStorage.setItem('quiz', JSON.stringify(quizData)) + saveResponses(responses, responseCount, currentQuestion) }) -}) +}) \ No newline at end of file