HFP-29 Merge with master

pull/4/merge
Timothy Lim 2017-05-10 10:23:49 +02:00
commit 9cf00d897d
17 changed files with 797 additions and 239 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
*~ *~
/nbproject/private/ /nbproject/private/
.idea

View File

@ -1,16 +1,16 @@
H5P Question Set H5P Question Set
========== ==========
Test your users with by putting together multiple tasks into a question set(quiz). Test your users with by putting together multiple tasks into a question set(quiz)
## License ## License
(The MIT License) (The MIT License)
Copyright (c) 2012-2014 Amendor AS Copyright (c) 2012-2014 Joubel AS
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,15 +1,3 @@
/* IcoMoon font licensed under the GNU General Public License: http://www.gnu.org/licenses/gpl.html */
@font-face {
font-family: 'icomoon-questionset';
src:url('../fonts/icomoon.eot');
src:url('../fonts/icomoon.eot?#iefix') format('embedded-opentype'),
url('../fonts/icomoon.woff') format('woff'),
url('../fonts/icomoon.ttf') format('truetype'),
url('../fonts/icomoon.svg#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
.questionset-results h2 { .questionset-results h2 {
font-size: 1.2em; font-size: 1.2em;
font-weight: bold; font-weight: bold;
@ -52,7 +40,12 @@
background: #fff; background: #fff;
background: #cecece; background: #cecece;
} }
.progress-dot:hover {
.progress-dot.disabled {
cursor: default;
}
.progress-dot:not(.disabled):hover {
box-shadow: 0 0 0.5em #c7c7c7; box-shadow: 0 0 0.5em #c7c7c7;
} }
.progress-dot.answered { .progress-dot.answered {
@ -61,6 +54,11 @@
.progress-dot.current { .progress-dot.current {
background: #285585; background: #285585;
} }
.progress-dot.disabled:focus {
outline: none
}
.progress-dot:focus { .progress-dot:focus {
outline-color: rgb(40, 130, 211); outline-color: rgb(40, 130, 211);
outline-width: thin; outline-width: thin;
@ -151,6 +149,12 @@
width: 2.1875em; width: 2.1875em;
} }
.h5p-question .h5p-question-prev.truncated,
.h5p-question .h5p-question-next.truncated {
padding: 0;
line-height: 2.2335em;
}
.h5p-question .h5p-question-next, .h5p-question .h5p-question-next,
.h5p-question .h5p-question-finish { .h5p-question .h5p-question-finish {
margin: 0 0 1.5em 0.5em; margin: 0 0 1.5em 0.5em;

Binary file not shown.

View File

@ -1,14 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" d="" horiz-adv-x="512" />
<glyph unicode="&#xe604;" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM256 640c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM640 640c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM704.098 332.74l82.328-49.396c-55.962-93.070-157.916-155.344-274.426-155.344s-218.464 62.274-274.426 155.344l82.328 49.396c39.174-65.148 110.542-108.74 192.098-108.74s152.924 43.592 192.098 108.74z" />
<glyph unicode="&#xe605;" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM745.74 358.38l22.488-76.776-437.008-128.002-22.488 76.776zM256 640c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64zM640 640c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64-35.346 0-64 28.654-64 64z" />
<glyph unicode="&#xe606;" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM192 448v-64c0-140.8 115.2-256 256-256h128c140.8 0 256 115.2 256 256v64h-640zM384 203.012c-26.538 9.458-50.924 24.822-71.544 45.446-36.406 36.402-56.456 84.54-56.456 135.542h128v-180.988zM576 192h-128v192h128v-192zM711.544 248.458c-20.624-20.624-45.010-35.988-71.544-45.446v180.988h128c0-51.002-20.048-99.14-56.456-135.542zM225.352 576c0.002 0 0 0 0 0 9.768 0 18.108 7.056 19.724 16.69 6.158 36.684 37.668 63.31 74.924 63.31s68.766-26.626 74.924-63.31c1.616-9.632 9.956-16.69 19.722-16.69 9.768 0 18.108 7.056 19.724 16.688 1.082 6.436 1.628 12.934 1.628 19.312 0 63.962-52.038 116-116 116s-116-52.038-116-116c0-6.378 0.548-12.876 1.628-19.312 1.62-9.632 9.96-16.688 19.726-16.688zM609.352 576c0.002 0 0 0 0 0 9.77 0 18.112 7.056 19.724 16.69 6.158 36.684 37.668 63.31 74.924 63.31s68.766-26.626 74.924-63.31c1.616-9.632 9.958-16.69 19.722-16.69s18.108 7.056 19.722 16.688c1.082 6.436 1.628 12.934 1.628 19.312 0 63.962-52.038 116-116 116s-116-52.038-116-116c0-6.378 0.544-12.876 1.626-19.312 1.624-9.632 9.964-16.688 19.73-16.688z" />
<glyph unicode="&#xe607;" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM384 256c0 70.692 57.308 128 128 128s128-57.308 128-128c0-70.692-57.308-128-128-128-70.692 0-128 57.308-128 128zM640 608c0 53.019 28.654 96 64 96s64-42.981 64-96c0-53.019-28.654-96-64-96-35.346 0-64 42.981-64 96zM256 608c0 53.019 28.654 96 64 96s64-42.981 64-96c0-53.019-28.654-96-64-96-35.346 0-64 42.981-64 96z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Binary file not shown.

105
icon.svg Normal file
View File

@ -0,0 +1,105 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 225">
<defs>
<style>
.cls-1 {
isolation: isolate;
}
.cls-2 {
fill: #56b5ef;
}
.cls-3 {
opacity: 0.15;
mix-blend-mode: multiply;
}
.cls-4 {
fill: #fff;
}
.cls-5 {
opacity: 0.2;
}
.cls-6 {
fill: #231f20;
}
.cls-7 {
fill: #ddd;
}
.cls-8 {
fill: #8db7e2;
}
.cls-9 {
fill: none;
}
</style>
</defs>
<title>question-set</title>
<g class="cls-1">
<g id="Layer_2" data-name="Layer 2">
<g id="question_set_copy" data-name="question set copy">
<g>
<circle class="cls-2" cx="204" cy="113.5" r="85"/>
<g>
<g>
<g class="cls-3">
<rect x="168" y="82.5" width="93" height="85"/>
</g>
<rect class="cls-4" x="165" y="78.5" width="92" height="86"/>
</g>
<g>
<g class="cls-3">
<rect x="162" y="75.5" width="92" height="85"/>
</g>
<rect class="cls-4" x="157" y="70.5" width="93" height="87"/>
</g>
<g>
<g class="cls-3">
<rect x="153" y="67.5" width="92" height="85"/>
</g>
<rect class="cls-4" x="151" y="63.5" width="91" height="86"/>
</g>
<g>
<g class="cls-5">
<rect class="cls-6" x="157" y="95.88" width="82.24" height="12.27" rx="5.44" ry="5.44"/>
<rect class="cls-6" x="161.84" y="99.51" width="69.11" height="4.84"/>
</g>
<g>
<rect class="cls-7" x="157" y="94.15" width="82.24" height="12.27" rx="5.44" ry="5.44"/>
<rect class="cls-8" x="161.84" y="97.78" width="69.11" height="4.84"/>
</g>
</g>
<g>
<g class="cls-5">
<rect class="cls-6" x="157" y="113.85" width="82.24" height="12.27" rx="5.44" ry="5.44"/>
<rect class="cls-6" x="161.84" y="117.65" width="57.02" height="4.84"/>
</g>
<g>
<rect class="cls-7" x="157" y="112.12" width="82.24" height="12.27" rx="5.44" ry="5.44"/>
<rect class="cls-8" x="161.84" y="115.92" width="57.02" height="4.84"/>
</g>
</g>
<g>
<g class="cls-5">
<rect class="cls-6" x="157" y="131.99" width="82.24" height="12.27" rx="5.44" ry="5.44"/>
<rect class="cls-6" x="161.84" y="135.79" width="64.27" height="4.84"/>
</g>
<g>
<rect class="cls-7" x="157" y="130.26" width="82.24" height="12.27" rx="5.44" ry="5.44"/>
<rect class="cls-8" x="161.84" y="134.06" width="64.27" height="4.84"/>
</g>
</g>
<circle class="cls-8" cx="197.91" cy="79.04" r="10.98"/>
<path class="cls-4" d="M196,82.5V81.07a2.91,2.91,0,0,1,.61-1.36A5.25,5.25,0,0,1,198,78.49a6,6,0,0,0,1.2-1,1.47,1.47,0,0,0,.31-.85.91.91,0,0,0-.37-.8,1.83,1.83,0,0,0-1.08-.28,6.24,6.24,0,0,0-2.78.8l-.88-1.78a7.75,7.75,0,0,1,3.85-1,4.09,4.09,0,0,1,2.66.8,2.63,2.63,0,0,1,1,2.15,2.85,2.85,0,0,1-.41,1.54,5.79,5.79,0,0,1-1.54,1.46,15,15,0,0,0-1.34.88c-.14.2-.56.46-.56.79V82.5Zm.3,2a1.36,1.36,0,0,1,.37-1,1.48,1.48,0,0,1,1.06-.35,1.44,1.44,0,0,1,1,.36,1.58,1.58,0,0,1,0,2,1.42,1.42,0,0,1-1,.37,1.46,1.46,0,0,1-1.06-.36A1.35,1.35,0,0,1,196.3,84.45Z"/>
</g>
</g>
<rect class="cls-9" width="400" height="225"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -1,4 +1,4 @@
var H5P = H5P || {}; H5P = H5P || {};
/** /**
* Will render a Question with multiple choices for answers. * Will render a Question with multiple choices for answers.
@ -39,14 +39,19 @@ H5P.QuestionSet = function (options, contentId, contentData) {
' <% } %>' + ' <% } %>' +
' <div class="qs-footer">' + ' <div class="qs-footer">' +
' <div class="qs-progress">' + ' <div class="qs-progress">' +
' <% if (progressType == "dots" && !disableBackwardsNavigation) { %>' + ' <% if (progressType == "dots") { %>' +
' <ul class="dots-container" role="navigation">' + ' <ul class="dots-container" role="navigation">' +
' <% for (var i=0; i<questions.length; i++) { %>' + ' <% for (var i=0; i<questions.length; i++) { %>' +
' <li class="progress-item"><a href="#" class="progress-dot unanswered" ' + ' <li class="progress-item">' +
' aria-label="<%=' + ' <a href="#" ' +
' texts.jumpToQuestion.replace("%d", i + 1).replace("%total", questions.length)' + ' class="progress-dot unanswered<%' +
' + ", " + texts.unansweredText' + ' if (disableBackwardsNavigation) { %> disabled <% } %>"' +
' %>" tabindex="-1"></a></li>' + ' aria-label="<%=' +
' texts.jumpToQuestion.replace("%d", i + 1).replace("%total", questions.length)' +
' + ", " + texts.unansweredText %>" tabindex="-1" ' +
' <% if (disableBackwardsNavigation) { %> aria-disabled="true" <% } %>' +
' ></a>' +
' </li>' +
' <% } %>' + ' <% } %>' +
' </div>' + ' </div>' +
' <% } else if (progressType == "textual") { %>' + ' <% } else if (progressType == "textual") { %>' +
@ -81,7 +86,6 @@ H5P.QuestionSet = function (options, contentId, contentData) {
'</div>'; '</div>';
var defaults = { var defaults = {
randomOrder: false,
initialQuestion: 0, initialQuestion: 0,
progressType: 'dots', progressType: 'dots',
passPercentage: 50, passPercentage: 50,
@ -126,18 +130,100 @@ H5P.QuestionSet = function (options, contentId, contentData) {
var endTemplate = new EJS({text: resulttemplate}); var endTemplate = new EJS({text: resulttemplate});
var params = $.extend(true, {}, defaults, options); var params = $.extend(true, {}, defaults, options);
var initialParams = $.extend(true, {}, defaults, options);
var poolOrder; // Order of questions in a pool
var currentQuestion = 0; var currentQuestion = 0;
var questionInstances = []; var questionInstances = [];
var questionOrder; //Stores order of questions to allow resuming of question set
var $myDom; var $myDom;
var scoreBar; var scoreBar;
var up; var up;
var renderSolutions = false; var renderSolutions = false;
var showingSolutions = false;
contentData = contentData || {}; contentData = contentData || {};
// Bring question set up to date when resuming
if (contentData.previousState) { if (contentData.previousState) {
currentQuestion = contentData.previousState.progress; if (contentData.previousState.progress) {
currentQuestion = contentData.previousState.progress;
}
questionOrder = contentData.previousState.order;
} }
/**
* Randomizes questions in an array and updates an array containing their order
* @param {array} questions
* @return {Object.<array, array>} questionOrdering
*/
var randomizeQuestionOrdering = function (questions) {
// Save the original order of the questions in a multidimensional array [[question0,0],[question1,1]...
var questionOrdering = questions.map(function(questionInstance, index) { return [questionInstance, index] });
// Shuffle the multidimensional array
questionOrdering = H5P.shuffleArray(questionOrdering);
// Retrieve question objects from the first index
var questions = [];
for (var i = 0; i < questionOrdering.length; i++) {
questions[i] = questionOrdering[i][0];
}
// Retrieve the new shuffled order from the second index
var newOrder = [];
for (var i = 0; i< questionOrdering.length; i++) {
// Use a previous order if it exists
if(contentData.previousState && contentData.previousState.questionOrder) {
newOrder[i] = questionOrder[questionOrdering[i][1]];
}
else {
newOrder[i] = questionOrdering[i][1];
}
}
// Return the questions in their new order *with* their new indexes
return {
questions: questions,
questionOrder: newOrder
};
};
// Create a pool (a subset) of questions if necessary
if (params.poolSize > 0) {
// If a previous pool exists, recreate it
if(contentData.previousState && contentData.previousState.poolOrder) {
poolOrder = contentData.previousState.poolOrder;
// Recreate the pool from the saved data
var pool = [];
for (var i = 0; i < poolOrder.length; i++) {
pool[i] = params.questions[poolOrder[i]];
}
// Replace original questions with just the ones in the pool
params.questions = pool;
}
else { // Otherwise create a new pool
// Randomize and get the results
var poolResult = randomizeQuestionOrdering(params.questions);
var poolQuestions = poolResult.questions;
poolOrder = poolResult.questionOrder;
// Discard extra questions
poolQuestions = poolQuestions.slice(0, params.poolSize);
poolOrder = poolOrder.slice(0, params.poolSize);
// Replace original questions with just the ones in the pool
params.questions = poolQuestions;
}
}
// Create the html template for the question container
var $template = $(template.render(params)); var $template = $(template.render(params));
// Set overrides for questions // Set overrides for questions
var override; var override;
if (params.override.showSolutionButton || params.override.retryButton) { if (params.override.showSolutionButton || params.override.retryButton) {
@ -155,29 +241,61 @@ H5P.QuestionSet = function (options, contentId, contentData) {
} }
} }
// Instantiate question instances /**
for (var i = 0; i < params.questions.length; i++) { * Generates question instances from H5P objects
var question = params.questions[i]; *
* @param {object} questions H5P content types to be created as instances
* @return {array} Array of questions instances
*/
var createQuestionInstancesFromQuestions = function(questions) {
var result = [];
// Create question instances from questions
// Instantiate question instances
for (var i = 0; i < questions.length; i++) {
if (override) { var question;
// Extend subcontent with the overrided settings. // If a previous order exists, use it
$.extend(question.params.behaviour, override); if (questionOrder !== undefined) {
question = questions[questionOrder[i]];
}
else {
// Use a generic order when initialzing for the first time
question = questions[i];
}
if (override) {
// Extend subcontent with the overrided settings.
$.extend(question.params.behaviour, override);
}
question.params = question.params || {};
question.params.overrideSettings = question.params.overrideSettings || {};
question.params.overrideSettings.$confirmationDialogParent = $template.last();
question.params.overrideSettings.instance = this;
var hasAnswers = contentData.previousState && contentData.previousState.answers;
var questionInstance = H5P.newRunnable(question, contentId, undefined, undefined,
{
previousState: hasAnswers ? contentData.previousState.answers[i] : undefined,
parent: self
});
questionInstance.on('resize', function () {
up = true;
self.trigger('resize');
});
result.push(questionInstance);
} }
question.params = question.params || {}; return result;
question.params.overrideSettings = question.params.overrideSettings || {}; }
question.params.overrideSettings.$confirmationDialogParent = $template.last();
question.params.overrideSettings.instance = this; // Create question instances from questions given by params
var questionInstance = H5P.newRunnable(question, contentId, undefined, undefined, questionInstances = createQuestionInstancesFromQuestions(params.questions);
{
previousState: contentData.previousState ? contentData.previousState.answers[i] : undefined, // Randomize questions only on instantiation
parent: self if (params.randomQuestions && contentData.previousState === undefined) {
}); var result = randomizeQuestionOrdering(questionInstances);
questionInstance.on('resize', function () { questionInstances = result.questions;
up = true; questionOrder = result.questionOrder;
self.trigger('resize');
});
questionInstances.push(questionInstance);
} }
// Resize all interactions on resize // Resize all interactions on resize
@ -195,6 +313,17 @@ H5P.QuestionSet = function (options, contentId, contentData) {
// Update button state. // Update button state.
var _updateButtons = function () { var _updateButtons = function () {
// Verify that current question is answered when backward nav is disabled
if (params.disableBackwardsNavigation) {
if (questionInstances[currentQuestion].getAnswerGiven()
&& questionInstances.length-1 !== currentQuestion) {
questionInstances[currentQuestion].showButton('next');
}
else {
questionInstances[currentQuestion].hideButton('next');
}
}
var answered = true; var answered = true;
for (var i = questionInstances.length - 1; i >= 0; i--) { for (var i = questionInstances.length - 1; i >= 0; i--) {
answered = answered && (questionInstances[i]).getAnswerGiven(); answered = answered && (questionInstances[i]).getAnswerGiven();
@ -284,7 +413,18 @@ H5P.QuestionSet = function (options, contentId, contentData) {
* @public * @public
*/ */
var showSolutions = function () { var showSolutions = function () {
showingSolutions = true;
for (var i = 0; i < questionInstances.length; i++) { for (var i = 0; i < questionInstances.length; i++) {
// Enable back and forth navigation in solution mode
toggleDotsNavigation(true);
if (i < questionInstances.length - 1) {
questionInstances[i].showButton('next');
}
if (i > 0) {
questionInstances[i].showButton('prev');
}
try { try {
// Do not read answers // Do not read answers
questionInstances[i].toggleReadSpeaker(true); questionInstances[i].toggleReadSpeaker(true);
@ -298,15 +438,50 @@ H5P.QuestionSet = function (options, contentId, contentData) {
} }
}; };
/**
* Toggles whether dots are enabled for navigation
*/
var toggleDotsNavigation = function (enable) {
$('.progress-dot', $myDom).each(function () {
$(this).toggleClass('disabled', !enable);
$(this).attr('aria-disabled', enable ? 'false' : 'true');
// Remove tabindex
if (!enable) {
$(this).attr('tabindex', '-1');
}
});
};
/** /**
* Resets the task and every subcontent task. * Resets the task and every subcontent task.
* Used for contracts with integrated content. * Used for contracts with integrated content.
* @public * @public
*/ */
var resetTask = function () { var resetTask = function () {
// Clear previous state to ensure questions are created cleanly
contentData.previousState = [];
showingSolutions = false;
for (var i = 0; i < questionInstances.length; i++) { for (var i = 0; i < questionInstances.length; i++) {
try { try {
questionInstances[i].resetTask(); questionInstances[i].resetTask();
// Hide back and forth navigation in normal mode
if (params.disableBackwardsNavigation) {
toggleDotsNavigation(false);
// Check if first question is answered by default
if (i === 0 && questionInstances[i].getAnswerGiven()) {
questionInstances[i].showButton('next');
}
else {
questionInstances[i].hideButton('next');
}
questionInstances[i].hideButton('prev');
}
} }
catch(error) { catch(error) {
H5P.error("subcontent does not contain a valid resetTask function"); H5P.error("subcontent does not contain a valid resetTask function");
@ -324,6 +499,32 @@ H5P.QuestionSet = function (options, contentId, contentData) {
//Force the last page to be reRendered //Force the last page to be reRendered
rendered = false; rendered = false;
if(params.poolSize > 0){
// Make new pool from params.questions
// Randomize and get the results
var poolResult = randomizeQuestionOrdering(initialParams.questions);
var poolQuestions = poolResult.questions;
poolOrder = poolResult.questionOrder;
// Discard extra questions
poolQuestions = poolQuestions.slice(0, params.poolSize);
poolOrder = poolOrder.slice(0, params.poolSize);
// Replace original questions with just the ones in the pool
params.questions = poolQuestions;
// Recreate the question instances
questionInstances = createQuestionInstancesFromQuestions(params.questions);
// Update buttons
initializeQuestion();
} else if (params.randomQuestions) {
randomizeQuestions();
}
}; };
var rendered = false; var rendered = false;
@ -332,18 +533,86 @@ H5P.QuestionSet = function (options, contentId, contentData) {
rendered = false; rendered = false;
}; };
/**
* Randomizes question instances
*/
var randomizeQuestions = function () {
var result = randomizeQuestionOrdering(questionInstances);
questionInstances = result.questions;
questionOrder = result.questionOrder;
replaceQuestionsInDOM(questionInstances);
};
/**
* Empty the DOM of all questions, attach new questions and update buttons
*
* @param {type} questionInstances Array of questions to be attached to the DOM
*/
var replaceQuestionsInDOM = function (questionInstances) {
// Find all question containers and detach questions from them
$('.question-container', $myDom).each(function (){
$(this).children().detach();
});
// Reattach questions and their buttons in the new order
for (var i = 0; i < questionInstances.length; i++) {
var question = questionInstances[i];
// Make sure styles are not being added twice
$('.question-container:eq(' + i + ')', $myDom).attr('class', 'question-container');
question.attach($('.question-container:eq(' + i + ')', $myDom));
//Show buttons if necessary
if(questionInstances[questionInstances.length -1] === question
&& question.hasButton('finish')) {
question.showButton('finish');
}
if(questionInstances[questionInstances.length -1] !== question
&& question.hasButton('next')) {
question.showButton('next');
}
if(questionInstances[0] !== question
&& question.hasButton('prev')
&& !params.disableBackwardsNavigation) {
question.showButton('prev');
}
// Hide relevant buttons since the order has changed
if (questionInstances[0] === question) {
question.hideButton('prev');
}
if (questionInstances[questionInstances.length-1] === question) {
question.hideButton('next');
}
if (questionInstances[questionInstances.length-1] !== question) {
question.hideButton('finish');
}
}
};
var moveQuestion = function (direction) { var moveQuestion = function (direction) {
if (params.disableBackwardsNavigation && !questionInstances[currentQuestion].getAnswerGiven()) {
questionInstances[currentQuestion].hideButton('next');
questionInstances[currentQuestion].hideButton('finish');
return;
}
_stopQuestion(currentQuestion); _stopQuestion(currentQuestion);
if (currentQuestion + direction >= questionInstances.length) { if (currentQuestion + direction >= questionInstances.length) {
_displayEndGame(); _displayEndGame();
}
else if (!params.disableBackwardsNavigation || questionInstances[currentQuestion].getAnswerGiven()) {
// Allow movement if backward navigation enabled or answer given
_showQuestion(currentQuestion + direction);
} }
else { else {
//TODO: Give an error message ? or disable/grey out previous button when not allowed // Allow movement if backward navigation enabled or answer given
_showQuestion(currentQuestion + direction);
} }
}; };
@ -394,9 +663,10 @@ H5P.QuestionSet = function (options, contentId, contentData) {
label += ', ' + texts.currentQuestionText; label += ', ' + texts.currentQuestionText;
} }
var disabledTabindex = params.disableBackwardsNavigation && !showingSolutions;
$el.toggleClass('current', isCurrent) $el.toggleClass('current', isCurrent)
.attr('aria-label', label) .attr('aria-label', label)
.attr('tabindex', isCurrent ? 0 : -1); .attr('tabindex', isCurrent && !disabledTabindex ? 0 : -1);
}; };
var _displayEndGame = function () { var _displayEndGame = function () {
@ -412,7 +682,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
// Get total score. // Get total score.
var finals = self.getScore(); var finals = self.getScore();
var totals = self.totalScore(); var totals = self.getMaxScore();
var scoreString = params.endGame.scoreString.replace("@score", finals).replace("@total", totals); var scoreString = params.endGame.scoreString.replace("@score", finals).replace("@total", totals);
var success = ((100 * finals / totals) >= params.passPercentage); var success = ((100 * finals / totals) >= params.passPercentage);
var eventData = { var eventData = {
@ -437,7 +707,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
}; };
var displayResults = function () { var displayResults = function () {
self.triggerXAPICompleted(self.getScore(), self.totalScore(), success); self.triggerXAPICompleted(self.getScore(), self.getMaxScore(), success);
var eparams = { var eparams = {
message: params.endGame.showResultPage ? params.endGame.message : params.endGame.noResultMessage, message: params.endGame.showResultPage ? params.endGame.message : params.endGame.noResultMessage,
@ -528,7 +798,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
}); });
video.play(); video.play();
if (params.endGame.skipButtonText) { if (params.endGame.skippable) {
$('<a class="h5p-joubelui-button h5p-button skip">' + params.endGame.skipButtonText + '</a>').click(function () { $('<a class="h5p-joubelui-button h5p-button skip">' + params.endGame.skipButtonText + '</a>').click(function () {
video.pause(); video.pause();
$videoContainer.hide(); $videoContainer.hide();
@ -544,7 +814,76 @@ H5P.QuestionSet = function (options, contentId, contentData) {
self.trigger('resize'); self.trigger('resize');
}; };
// Function for attaching the multichoice to a DOM element. var registerImageLoadedListener = function (question) {
H5P.on(question, 'imageLoaded', function () {
self.trigger('resize');
});
};
/**
* Initialize a question and attach it to the DOM
*
*/
function initializeQuestion() {
// Attach questions
for (var i = 0; i < questionInstances.length; i++) {
var question = questionInstances[i];
// Make sure styles are not being added twice
$('.question-container:eq(' + i + ')', $myDom).attr('class', 'question-container');
question.attach($('.question-container:eq(' + i + ')', $myDom));
// Listen for image resize
registerImageLoadedListener(question);
// Add finish button
question.addButton('finish', params.texts.finishButton,
moveQuestion.bind(this, 1), false);
// Add next button
question.addButton('next', '', moveQuestion.bind(this, 1),
!params.disableBackwardsNavigation || !!question.getAnswerGiven(), {
href: '#', // Use href since this is a navigation button
'aria-label': params.texts.nextButton
});
// Add previous button
question.addButton('prev', '', moveQuestion.bind(this, -1),
!(questionInstances[0] === question || params.disableBackwardsNavigation), {
href: '#', // Use href since this is a navigation button
'aria-label': params.texts.prevButton
});
// Hide next button if it is the last question
if(questionInstances[questionInstances.length -1] === question) {
question.hideButton('next');
}
question.on('xAPI', function (event) {
var shortVerb = event.getVerb();
if (shortVerb === 'interacted' ||
shortVerb === 'answered' ||
shortVerb === 'attempted') {
toggleAnsweredDot(currentQuestion,
questionInstances[currentQuestion].getAnswerGiven());
_updateButtons();
}
if (shortVerb === 'completed') {
// An activity within this activity is not allowed to send completed events
event.setVerb('answered');
}
if (event.data.statement.context.extensions === undefined) {
event.data.statement.context.extensions = {};
}
event.data.statement.context.extensions['http://id.tincanapi.com/extension/ending-point'] = currentQuestion + 1;
});
// Mark question if answered
toggleAnsweredDot(i, question.getAnswerGiven());
}
}
this.attach = function (target) { this.attach = function (target) {
if (this.isRoot()) { if (this.isRoot()) {
this.setActivityStarted(); this.setActivityStarted();
@ -579,67 +918,8 @@ H5P.QuestionSet = function (options, contentId, contentData) {
}); });
} }
} }
var registerImageLoadedListener = function (question) {
H5P.on(question, 'imageLoaded', function () {
self.trigger('resize');
});
};
// Attach questions initializeQuestion();
for (var i = 0; i < questionInstances.length; i++) {
var question = questionInstances[i];
question.attach($('.question-container:eq(' + i + ')', $myDom));
// Listen for image resize
registerImageLoadedListener(question);
// Add next/finish button
if (questionInstances[questionInstances.length -1] === question) {
// Add finish question set button
question.addButton('finish', params.texts.finishButton,
moveQuestion.bind(this, 1), false);
} else {
// Add next question button
question.addButton('next', '', moveQuestion.bind(this, 1), true, {
href: '#', // Use href since this is a navigation button
'aria-label': params.texts.nextButton
});
}
// Add previous question button
if (questionInstances[0] !== question && !params.disableBackwardsNavigation) {
question.addButton('prev', '', moveQuestion.bind(this, -1), true, {
href: '#', // Use href since this is a navigation button
'aria-label': params.texts.prevButton
});
}
question.on('xAPI', function (event) {
var shortVerb = event.getVerb();
if (shortVerb === 'interacted' ||
shortVerb === 'answered' ||
shortVerb === 'attempted') {
toggleAnsweredDot(currentQuestion,
questionInstances[currentQuestion].getAnswerGiven());
_updateButtons();
}
if (shortVerb === 'completed') {
// An activity within this activity is not allowed to send completed events
event.setVerb('answered');
}
if (event.data.statement.context.extensions === undefined) {
event.data.statement.context.extensions = {};
}
event.data.statement.context.extensions['http://id.tincanapi.com/extension/ending-point'] = currentQuestion + 1;
});
// Mark question if answered
toggleAnsweredDot(i, question.getAnswerGiven());
}
// Allow other libraries to add transitions after the questions have been inited // Allow other libraries to add transitions after the questions have been inited
$('.questionset', $myDom).addClass('started'); $('.questionset', $myDom).addClass('started');
@ -657,9 +937,13 @@ H5P.QuestionSet = function (options, contentId, contentData) {
* @param {Object} [event] * @param {Object} [event]
*/ */
var handleProgressDotClick = function (event) { var handleProgressDotClick = function (event) {
// Disable dots when backward nav disabled
event.preventDefault();
if (params.disableBackwardsNavigation && !showingSolutions) {
return;
}
_stopQuestion(currentQuestion); _stopQuestion(currentQuestion);
_showQuestion($(this).parent().index()); _showQuestion($(this).parent().index());
event.preventDefault();
}; };
// Set event listeners. // Set event listeners.
@ -719,7 +1003,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
}; };
// Get total score possible for questionset. // Get total score possible for questionset.
this.totalScore = function () { this.getMaxScore = function () {
var score = 0; var score = 0;
for (var i = questionInstances.length - 1; i >= 0; i--) { for (var i = questionInstances.length - 1; i >= 0; i--) {
score += questionInstances[i].getMaxScore(); score += questionInstances[i].getMaxScore();
@ -727,6 +1011,14 @@ H5P.QuestionSet = function (options, contentId, contentData) {
return score; return score;
}; };
/**
* @deprecated since version 1.9.2
* @returns {number}
*/
this.totalScore = function () {
return this.getMaxScore();
};
/** /**
* Gather copyright information for the current content. * Gather copyright information for the current content.
* *
@ -821,17 +1113,74 @@ H5P.QuestionSet = function (options, contentId, contentData) {
/** /**
* Returns the complete state of question set and sub-content * Returns the complete state of question set and sub-content
* *
* @returns {Object} * @returns {Object} current state
*/ */
this.getCurrentState = function () { this.getCurrentState = function () {
var state = { return {
progress: currentQuestion, progress: showingSolutions ? questionInstances.length - 1 : currentQuestion,
answers: questionInstances.map(function (qi) { answers: questionInstances.map(function (qi) {
return qi.getCurrentState(); return qi.getCurrentState();
}) }),
order: questionOrder,
poolOrder: poolOrder
};
};
/**
* Generate xAPI object definition used in xAPI statements.
* @return {Object}
*/
var getxAPIDefinition = function () {
var definition = {};
definition.interactionType = 'compound';
definition.type = 'http://adlnet.gov/expapi/activities/cmi.interaction';
definition.description = {
'en-US': ''
}; };
return state; return definition;
};
/**
* Add the question itself to the definition part of an xAPIEvent
*/
var addQuestionToXAPI = function(xAPIEvent) {
var definition = xAPIEvent.getVerifiedStatementValue(['object', 'definition']);
$.extend(definition, getxAPIDefinition());
};
/**
* Get xAPI data from sub content types
*
* @param {Object} metaContentType
* @returns {array}
*/
var getXAPIDataFromChildren = function(metaContentType) {
return metaContentType.getQuestions().map(function(question) {
return question.getXAPIData();
});
};
/**
* Get xAPI data.
* Contract used by report rendering engine.
*
* @see contract at {@link https://h5p.org/documentation/developers/contracts#guides-header-6}
*/
this.getXAPIData = function(){
var xAPIEvent = this.createXAPIEventTemplate('answered');
addQuestionToXAPI(xAPIEvent);
xAPIEvent.setScoredResult(this.getScore(),
this.getMaxScore(),
this,
true,
this.getScore() === this.getMaxScore()
);
return {
statement: xAPIEvent.data.statement,
children: getXAPIDataFromChildren(this)
}
}; };
}; };

View File

@ -107,6 +107,14 @@
"label": "Disable backwards navigation", "label": "Disable backwards navigation",
"description": "This option will only allow you to move forward in Question Set" "description": "This option will only allow you to move forward in Question Set"
}, },
{
"label": "Randomize questions",
"description": "Enable to randomize the order of questions on display."
},
{
"label": "Number of questions to be shown:",
"description": "Create a randomized batch of questions from the total."
},
{ {
"label": "انتهاء المسابقة", "label": "انتهاء المسابقة",
"fields": [ "fields": [

View File

@ -1,7 +1,7 @@
{ {
"semantics": [ "semantics": [
{ {
"label": "Quiz Einführung", "label": "Quiz-Einführung",
"fields": [ "fields": [
{ {
"label": "Zeige Einführung" "label": "Zeige Einführung"
@ -15,7 +15,7 @@
"description": "Dieser Text wird angezeigt, bevor das Quiz anfängt." "description": "Dieser Text wird angezeigt, bevor das Quiz anfängt."
}, },
{ {
"label": "Start Button Text", "label": "Beschriftung des \"Start\"-Buttons",
"default": "Starte Quiz" "default": "Starte Quiz"
}, },
{ {
@ -26,11 +26,11 @@
}, },
{ {
"label": "Hintergrundbild", "label": "Hintergrundbild",
"description": "Ein optionales Hintergrundbild für das Frage Set." "description": "Ein optionales Hintergrundbild für das Fragenset."
}, },
{ {
"label": "Fortschrittsanzeige", "label": "Fortschrittsanzeige",
"description": "Anzeigestil für die Fortschrittsanzeige des Frage Sets.", "description": "Anzeigestil für die Fortschrittsanzeige des Fragensets.",
"options": [ "options": [
{ {
"label": "Text" "label": "Text"
@ -42,7 +42,7 @@
}, },
{ {
"label": "Prozent bearbeitet", "label": "Prozent bearbeitet",
"description": "Prozent der Gesamtpunkte sind notwendig um das Quiz zu bestehen." "description": "Prozentsatz der Gesamtpunkte, die notwendig sind, um das Quiz zu bestehen."
}, },
{ {
"label": "Fragen", "label": "Fragen",
@ -64,53 +64,61 @@
"label": "Anzeigetexte im Quiz", "label": "Anzeigetexte im Quiz",
"fields": [ "fields": [
{ {
"label": "Rückwärts Button", "label": "Beschriftung des \"Zurück\"-Buttons",
"default": "vorherige" "default": "Zurück"
}, },
{ {
"label": "Weiter Button", "label": "Beschriftung des \"Weiter\"-Buttons",
"default": "weiter" "default": "Weiter"
}, },
{ {
"label": "Ende Button", "label": "Beschriftung des \"Beenden\"-Buttons",
"default": "beenden" "default": "Beenden"
}, },
{ {
"label": "Fortschrittstext", "label": "Fortschrittstext",
"description": "Verwendeter Text wenn Text Fortschrittsanzeige gewählt wurde.", "description": "Verwendeter Text, wenn Fortschrittsanzeige in Textform gewählt wurde.",
"default": "Aktuelle Frage: @current von @total Fragen" "default": "Aktuelle Frage: @current von @total Fragen"
}, },
{ {
"label": "Label for jumping to a certain question", "label": "Beschriftung für das Springen zu einem bestimmten Punkt",
"description": "You must use the placeholder '%d' instead of the question number, and %total instead of total amount of questions.", "description": "Nutze den Platzhalter '%d' für die Fragennummer und %total für die Gesamtzahl der Fragen.",
"default": "Question %d of %total" "default": "Frage %d von %total"
}, },
{ {
"label": "Copyright dialog question label", "label": "Beschriftung für eine Frage zum Urheberrechtsdialog",
"default": "Question" "default": "Frage"
}, },
{ {
"label": "Readspeaker progress", "label": "Fortschritt \"Readspeaker\"",
"description": "May use @current and @total question variables", "description": "Variablen: @current und @total",
"default": "Question @current of @total" "default": "Frage @current von @total"
}, },
{ {
"label": "Unanswered question text", "label": "Text für unbeantwortete Fragen",
"default": "Unanswered" "default": "Unbeantwortet"
}, },
{ {
"label": "Answered question text", "label": "Text für beantwortete Fragen",
"default": "Answered" "default": "Beantwortet"
}, },
{ {
"label": "Current question text", "label": "Text fpr aktuelle Frage",
"default": "Current question" "default": "Aktuelle Frage"
} }
] ]
}, },
{ {
"label": "Disable backwards navigation", "label": "Möglichkeit zum Rückwärts-Springen deaktivieren",
"description": "This option will only allow you to move forward in Question Set" "description": "Wenn aktiviert, kann der Nutzer nur vorwärts durch das Fragenset navigieren."
},
{
"label": "Fragen zufällig anordnen",
"description": "Aktivieren, um die Reihenfolge der Fragen zufällig zu bestimmen."
},
{
"label": "Anzahl der anzuzeigenden Fragen:",
"description": "Kann benutzt werden, um eine zufällige Auswahl auf mehreren Fragen zu treffen."
}, },
{ {
"label": "Quiz beendet", "label": "Quiz beendet",
@ -119,101 +127,99 @@
"label": "Ergebnisanzeige" "label": "Ergebnisanzeige"
}, },
{ {
"label": "Display solution button" "label": "Hinweis bei keinen Ergebnissen",
"description": "Text, der am Ende angezeigt wird, falls \"Ergebnisse anzeigen\" deaktiviert ist",
"default": "Beendet"
}, },
{ {
"label": "No results message", "label": "Kopfzeile für die Rückmeldungen",
"description": "Text displayed on end page when \"Display results\" is disabled",
"default": "Finished"
},
{
"label": "Kopfzeile Feedback",
"default": "Dein Ergebnis:", "default": "Dein Ergebnis:",
"description": "diese Kopfzeile wird am Ende des Quiz angezeigt, wenn der Benutzer alle Fragen beantwortet hat." "description": "diese Kopfzeile wird am Ende des Quizzes angezeigt, wenn der Nutzer alle Fragen beantwortet hat."
}, },
{ {
"label": "Punkt Anzeige Text", "label": "Text für die Punkteanzeige",
"description": "Dieser Text wird verwendet um die Gesamtpunkte des Benutzers anzuzeigen. \"@score\" wird durch die errechneten Punkte ersetzt, \"@total\" wird durch die maximal erreichbaren Punkte ersetzt.", "description": "Dieser Text wird verwendet, um die Gesamtpunkte des Nutzers anzuzeigen. \"@score\" wird durch die errechnete Punktzahl ersetzt, \"@total\" wird durch die maximal erreichbare Punktzahl ersetzt.",
"default": "Du hast @score Punkte von @total möglichen." "default": "Du hast @score Punkte von @total möglichen."
}, },
{ {
"label": "Quiz bestanden Mitteilung", "label": "Kopfzeile für \"Quiz bestanden\"",
"default": "Gratulation!", "placeholder": "Glückwunsch!",
"description": "Dieser Text wird oberhalb der Punkte angezeigt, wenn der Benutzer das Quiz erfolgreich abgeschlossen hat." "default": "Glückwunsch!",
"description": "Dieser Text wird oberhalb der Punkte angezeigt, wenn der Nutzer das Quiz erfolgreich abgeschlossen hat."
}, },
{ {
"label": "Bestanden Kommentar", "label": "Kommentar für bestandenes Quiz",
"default": "Gut gemacht!", "default": "Gut gemacht!",
"description": "dieser Kommentar wird nach den Punkten angezeigt, wenn der Benutzer das Quiz erfolgreich bestanden hat." "description": "Dieser Kommentar wird nach den Punkten angezeigt, wenn der Nutzer das Quiz erfolgreich bestanden hat."
}, },
{ {
"label": "Quiz nicht bestanden Titel", "label": "Kopfzeile für nicht bestandenes Quiz",
"default": "Diese Mal hast du nicht bestanden.", "default": "Diese Mal hast du nicht bestanden.",
"description": "dieser Text wird oberhalb der Punkte angezeigt, wenn der Benutzer das Quiz nicht bestanden hat." "description": "Dieser Text wird oberhalb der Punkte angezeigt, wenn der Nutzer das Quiz nicht bestanden hat."
}, },
{ {
"label": "Nicht bestanden Kommentar", "label": "Kommentar für nicht bestandenes Quiz",
"default": "Versuche es noch einmal!", "default": "Versuche es noch einmal!",
"description": "Dieser Kommentar wird nach den Punkten angezeigt, wenn der Benutzer das Quiz nicht bestanden hat." "description": "Dieser Kommentar wird nach den Punkten angezeigt, wenn der Nutzer das Quiz nicht bestanden hat."
}, },
{ {
"label": "Lösungs Button Beschriftung", "label": "Beschriftung des \"Lösung zeigen\"-Buttons",
"default": "Zeige die Lösung", "default": "Lösung zeigen",
"description": "Text für den Lösungs Button." "description": "Beschriftung des \"Lösung zeigen\"-Buttons"
}, },
{ {
"label": "Wiederholen Button Beschriftung", "label": "Beschriftung des \"Wiederholen\"-Buttons",
"default": "Versuch es nochmal", "default": "Wiederholen",
"description": "Text für den Wiederholen Button." "description": "Beschriftung des \"Wiederholen\"-Buttons"
}, },
{ {
"label": "Beende Button Text", "label": "Beschriftung des \"Beenden\"-Buttons",
"default": "Beenden" "default": "Beenden"
}, },
{ {
"label": "Zeige Video vor den Quizergebnissen" "label": "Zeige Video vor den Quizergebnissen"
}, },
{ {
"label": "Aktiviere Skip Video Button" "label": "Aktiviere \"Video überspringen\"-Button"
}, },
{ {
"label": "Skip Video Button Beschriftung", "label": "Beschriftung des \"Video überspringen\"-Buttons",
"default": "Überspringe Video" "default": "Video überspringen"
}, },
{ {
"label": "Bestanden Video", "label": "Bestanden-Video",
"description": "Dieses Video wird angezeigt, wenn der Benutzer das Quiz erfolgreich bestanden hat." "description": "Dieses Video wird angezeigt, wenn der Nutzer das Quiz erfolgreich bestanden hat."
}, },
{ {
"label": "Nicht bestanden Video", "label": "Nicht-bestanden-Video",
"description": "Dieses Video wird angezeigt, wenn der Benutzer das Quiz nicht bestanden hat." "description": "Dieses Video wird angezeigt, wenn der Nutzer das Quiz nicht bestanden hat."
} }
] ]
}, },
{ {
"label": "Einstellungen für \"Zeige die Lösung\" Button und \"Nochmal\".", "label": "Einstellungen für \"Lösung zeigen\"-Button und \"Nochmal\".",
"fields": [ "fields": [
{ {
"label": "Override \"Show Solution\" button", "label": "Überschreiben des \"Lösungen anzeigen\"-Buttons",
"description": "This option determines if the \"Show Solution\" button will be shown for all questions, disabled for all or configured for each question individually.", "description": "Diese Option gibt an, ob der \"Lösung anzeigen\"-Button für alle Fragen angezeigt, ausgeblendet oder für jede Frage individuell konfiguriert wird.",
"options": [ "options": [
{ {
"label": "Enabled" "label": "Anzeigen"
}, },
{ {
"label": "Disabled" "label": "Ausblenden"
} }
] ]
}, },
{ {
"label": "Override \"Retry\" button", "label": "Überschreiben des \"Wiederholen\"-Buttons",
"description": "This option determines if the \"Retry\" button will be shown for all questions, disabled for all or configured for each question individually.", "description": "Diese Option gibt an, ob der \"Wiederholen\" Button für alle Fragen angezeigt, ausgeblendet oder für jede Frage individuell konfiguriert wird.",
"options": [ "options": [
{ {
"label": "Enabled" "label": "Anzeigen"
}, },
{ {
"label": "Disabled" "label": "Ausblenden"
} }
] ]
} }

View File

@ -109,8 +109,16 @@
] ]
}, },
{ {
"label": "Disable backwards navigation", "label": "Désactiver la possibilité de naviguer en arrière",
"description": "This option will only allow you to move forward in Question Set" "description": "Cette option ne permettra plus que la navigation en avant au sein du module Question Set"
},
{
"label": "Afficher les question dans un ordre aléatoire",
"description": "Ceci permet d'afficher les questions dans un ordre aléatoire."
},
{
"label": "Nombre de questions à afficher:",
"description": "Génère aléatoire un jeu de question parmi toutes les questions disponibles."
}, },
{ {
"label": "Quiz terminé", "label": "Quiz terminé",

View File

@ -107,6 +107,14 @@
"label": "Disable backwards navigation", "label": "Disable backwards navigation",
"description": "This option will only allow you to move forward in Question Set" "description": "This option will only allow you to move forward in Question Set"
}, },
{
"label": "Randomize questions",
"description": "Enable to randomize the order of questions on display."
},
{
"label": "Number of questions to be shown:",
"description": "Create a randomized batch of questions from the total."
},
{ {
"label": "Quiz terminato", "label": "Quiz terminato",
"fields": [ "fields": [

View File

@ -47,14 +47,17 @@
{ {
"label": "Spørsmål", "label": "Spørsmål",
"entity": "spørsmål", "entity": "spørsmål",
"widgets": [
{
"label": "Standard"
},
{
"label": "Tekstlig"
}
],
"field": { "field": {
"label": "Spørsmål", "label": "Spørsmåltype",
"fields": [ "description": "Velg spørsmålstype for dette spørsmålet"
{
"label": "Spørsmålstype",
"description": "Velg spørsmålstype for dette spørsmålet"
}
]
} }
}, },
{ {
@ -109,6 +112,14 @@
"label": "Slå av bakoverknapp", "label": "Slå av bakoverknapp",
"description": "Slå på for å nekte å gå tilbake i Question Set" "description": "Slå på for å nekte å gå tilbake i Question Set"
}, },
{
"label": "Randomize questions",
"description": "Enable to randomize the order of questions on display."
},
{
"label": "Number of questions to be shown:",
"description": "Create a randomized batch of questions from the total."
},
{ {
"label": "Spørsmålssett avslutning", "label": "Spørsmålssett avslutning",
"fields": [ "fields": [

View File

@ -47,14 +47,17 @@
{ {
"label": "Spørsmål", "label": "Spørsmål",
"entity": "spørsmål", "entity": "spørsmål",
"widgets": [
{
"label": "Standard"
},
{
"label": "Tekstlig"
}
],
"field": { "field": {
"label": "Spørsmål", "label": "Spørsmålstype",
"fields": [ "description": "Velg spørsmålstype for dette spørsmålet"
{
"label": "Spørsmålstype",
"description": "Velg spørsmålstype for dette spørsmålet"
}
]
} }
}, },
{ {
@ -109,6 +112,14 @@
"label": "Slå av bakoverknapp", "label": "Slå av bakoverknapp",
"description": "Slå på for å nekte å gå tilbake i Question Set" "description": "Slå på for å nekte å gå tilbake i Question Set"
}, },
{
"label": "Randomize questions",
"description": "Enable to randomize the order of questions on display."
},
{
"label": "Number of questions to be shown:",
"description": "Create a randomized batch of questions from the total."
},
{ {
"label": "Spørsmålssett avslutning", "label": "Spørsmålssett avslutning",
"fields": [ "fields": [

View File

@ -3,15 +3,15 @@
"description": "Put together a set of different questions that has to be solved. (Quiz)", "description": "Put together a set of different questions that has to be solved. (Quiz)",
"contentType": "question", "contentType": "question",
"majorVersion": 1, "majorVersion": 1,
"minorVersion": 9, "minorVersion": 13,
"patchVersion": 1, "patchVersion": 0,
"embedTypes": [ "embedTypes": [
"iframe" "iframe"
], ],
"runnable": 1, "runnable": 1,
"fullscreen": 0, "fullscreen": 0,
"machineName": "H5P.QuestionSet", "machineName": "H5P.QuestionSet",
"author": "Joubel AS", "author": "Joubel",
"coreApi": { "coreApi": {
"majorVersion": 1, "majorVersion": 1,
"minorVersion": 6 "minorVersion": 6
@ -53,12 +53,12 @@
{ {
"machineName": "H5PEditor.VerticalTabs", "machineName": "H5PEditor.VerticalTabs",
"majorVersion": 1, "majorVersion": 1,
"minorVersion": 2 "minorVersion": 3
}, },
{ {
"machineName": "H5PEditor.QuestionSetTextualEditor", "machineName": "H5PEditor.QuestionSetTextualEditor",
"majorVersion": 1, "majorVersion": 1,
"minorVersion": 1 "minorVersion": 2
} }
] ]
} }

View File

@ -3,16 +3,19 @@
"name": "introPage", "name": "introPage",
"type": "group", "type": "group",
"label": "Quiz introduction", "label": "Quiz introduction",
"importance": "medium",
"fields": [ "fields": [
{ {
"name": "showIntroPage", "name": "showIntroPage",
"type": "boolean", "type": "boolean",
"label": "Display introduction" "label": "Display introduction",
"importance": "low"
}, },
{ {
"name": "title", "name": "title",
"type": "text", "type": "text",
"label": "Title", "label": "Title",
"importance": "high",
"optional": true, "optional": true,
"description": "This title will be displayed above the introduction text.", "description": "This title will be displayed above the introduction text.",
"tags": [ "tags": [
@ -27,6 +30,7 @@
"type": "text", "type": "text",
"widget": "html", "widget": "html",
"label": "Introduction text", "label": "Introduction text",
"importance": "medium",
"optional": true, "optional": true,
"description": "This text will be displayed before the quiz starts.", "description": "This text will be displayed before the quiz starts.",
"enterMode": "p", "enterMode": "p",
@ -42,6 +46,7 @@
"name": "startButtonText", "name": "startButtonText",
"type": "text", "type": "text",
"label": "Start button text", "label": "Start button text",
"importance": "low",
"optional": true, "optional": true,
"default": "Start Quiz" "default": "Start Quiz"
}, },
@ -49,6 +54,7 @@
"name": "backgroundImage", "name": "backgroundImage",
"type": "image", "type": "image",
"label": "Background image", "label": "Background image",
"importance": "low",
"optional": true, "optional": true,
"description": "An optional background image for the introduction." "description": "An optional background image for the introduction."
} }
@ -58,6 +64,7 @@
"name": "backgroundImage", "name": "backgroundImage",
"type": "image", "type": "image",
"label": "Background image", "label": "Background image",
"importance": "low",
"optional": true, "optional": true,
"description": "An optional background image for the Question set." "description": "An optional background image for the Question set."
}, },
@ -65,6 +72,7 @@
"name": "progressType", "name": "progressType",
"type": "select", "type": "select",
"label": "Progress indicator", "label": "Progress indicator",
"importance": "low",
"description": "Question set progress indicator style.", "description": "Question set progress indicator style.",
"options": [ "options": [
{ {
@ -82,6 +90,7 @@
"name": "passPercentage", "name": "passPercentage",
"type": "number", "type": "number",
"label": "Pass percentage", "label": "Pass percentage",
"importance": "low",
"description": "Percentage of Total score required for passing the quiz.", "description": "Percentage of Total score required for passing the quiz.",
"min": 0, "min": 0,
"max": 100, "max": 100,
@ -91,6 +100,7 @@
{ {
"name": "questions", "name": "questions",
"label": "Questions", "label": "Questions",
"importance": "high",
"type": "list", "type": "list",
"widgets": [ "widgets": [
{ {
@ -108,13 +118,15 @@
"name": "question", "name": "question",
"type": "library", "type": "library",
"label": "Question type", "label": "Question type",
"importance": "high",
"description": "Library for this question.", "description": "Library for this question.",
"options": [ "options": [
"H5P.MultiChoice 1.8", "H5P.MultiChoice 1.9",
"H5P.DragQuestion 1.7", "H5P.DragQuestion 1.10",
"H5P.Blanks 1.7", "H5P.Blanks 1.7",
"H5P.MarkTheWords 1.6", "H5P.MarkTheWords 1.6",
"H5P.DragText 1.5" "H5P.DragText 1.5",
"H5P.TrueFalse 1.1"
] ]
} }
}, },
@ -122,30 +134,35 @@
"name": "texts", "name": "texts",
"type": "group", "type": "group",
"label": "Interface texts in quiz", "label": "Interface texts in quiz",
"importance": "low",
"common": true, "common": true,
"fields": [ "fields": [
{ {
"name": "prevButton", "name": "prevButton",
"type": "text", "type": "text",
"label": "Back button", "label": "Back button",
"importance": "low",
"default": "Previous question" "default": "Previous question"
}, },
{ {
"name": "nextButton", "name": "nextButton",
"type": "text", "type": "text",
"label": "Next button", "label": "Next button",
"importance": "low",
"default": "Next question" "default": "Next question"
}, },
{ {
"name": "finishButton", "name": "finishButton",
"type": "text", "type": "text",
"label": "Finish button", "label": "Finish button",
"importance": "low",
"default": "Finish" "default": "Finish"
}, },
{ {
"name": "textualProgress", "name": "textualProgress",
"type": "text", "type": "text",
"label": "Progress text", "label": "Progress text",
"importance": "low",
"description": "Text used if textual progress is selected.", "description": "Text used if textual progress is selected.",
"default": "Question: @current of @total questions", "default": "Question: @current of @total questions",
"tags": [ "tags": [
@ -157,6 +174,7 @@
"name": "jumpToQuestion", "name": "jumpToQuestion",
"type": "text", "type": "text",
"label": "Label for jumping to a certain question", "label": "Label for jumping to a certain question",
"importance": "low",
"description": "You must use the placeholder '%d' instead of the question number, and %total instead of total amount of questions.", "description": "You must use the placeholder '%d' instead of the question number, and %total instead of total amount of questions.",
"default": "Question %d of %total" "default": "Question %d of %total"
}, },
@ -164,12 +182,14 @@
"name": "questionLabel", "name": "questionLabel",
"type": "text", "type": "text",
"label": "Copyright dialog question label", "label": "Copyright dialog question label",
"importance": "low",
"default": "Question" "default": "Question"
}, },
{ {
"name": "readSpeakerProgress", "name": "readSpeakerProgress",
"type": "text", "type": "text",
"label": "Readspeaker progress", "label": "Readspeaker progress",
"importance": "low",
"description": "May use @current and @total question variables", "description": "May use @current and @total question variables",
"default": "Question @current of @total" "default": "Question @current of @total"
}, },
@ -177,18 +197,21 @@
"name": "unansweredText", "name": "unansweredText",
"type": "text", "type": "text",
"label": "Unanswered question text", "label": "Unanswered question text",
"importance": "low",
"default": "Unanswered" "default": "Unanswered"
}, },
{ {
"name": "answeredText", "name": "answeredText",
"type": "text", "type": "text",
"label": "Answered question text", "label": "Answered question text",
"importance": "low",
"default": "Answered" "default": "Answered"
}, },
{ {
"name": "currentQuestionText", "name": "currentQuestionText",
"type": "text", "type": "text",
"label": "Current question text", "label": "Current question text",
"importance": "low",
"default": "Current question" "default": "Current question"
} }
] ]
@ -197,19 +220,39 @@
"name": "disableBackwardsNavigation", "name": "disableBackwardsNavigation",
"type": "boolean", "type": "boolean",
"label": "Disable backwards navigation", "label": "Disable backwards navigation",
"importance": "low",
"description": "This option will only allow you to move forward in Question Set", "description": "This option will only allow you to move forward in Question Set",
"optional": true, "optional": true,
"default": false "default": false
}, },
{
"name": "randomQuestions",
"type": "boolean",
"label": "Randomize questions",
"importance": "low",
"description": "Enable to randomize the order of questions on display.",
"default": false
},
{
"name": "poolSize",
"type": "number",
"min": 1,
"label": "Number of questions to be shown:",
"importance": "low",
"description": "Create a randomized batch of questions from the total.",
"optional": true
},
{ {
"name": "endGame", "name": "endGame",
"type": "group", "type": "group",
"label": "Quiz finished", "label": "Quiz finished",
"importance": "medium",
"fields": [ "fields": [
{ {
"name": "showResultPage", "name": "showResultPage",
"type": "boolean", "type": "boolean",
"label": "Display results", "label": "Display results",
"importance": "low",
"default": true "default": true
}, },
{ {
@ -222,6 +265,7 @@
"name": "noResultMessage", "name": "noResultMessage",
"type": "text", "type": "text",
"label": "No results message", "label": "No results message",
"importance": "low",
"description": "Text displayed on end page when \"Display results\" is disabled", "description": "Text displayed on end page when \"Display results\" is disabled",
"default": "Finished", "default": "Finished",
"optional": true "optional": true
@ -230,6 +274,7 @@
"name": "message", "name": "message",
"type": "text", "type": "text",
"label": "Feedback heading", "label": "Feedback heading",
"importance": "low",
"default": "Your result:", "default": "Your result:",
"optional": true, "optional": true,
"description": "This heading will be displayed at the end of the quiz when the user has answered all questions.", "description": "This heading will be displayed at the end of the quiz when the user has answered all questions.",
@ -242,6 +287,7 @@
"name": "scoreString", "name": "scoreString",
"type": "text", "type": "text",
"label": "Score display text", "label": "Score display text",
"importance": "low",
"description": "Text used to display Total user score. \"@score\" will be replaced by calculated score, \"@total\" will be replaced by maximum possible score. ", "description": "Text used to display Total user score. \"@score\" will be replaced by calculated score, \"@total\" will be replaced by maximum possible score. ",
"default": "You got @score of @total points", "default": "You got @score of @total points",
"optional": true "optional": true
@ -250,6 +296,7 @@
"name": "successGreeting", "name": "successGreeting",
"type": "text", "type": "text",
"label": "Quiz passed greeting", "label": "Quiz passed greeting",
"importance": "low",
"placeholder": "Congratulations!", "placeholder": "Congratulations!",
"default": "Congratulations!", "default": "Congratulations!",
"optional": true, "optional": true,
@ -264,6 +311,7 @@
"type": "text", "type": "text",
"widget": "html", "widget": "html",
"label": "Passed comment", "label": "Passed comment",
"importance": "low",
"default": "You did very well!", "default": "You did very well!",
"optional": true, "optional": true,
"description": "This comment will be displayed after the score if the user has successfully passed the quiz.", "description": "This comment will be displayed after the score if the user has successfully passed the quiz.",
@ -280,6 +328,7 @@
"name": "failGreeting", "name": "failGreeting",
"type": "text", "type": "text",
"label": "Quiz failed title", "label": "Quiz failed title",
"importance": "low",
"default": "You did not pass this time.", "default": "You did not pass this time.",
"optional": true, "optional": true,
"description": "This text will be displayed above the score if the user has failed the quiz.", "description": "This text will be displayed above the score if the user has failed the quiz.",
@ -293,6 +342,7 @@
"type": "text", "type": "text",
"widget": "html", "widget": "html",
"label": "Failed comment", "label": "Failed comment",
"importance": "low",
"default": "Have another try!", "default": "Have another try!",
"optional": true, "optional": true,
"description": "This comment will be displayed after the score if the user has failed the quiz.", "description": "This comment will be displayed after the score if the user has failed the quiz.",
@ -309,6 +359,7 @@
"name": "solutionButtonText", "name": "solutionButtonText",
"type": "text", "type": "text",
"label": "Solution button label", "label": "Solution button label",
"importance": "low",
"default": "Show solution", "default": "Show solution",
"description": "Text for the solution button." "description": "Text for the solution button."
}, },
@ -316,6 +367,7 @@
"name": "retryButtonText", "name": "retryButtonText",
"type": "text", "type": "text",
"label": "Retry button label", "label": "Retry button label",
"importance": "low",
"default": "Retry", "default": "Retry",
"description": "Text for the retry button." "description": "Text for the retry button."
}, },
@ -323,28 +375,33 @@
"name": "finishButtonText", "name": "finishButtonText",
"type": "text", "type": "text",
"label": "Finish button text", "label": "Finish button text",
"importance": "low",
"default": "Finish" "default": "Finish"
}, },
{ {
"name": "showAnimations", "name": "showAnimations",
"type": "boolean", "type": "boolean",
"label": "Display video before quiz results" "label": "Display video before quiz results",
"importance": "low"
}, },
{ {
"name": "skippable", "name": "skippable",
"type": "boolean", "type": "boolean",
"label": "Enable skip video button" "label": "Enable skip video button",
"importance": "low"
}, },
{ {
"name": "skipButtonText", "name": "skipButtonText",
"type": "text", "type": "text",
"label": "Skip video button label", "label": "Skip video button label",
"importance": "low",
"default": "Skip video" "default": "Skip video"
}, },
{ {
"name": "successVideo", "name": "successVideo",
"type": "video", "type": "video",
"label": "Passed video", "label": "Passed video",
"importance": "low",
"optional": true, "optional": true,
"description": "This video will be played if the user successfully passed the quiz." "description": "This video will be played if the user successfully passed the quiz."
}, },
@ -352,6 +409,7 @@
"name": "failVideo", "name": "failVideo",
"type": "video", "type": "video",
"label": "Fail video", "label": "Fail video",
"importance": "low",
"optional": true, "optional": true,
"description": "This video will be played if the user failes the quiz." "description": "This video will be played if the user failes the quiz."
} }
@ -361,12 +419,14 @@
"name": "override", "name": "override",
"type": "group", "type": "group",
"label": "Settings for \"Show solution\" and \"Retry\" buttons", "label": "Settings for \"Show solution\" and \"Retry\" buttons",
"importance": "low",
"optional": true, "optional": true,
"fields": [ "fields": [
{ {
"name": "showSolutionButton", "name": "showSolutionButton",
"type": "select", "type": "select",
"label": "Override \"Show Solution\" button", "label": "Override \"Show Solution\" button",
"importance": "low",
"description": "This option determines if the \"Show Solution\" button will be shown for all questions, disabled for all or configured for each question individually.", "description": "This option determines if the \"Show Solution\" button will be shown for all questions, disabled for all or configured for each question individually.",
"optional": true, "optional": true,
"options": [ "options": [
@ -384,6 +444,7 @@
"name": "retryButton", "name": "retryButton",
"type": "select", "type": "select",
"label": "Override \"Retry\" button", "label": "Override \"Retry\" button",
"importance": "low",
"description": "This option determines if the \"Retry\" button will be shown for all questions, disabled for all or configured for each question individually.", "description": "This option determines if the \"Retry\" button will be shown for all questions, disabled for all or configured for each question individually.",
"optional": true, "optional": true,
"options": [ "options": [
@ -399,4 +460,4 @@
} }
] ]
} }
] ]