// Will render a Question with multiple choices for answers. // Options format: // { // title: "Optional title for question box", // question: "Question text", // answers: [{text: "Answer text", correct: false}, ...], // singleAnswer: true, // or false, will change rendered output slightly. // } // // Events provided: // - h5pQuestionSetFinished: Triggered when a question is finished. (User presses Finish-button) var H5P = H5P || {}; H5P.QuestionSet = function (options, contentId) { if ( !(this instanceof H5P.QuestionSet) ) return new H5P.QuestionSet(options, contentId); var $ = H5P.jQuery; var cp = H5P.getContentPath(contentId); var texttemplate = '' + '<% if (introPage.showIntroPage) { %>' + '
' + '
<%= introPage.title %>
' + '
<%= introPage.introduction %>
' + '
<%= introPage.startButtonText %>
' + '
' + '<%} %>' + '' + ''; var resulttemplate = '' + '
' + '
<%= greeting %>
' + '
<%= score %>
' + '
<%= resulttext %>
' + '
<%= finishButtonText %>
' + '
' + ''; var that = this; var defaults = { title: "", randomOrder: false, initialQuestion: 0, backgroundImage: "", progressType: 'dots', passPercentage: 50, questions: [], introPage: { showIntroPage: true, title: "Welcome", introduction: "Click start to start.", startButtonText: "Start" }, texts: { prevButton: "Previous", nextButton: "Next", finishButton: "Finish", textualProgress: "Question: @current of @total questions" }, endGame: { showResultPage: true, resultPage: { successGreeting: "Congratulations!", successComment: "You have enough correct answers to pass the test.", failGreeting: "Sorry!", failComment: "You don't have enough correct answers to pass this test.", scoreString: "@score/@total", finishButtonText: "Finish" }, animations: { showAnimations: false, successVideo: undefined, failVideo: undefined } } }; var template = new EJS({text: texttemplate}); var endTemplate = new EJS({text: resulttemplate}); var params = $.extend({}, defaults, options); var currentQuestion = 0; var questionInstances = new Array(); var allQuestionsAnswered = false; var $myDom; if (params.randomOrder) { // TODO: Randomize order of questions console.log("TODO: Randomize order of questions"); } // Instantiate question instances for (var i=0; i= 0; i--) { answered = answered && (questionInstances[i]).getAnswerGiven(); } if (currentQuestion === 0) { $('.prev.button', $myDom).hide(); } else { $('.prev.button', $myDom).show(); } if (currentQuestion == (params.questions.length - 1)) { $('.next.button', $myDom).hide(); if (answered) { $('.finish.button', $myDom).show(); } } else { $('.next.button', $myDom).show(); $('.finish.button', $myDom).hide(); } }; var _showQuestion = function (questionNumber) { // Sanitize input. if (questionNumber < 0) { questionNumber = 0; } if (questionNumber >= params.questions.length) { questionNumber = params.questions.length - 1; } // Hide all questions $('.question-container', $myDom).hide(); // Reshow the requested question $('#q-' + questionNumber, $myDom).show(); // Update progress indicator // Test if current has been answered. if (params.progressType == 'textual') { $('.progress-text', $myDom).text(params.texts.textualProgress.replace("@current", questionNumber+1).replace("@total", params.questions.length)); } else { // Set currentNess $('.progress-dot.current', $myDom).removeClass('current'); $('#qdot-' + questionNumber, $myDom).addClass('current'); } // Remember where we are currentQuestion = questionNumber; _updateButtons(); return currentQuestion; }; var _displayEndGame = function () { // Get total score. var finals = getScore(); var totals = totalScore(); var scoreString = params.endGame.resultPage.scoreString.replace("@score", finals).replace("@total", totals); var success = ((100 * finals / totals) >= params.passPercentage); var eventData = { score: scoreString, passed: success }; var displayResults = function () { if (!params.endGame.showResultPage) { $(returnObject).trigger('h5pQuestionSetFinished', eventData); return; } var eparams = { greeting: (success ? params.endGame.resultPage.succesGreeting : params.endGame.resultPage.failGreeting), score: scoreString, scoreclass: (success ? 'success' : 'fail'), resulttext: (success ? params.endGame.resultPage.successComment : params.endGame.resultPage.failComment), finishButtonText: params.endGame.resultPage.finishButtonText }; // Show result page. $myDom.children().hide(); $myDom.append(endTemplate.render(eparams)); $('.qs-finishbutton').click(function (ev) { $(returnObject).trigger('h5pQuestionSetFinished', eventData); }); }; if (params.endGame.animations.showAnimations) { var videoData = success ? params.endGame.animations.successVideo : params.endGame.animations.failVideo; if (videoData) { H5P.playVideo($myDom, videoData, params.endGame.animations.skipButtonText, cp, function () { displayResults(); }); return; } } // Trigger finished event. displayResults(); }; // Function for attaching the multichoice to a DOM element. var attach = function (target) { if (typeof(target) == "string") { $myDom = $("#" + target); } else { $myDom = $(target); } // Render own DOM into target. $myDom.html(template.render(params)).css({ backgroundImage: 'url(' + cp + params.backgroundImage.path + ')' }); // Attach questions for (var i=0; i= 0; i--) { score += questionInstances[i].getScore(); } return score; }; // Get total score possible for questionset. var totalScore = function () { var score = 0; for (var i = questionInstances.length - 1; i >= 0; i--) { score += questionInstances[i].totalScore(); } return score; }; // Masquerade the main object to hide inner properties and functions. var returnObject = { attach: attach, // Attach to DOM object getQuestions: function () {return questionInstances;}, getScore: getScore, totalScore: totalScore, defaults: defaults // Provide defaults for inspection }; return returnObject; };