commit 85a18446fb863939d7930182eaec4ac6929df22f Author: Frank Ronny Larsen Date: Wed Jan 16 14:37:45 2013 +0100 Added H5P libraries diff --git a/content.json b/content.json new file mode 100644 index 0000000..e69de29 diff --git a/js/questionset.js b/js/questionset.js new file mode 100644 index 0000000..ca85d98 --- /dev/null +++ b/js/questionset.js @@ -0,0 +1,305 @@ +// 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) +window.H5P = window.H5P || {}; + +H5P.QuestionSet = function (options) { + if ( !(this instanceof H5P.QuestionSet) ) + return new H5P.QuestionSet(options); + + var $ = H5P.jQuery; + + var texttemplate = '' + +'' + +'
' + +' <% if (introPage.showIntroPage) { %>' + +'
' + +'
<%= introPage.title %>
' + +'
<%= introPage.introduction %>
' + +'
' + +'
' + +' <%} %>' + +'
<%= title %>
' + +' <% for (var i=0; i' + +'
' + +'
<%= questions[i].machineName %>
' + +'
' + +' <% } %>' + +' ' + +'
' + + ''; + + var resulttemplate = '' + +'
' + +'
<%= greeting %>
' + +'
<%= score %>
' + +'
<%= resulttext %>
' + +'
' + +'
' + +''; + + 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: { + succesGreeting: "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, + succesResultAnimation: { + machineName: "H5P.Image", + options: {image: ""} + }, + failedResultAnimation: { + machineName: "H5P.Image", + options: {image: ""} + } + } + } + }; + + 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(); + } + $('.finish.button', $myDom).attr({'disabled': !answered}); + }; + + var _showQuestion = function (questionNumber) { + // Sanitize input. + if (questionNumber < 0) { questionNumber = 0; } + if (questionNumber >= params.questions.length) { questionNumber = params.questions.length - 1; } + + $('.prev.button', $myDom).attr({'disabled': (questionNumber === 0)}); + $('.next.button', $myDom).attr({'disabled': (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; + return currentQuestion; + }; + + // Function for attaching the multichoice to a DOM element. + var attach = function (targetId) { + // Render own DOM into target. + template.update(targetId, params); + $myDom = $('#' + targetId); + $myDom.css({backgroundImage: 'url(' + params.backgroundImage + ')'}); + + // Attach questions + for (var i=0; i= params.passPercentage); + var eventData = { + score: scoreString, + passed: success + }; + // Display result page. + if (params.endGame.showResultPage) { + // Render result page into. + 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 + }; + endTemplate.update(targetId, eparams); + $('.qs-finishbutton').click(function (ev) { + // Display animation if present. + if (params.endGame.animations.showAnimations) { + // Init anims. + console.log("Now we should have started some anims..."); + // On animation finished: + $(returnObject).trigger('h5pQuestionSetFinished', eventData); + } else { + // Trigger finished event. + $(returnObject).trigger('h5pQuestionSetFinished', eventData); + } + }); + } else { + $(returnObject).trigger('h5pQuestionSetFinished', eventData); + } + }); + + // Hide all but initial Question. + _showQuestion(params.initialQuestion); + _updateFinishButton(); + return this; + }; + + // Get current score for questionset. + var getScore = function () { + var score = 0; + for (var i = questionInstances.length - 1; 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; +}; diff --git a/library.json b/library.json new file mode 100644 index 0000000..e69de29 diff --git a/schema.json b/schema.json new file mode 100644 index 0000000..790af6a --- /dev/null +++ b/schema.json @@ -0,0 +1,168 @@ +{ + "title": { + "label": "Title", + "description": "Question set title (optional)", + "type": "text", + "default": "" + }, + "randomOrder": { + "label": "Randomize order", + "description": "Whether questions should be shown in random order", + "type": "boolean", + "default": false + }, + "initialQuestion": { + "label": "Initial question", + "description": "Which question to start with. Count from 0", + "type": "integer", + "default": 0 + }, + "backgroundImage": { + "label": "Background image", + "description": "An optional background image for the Question set.", + "type": "image", + "default": "" + }, + "progressType": { + "label": "Progress indicator", + "description": "Question set progress indicator style", + "type": "select", + "values": [{"text": "Textual", "value": "textual"}, {"text": "Dots", "value": "dots"}], + "default": "textual" + }, + "passPercentage": { + "label": "Pass percentage", + "description": "Percentage of total score required for passing the quiz.", + "type": "integer", + "minValue": 0, + "maxValue": 100, + "default": 50 + }, + "questions": { + "label": "Questions", + "description": "List of questions in this set.", + "type": "h5p-library", + "validLibs": ["H5P.MultiChoice", "H5P.DragTextMatch", "H5PDragImageIntoPosition"], + "array": true, + "minEntries": 1, + "maxEntries": -1 + }, + "introPage": { + "label": "Intro page", + "description": "Data for the intro page", + "type": "combined", + "fields": { + "showIntroPage": { + "label": "Show intro page?", + "type": "boolean" + }, + "title": { + "label": "Title", + "type": "text" + }, + "introduction": { + "label": "Introduction text", + "type": "text" + }, + "startButtonText": { + "label": "Start button text", + "type": "text" + } + } + }, + "texts": { + "label": "Interface texts in quiz", + "type": "combined" + "fields": { + "prevButton": { + "label": "Back button", + "type": "text", + "default": "Previous" + }, + "nextButton": { + "label": "Next button", + "type": "text", + "default": "Next" + }, + "finishButton": { + "label": "Finish button", + "type": "text", + "default": "Finish" + }, + "textualProgress": { + "label": "Progress text", + "description": "Text used if textual progress is selected.", + "type": "text", + "default": "Question: @current of @total questions" + } + } + }, + "endGame": { + "label": "End game data", + "type": "combined", + "fields" { + "showResultPage": { + "label": "Show result page", + "type": "boolean", + "default": true + }, + "resultPage": { + "label": "Result page", + "description": "Data and texts for the result page", + "type": "combined", + "fields": { + "successGreeting": { + "label": "Success greeting", + "description": "Title in result page on success", + "type": "text" + }, + "successComment": { + "label": "Success comment", + "description": "Comment shown after the score", + "type": "text" + }, + "failGreeting": { + "label": "Failed greeting", + "description": "Title in result page on failed quiz", + "type": "text" + }, + "failComment": { + "label": "Failed comment", + "description": "Comment shown after the score on failed quiz", + "type": "text" + }, + "finishButtonText": { + "label": "Finish button text", + "description": "Text for the finish button", + "type": "text" + } + } + }, + "animations": { + "label": "Animations", + "type": "combined" + "fields": { + "showAnimations": { + "label": "Show animations", + "type": "boolean", + "default": false + } + "successResultAnimation": { + "label": "Result animation for success", + "description": "Add animation for successful completion of the quiz", + "optional": true, + "type": "h5p-library", + "validLibs": ["H5P.Animation", "H5P.Video", "H5P.Image"] + }, + "failedResultAnimation": { + "label": "Result animation for failed quiz", + "description": "Add animation for failed completion of the quiz", + "optional": true, + "type": "h5p-library", + "validLibs": ["H5P.Animation", "H5P.Video", "H5P.Image"] + } + } + } + } + } +} diff --git a/views/questionset-intro.ejs b/views/questionset-intro.ejs new file mode 100644 index 0000000..cc18bb6 --- /dev/null +++ b/views/questionset-intro.ejs @@ -0,0 +1,5 @@ +
+
<%= title %>
+
<%= introduction %>
+
+
\ No newline at end of file diff --git a/views/questionset-results.ejs b/views/questionset-results.ejs new file mode 100644 index 0000000..a107cb5 --- /dev/null +++ b/views/questionset-results.ejs @@ -0,0 +1,6 @@ +
+
<%= greeting %>
+
<%= score %>
+
<%= resulttext %>
+
+
diff --git a/views/questionset.ejs b/views/questionset.ejs new file mode 100644 index 0000000..574132b --- /dev/null +++ b/views/questionset.ejs @@ -0,0 +1,60 @@ + +
+ <% if (introPage.showIntroPage) { %> +
+
<%= introPage.title %>
+
<%= introPage.introduction %>
+
+
+ <%} %> +
<%= title %>
+ <% for (var i=0; i +
+
<%= questions[i].machineName %>
+
+ <% } %> + +