HFP-29 Merge with master
commit
9cf00d897d
|
@ -1,2 +1,3 @@
|
|||
*~
|
||||
/nbproject/private/
|
||||
/nbproject/private/
|
||||
.idea
|
10
README.md
10
README.md
|
@ -1,16 +1,16 @@
|
|||
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
|
||||
|
||||
(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:
|
||||
|
||||
|
||||
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.
|
||||
|
|
|
@ -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 {
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
|
@ -52,7 +40,12 @@
|
|||
background: #fff;
|
||||
background: #cecece;
|
||||
}
|
||||
.progress-dot:hover {
|
||||
|
||||
.progress-dot.disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.progress-dot:not(.disabled):hover {
|
||||
box-shadow: 0 0 0.5em #c7c7c7;
|
||||
}
|
||||
.progress-dot.answered {
|
||||
|
@ -61,6 +54,11 @@
|
|||
.progress-dot.current {
|
||||
background: #285585;
|
||||
}
|
||||
|
||||
.progress-dot.disabled:focus {
|
||||
outline: none
|
||||
}
|
||||
|
||||
.progress-dot:focus {
|
||||
outline-color: rgb(40, 130, 211);
|
||||
outline-width: thin;
|
||||
|
@ -151,6 +149,12 @@
|
|||
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-finish {
|
||||
margin: 0 0 1.5em 0.5em;
|
||||
|
|
Binary file not shown.
|
@ -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=" " d="" horiz-adv-x="512" />
|
||||
<glyph unicode="" 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="" 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="" 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="" 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.
|
@ -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 |
|
@ -1,4 +1,4 @@
|
|||
var H5P = H5P || {};
|
||||
H5P = H5P || {};
|
||||
|
||||
/**
|
||||
* 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-progress">' +
|
||||
' <% if (progressType == "dots" && !disableBackwardsNavigation) { %>' +
|
||||
' <% if (progressType == "dots") { %>' +
|
||||
' <ul class="dots-container" role="navigation">' +
|
||||
' <% for (var i=0; i<questions.length; i++) { %>' +
|
||||
' <li class="progress-item"><a href="#" class="progress-dot unanswered" ' +
|
||||
' aria-label="<%=' +
|
||||
' texts.jumpToQuestion.replace("%d", i + 1).replace("%total", questions.length)' +
|
||||
' + ", " + texts.unansweredText' +
|
||||
' %>" tabindex="-1"></a></li>' +
|
||||
' <li class="progress-item">' +
|
||||
' <a href="#" ' +
|
||||
' class="progress-dot unanswered<%' +
|
||||
' if (disableBackwardsNavigation) { %> disabled <% } %>"' +
|
||||
' aria-label="<%=' +
|
||||
' texts.jumpToQuestion.replace("%d", i + 1).replace("%total", questions.length)' +
|
||||
' + ", " + texts.unansweredText %>" tabindex="-1" ' +
|
||||
' <% if (disableBackwardsNavigation) { %> aria-disabled="true" <% } %>' +
|
||||
' ></a>' +
|
||||
' </li>' +
|
||||
' <% } %>' +
|
||||
' </div>' +
|
||||
' <% } else if (progressType == "textual") { %>' +
|
||||
|
@ -81,7 +86,6 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
'</div>';
|
||||
|
||||
var defaults = {
|
||||
randomOrder: false,
|
||||
initialQuestion: 0,
|
||||
progressType: 'dots',
|
||||
passPercentage: 50,
|
||||
|
@ -126,18 +130,100 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
var endTemplate = new EJS({text: resulttemplate});
|
||||
var params = $.extend(true, {}, defaults, options);
|
||||
|
||||
var initialParams = $.extend(true, {}, defaults, options);
|
||||
var poolOrder; // Order of questions in a pool
|
||||
var currentQuestion = 0;
|
||||
var questionInstances = [];
|
||||
var questionOrder; //Stores order of questions to allow resuming of question set
|
||||
var $myDom;
|
||||
var scoreBar;
|
||||
var up;
|
||||
var renderSolutions = false;
|
||||
var showingSolutions = false;
|
||||
contentData = contentData || {};
|
||||
|
||||
// Bring question set up to date when resuming
|
||||
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));
|
||||
|
||||
// Set overrides for questions
|
||||
var override;
|
||||
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++) {
|
||||
var question = params.questions[i];
|
||||
/**
|
||||
* Generates question instances from H5P objects
|
||||
*
|
||||
* @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) {
|
||||
// Extend subcontent with the overrided settings.
|
||||
$.extend(question.params.behaviour, override);
|
||||
var question;
|
||||
// If a previous order exists, use it
|
||||
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 || {};
|
||||
question.params.overrideSettings = question.params.overrideSettings || {};
|
||||
question.params.overrideSettings.$confirmationDialogParent = $template.last();
|
||||
question.params.overrideSettings.instance = this;
|
||||
var questionInstance = H5P.newRunnable(question, contentId, undefined, undefined,
|
||||
{
|
||||
previousState: contentData.previousState ? contentData.previousState.answers[i] : undefined,
|
||||
parent: self
|
||||
});
|
||||
questionInstance.on('resize', function () {
|
||||
up = true;
|
||||
self.trigger('resize');
|
||||
});
|
||||
questionInstances.push(questionInstance);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Create question instances from questions given by params
|
||||
questionInstances = createQuestionInstancesFromQuestions(params.questions);
|
||||
|
||||
// Randomize questions only on instantiation
|
||||
if (params.randomQuestions && contentData.previousState === undefined) {
|
||||
var result = randomizeQuestionOrdering(questionInstances);
|
||||
questionInstances = result.questions;
|
||||
questionOrder = result.questionOrder;
|
||||
}
|
||||
|
||||
// Resize all interactions on resize
|
||||
|
@ -195,6 +313,17 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
|
||||
// Update button state.
|
||||
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;
|
||||
for (var i = questionInstances.length - 1; i >= 0; i--) {
|
||||
answered = answered && (questionInstances[i]).getAnswerGiven();
|
||||
|
@ -284,7 +413,18 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
* @public
|
||||
*/
|
||||
var showSolutions = function () {
|
||||
showingSolutions = true;
|
||||
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 {
|
||||
// Do not read answers
|
||||
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.
|
||||
* Used for contracts with integrated content.
|
||||
* @public
|
||||
*/
|
||||
var resetTask = function () {
|
||||
|
||||
// Clear previous state to ensure questions are created cleanly
|
||||
contentData.previousState = [];
|
||||
|
||||
showingSolutions = false;
|
||||
|
||||
for (var i = 0; i < questionInstances.length; i++) {
|
||||
try {
|
||||
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) {
|
||||
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
|
||||
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;
|
||||
|
@ -332,18 +533,86 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
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) {
|
||||
if (params.disableBackwardsNavigation && !questionInstances[currentQuestion].getAnswerGiven()) {
|
||||
questionInstances[currentQuestion].hideButton('next');
|
||||
questionInstances[currentQuestion].hideButton('finish');
|
||||
return;
|
||||
}
|
||||
|
||||
_stopQuestion(currentQuestion);
|
||||
if (currentQuestion + direction >= questionInstances.length) {
|
||||
_displayEndGame();
|
||||
|
||||
}
|
||||
else if (!params.disableBackwardsNavigation || questionInstances[currentQuestion].getAnswerGiven()) {
|
||||
// Allow movement if backward navigation enabled or answer given
|
||||
_showQuestion(currentQuestion + direction);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
var disabledTabindex = params.disableBackwardsNavigation && !showingSolutions;
|
||||
$el.toggleClass('current', isCurrent)
|
||||
.attr('aria-label', label)
|
||||
.attr('tabindex', isCurrent ? 0 : -1);
|
||||
.attr('tabindex', isCurrent && !disabledTabindex ? 0 : -1);
|
||||
};
|
||||
|
||||
var _displayEndGame = function () {
|
||||
|
@ -412,7 +682,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
|
||||
// Get total score.
|
||||
var finals = self.getScore();
|
||||
var totals = self.totalScore();
|
||||
var totals = self.getMaxScore();
|
||||
var scoreString = params.endGame.scoreString.replace("@score", finals).replace("@total", totals);
|
||||
var success = ((100 * finals / totals) >= params.passPercentage);
|
||||
var eventData = {
|
||||
|
@ -437,7 +707,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
};
|
||||
|
||||
var displayResults = function () {
|
||||
self.triggerXAPICompleted(self.getScore(), self.totalScore(), success);
|
||||
self.triggerXAPICompleted(self.getScore(), self.getMaxScore(), success);
|
||||
|
||||
var eparams = {
|
||||
message: params.endGame.showResultPage ? params.endGame.message : params.endGame.noResultMessage,
|
||||
|
@ -528,7 +798,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
});
|
||||
video.play();
|
||||
|
||||
if (params.endGame.skipButtonText) {
|
||||
if (params.endGame.skippable) {
|
||||
$('<a class="h5p-joubelui-button h5p-button skip">' + params.endGame.skipButtonText + '</a>').click(function () {
|
||||
video.pause();
|
||||
$videoContainer.hide();
|
||||
|
@ -544,7 +814,76 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
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) {
|
||||
if (this.isRoot()) {
|
||||
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
|
||||
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());
|
||||
}
|
||||
initializeQuestion();
|
||||
|
||||
// Allow other libraries to add transitions after the questions have been inited
|
||||
$('.questionset', $myDom).addClass('started');
|
||||
|
@ -657,9 +937,13 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
* @param {Object} [event]
|
||||
*/
|
||||
var handleProgressDotClick = function (event) {
|
||||
// Disable dots when backward nav disabled
|
||||
event.preventDefault();
|
||||
if (params.disableBackwardsNavigation && !showingSolutions) {
|
||||
return;
|
||||
}
|
||||
_stopQuestion(currentQuestion);
|
||||
_showQuestion($(this).parent().index());
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
// Set event listeners.
|
||||
|
@ -719,7 +1003,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
};
|
||||
|
||||
// Get total score possible for questionset.
|
||||
this.totalScore = function () {
|
||||
this.getMaxScore = function () {
|
||||
var score = 0;
|
||||
for (var i = questionInstances.length - 1; i >= 0; i--) {
|
||||
score += questionInstances[i].getMaxScore();
|
||||
|
@ -727,6 +1011,14 @@ H5P.QuestionSet = function (options, contentId, contentData) {
|
|||
return score;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated since version 1.9.2
|
||||
* @returns {number}
|
||||
*/
|
||||
this.totalScore = function () {
|
||||
return this.getMaxScore();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 {Object}
|
||||
* @returns {Object} current state
|
||||
*/
|
||||
this.getCurrentState = function () {
|
||||
var state = {
|
||||
progress: currentQuestion,
|
||||
return {
|
||||
progress: showingSolutions ? questionInstances.length - 1 : currentQuestion,
|
||||
answers: questionInstances.map(function (qi) {
|
||||
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)
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -107,6 +107,14 @@
|
|||
"label": "Disable backwards navigation",
|
||||
"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": "انتهاء المسابقة",
|
||||
"fields": [
|
||||
|
|
146
language/de.json
146
language/de.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"semantics": [
|
||||
{
|
||||
"label": "Quiz Einführung",
|
||||
"label": "Quiz-Einführung",
|
||||
"fields": [
|
||||
{
|
||||
"label": "Zeige Einführung"
|
||||
|
@ -15,7 +15,7 @@
|
|||
"description": "Dieser Text wird angezeigt, bevor das Quiz anfängt."
|
||||
},
|
||||
{
|
||||
"label": "Start Button Text",
|
||||
"label": "Beschriftung des \"Start\"-Buttons",
|
||||
"default": "Starte Quiz"
|
||||
},
|
||||
{
|
||||
|
@ -26,11 +26,11 @@
|
|||
},
|
||||
{
|
||||
"label": "Hintergrundbild",
|
||||
"description": "Ein optionales Hintergrundbild für das Frage Set."
|
||||
"description": "Ein optionales Hintergrundbild für das Fragenset."
|
||||
},
|
||||
{
|
||||
"label": "Fortschrittsanzeige",
|
||||
"description": "Anzeigestil für die Fortschrittsanzeige des Frage Sets.",
|
||||
"description": "Anzeigestil für die Fortschrittsanzeige des Fragensets.",
|
||||
"options": [
|
||||
{
|
||||
"label": "Text"
|
||||
|
@ -42,7 +42,7 @@
|
|||
},
|
||||
{
|
||||
"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",
|
||||
|
@ -64,53 +64,61 @@
|
|||
"label": "Anzeigetexte im Quiz",
|
||||
"fields": [
|
||||
{
|
||||
"label": "Rückwärts Button",
|
||||
"default": "vorherige"
|
||||
"label": "Beschriftung des \"Zurück\"-Buttons",
|
||||
"default": "Zurück"
|
||||
},
|
||||
{
|
||||
"label": "Weiter Button",
|
||||
"default": "weiter"
|
||||
"label": "Beschriftung des \"Weiter\"-Buttons",
|
||||
"default": "Weiter"
|
||||
},
|
||||
{
|
||||
"label": "Ende Button",
|
||||
"default": "beenden"
|
||||
"label": "Beschriftung des \"Beenden\"-Buttons",
|
||||
"default": "Beenden"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"label": "Label for jumping to a certain question",
|
||||
"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"
|
||||
"label": "Beschriftung für das Springen zu einem bestimmten Punkt",
|
||||
"description": "Nutze den Platzhalter '%d' für die Fragennummer und %total für die Gesamtzahl der Fragen.",
|
||||
"default": "Frage %d von %total"
|
||||
},
|
||||
{
|
||||
"label": "Copyright dialog question label",
|
||||
"default": "Question"
|
||||
"label": "Beschriftung für eine Frage zum Urheberrechtsdialog",
|
||||
"default": "Frage"
|
||||
},
|
||||
{
|
||||
"label": "Readspeaker progress",
|
||||
"description": "May use @current and @total question variables",
|
||||
"default": "Question @current of @total"
|
||||
"label": "Fortschritt \"Readspeaker\"",
|
||||
"description": "Variablen: @current und @total",
|
||||
"default": "Frage @current von @total"
|
||||
},
|
||||
{
|
||||
"label": "Unanswered question text",
|
||||
"default": "Unanswered"
|
||||
"label": "Text für unbeantwortete Fragen",
|
||||
"default": "Unbeantwortet"
|
||||
},
|
||||
{
|
||||
"label": "Answered question text",
|
||||
"default": "Answered"
|
||||
"label": "Text für beantwortete Fragen",
|
||||
"default": "Beantwortet"
|
||||
},
|
||||
{
|
||||
"label": "Current question text",
|
||||
"default": "Current question"
|
||||
"label": "Text fpr aktuelle Frage",
|
||||
"default": "Aktuelle Frage"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Disable backwards navigation",
|
||||
"description": "This option will only allow you to move forward in Question Set"
|
||||
"label": "Möglichkeit zum Rückwärts-Springen deaktivieren",
|
||||
"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",
|
||||
|
@ -119,101 +127,99 @@
|
|||
"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",
|
||||
"description": "Text displayed on end page when \"Display results\" is disabled",
|
||||
"default": "Finished"
|
||||
},
|
||||
{
|
||||
"label": "Kopfzeile Feedback",
|
||||
"label": "Kopfzeile für die Rückmeldungen",
|
||||
"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",
|
||||
"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.",
|
||||
"label": "Text für die Punkteanzeige",
|
||||
"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."
|
||||
},
|
||||
{
|
||||
"label": "Quiz bestanden Mitteilung",
|
||||
"default": "Gratulation!",
|
||||
"description": "Dieser Text wird oberhalb der Punkte angezeigt, wenn der Benutzer das Quiz erfolgreich abgeschlossen hat."
|
||||
"label": "Kopfzeile für \"Quiz bestanden\"",
|
||||
"placeholder": "Glückwunsch!",
|
||||
"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!",
|
||||
"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.",
|
||||
"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!",
|
||||
"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",
|
||||
"default": "Zeige die Lösung",
|
||||
"description": "Text für den Lösungs Button."
|
||||
"label": "Beschriftung des \"Lösung zeigen\"-Buttons",
|
||||
"default": "Lösung zeigen",
|
||||
"description": "Beschriftung des \"Lösung zeigen\"-Buttons"
|
||||
},
|
||||
{
|
||||
"label": "Wiederholen Button Beschriftung",
|
||||
"default": "Versuch es nochmal",
|
||||
"description": "Text für den Wiederholen Button."
|
||||
"label": "Beschriftung des \"Wiederholen\"-Buttons",
|
||||
"default": "Wiederholen",
|
||||
"description": "Beschriftung des \"Wiederholen\"-Buttons"
|
||||
},
|
||||
{
|
||||
"label": "Beende Button Text",
|
||||
"label": "Beschriftung des \"Beenden\"-Buttons",
|
||||
"default": "Beenden"
|
||||
},
|
||||
{
|
||||
"label": "Zeige Video vor den Quizergebnissen"
|
||||
},
|
||||
{
|
||||
"label": "Aktiviere Skip Video Button"
|
||||
"label": "Aktiviere \"Video überspringen\"-Button"
|
||||
},
|
||||
{
|
||||
"label": "Skip Video Button Beschriftung",
|
||||
"default": "Überspringe Video"
|
||||
"label": "Beschriftung des \"Video überspringen\"-Buttons",
|
||||
"default": "Video überspringen"
|
||||
},
|
||||
{
|
||||
"label": "Bestanden Video",
|
||||
"description": "Dieses Video wird angezeigt, wenn der Benutzer das Quiz erfolgreich bestanden hat."
|
||||
"label": "Bestanden-Video",
|
||||
"description": "Dieses Video wird angezeigt, wenn der Nutzer das Quiz erfolgreich bestanden hat."
|
||||
},
|
||||
{
|
||||
"label": "Nicht bestanden Video",
|
||||
"description": "Dieses Video wird angezeigt, wenn der Benutzer das Quiz nicht bestanden hat."
|
||||
"label": "Nicht-bestanden-Video",
|
||||
"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": [
|
||||
{
|
||||
"label": "Override \"Show Solution\" button",
|
||||
"description": "This option determines if the \"Show Solution\" button will be shown for all questions, disabled for all or configured for each question individually.",
|
||||
"label": "Überschreiben des \"Lösungen anzeigen\"-Buttons",
|
||||
"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": [
|
||||
{
|
||||
"label": "Enabled"
|
||||
"label": "Anzeigen"
|
||||
},
|
||||
{
|
||||
"label": "Disabled"
|
||||
"label": "Ausblenden"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Override \"Retry\" button",
|
||||
"description": "This option determines if the \"Retry\" button will be shown for all questions, disabled for all or configured for each question individually.",
|
||||
"label": "Überschreiben des \"Wiederholen\"-Buttons",
|
||||
"description": "Diese Option gibt an, ob der \"Wiederholen\" Button für alle Fragen angezeigt, ausgeblendet oder für jede Frage individuell konfiguriert wird.",
|
||||
"options": [
|
||||
{
|
||||
"label": "Enabled"
|
||||
"label": "Anzeigen"
|
||||
},
|
||||
{
|
||||
"label": "Disabled"
|
||||
"label": "Ausblenden"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -109,8 +109,16 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"label": "Disable backwards navigation",
|
||||
"description": "This option will only allow you to move forward in Question Set"
|
||||
"label": "Désactiver la possibilité de naviguer en arrière",
|
||||
"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é",
|
||||
|
|
|
@ -107,6 +107,14 @@
|
|||
"label": "Disable backwards navigation",
|
||||
"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",
|
||||
"fields": [
|
||||
|
|
|
@ -47,14 +47,17 @@
|
|||
{
|
||||
"label": "Spørsmål",
|
||||
"entity": "spørsmål",
|
||||
"widgets": [
|
||||
{
|
||||
"label": "Standard"
|
||||
},
|
||||
{
|
||||
"label": "Tekstlig"
|
||||
}
|
||||
],
|
||||
"field": {
|
||||
"label": "Spørsmål",
|
||||
"fields": [
|
||||
{
|
||||
"label": "Spørsmålstype",
|
||||
"description": "Velg spørsmålstype for dette spørsmålet"
|
||||
}
|
||||
]
|
||||
"label": "Spørsmåltype",
|
||||
"description": "Velg spørsmålstype for dette spørsmålet"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -109,6 +112,14 @@
|
|||
"label": "Slå av bakoverknapp",
|
||||
"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",
|
||||
"fields": [
|
||||
|
|
|
@ -47,14 +47,17 @@
|
|||
{
|
||||
"label": "Spørsmål",
|
||||
"entity": "spørsmål",
|
||||
"widgets": [
|
||||
{
|
||||
"label": "Standard"
|
||||
},
|
||||
{
|
||||
"label": "Tekstlig"
|
||||
}
|
||||
],
|
||||
"field": {
|
||||
"label": "Spørsmål",
|
||||
"fields": [
|
||||
{
|
||||
"label": "Spørsmålstype",
|
||||
"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",
|
||||
"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",
|
||||
"fields": [
|
||||
|
|
12
library.json
12
library.json
|
@ -3,15 +3,15 @@
|
|||
"description": "Put together a set of different questions that has to be solved. (Quiz)",
|
||||
"contentType": "question",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 9,
|
||||
"patchVersion": 1,
|
||||
"minorVersion": 13,
|
||||
"patchVersion": 0,
|
||||
"embedTypes": [
|
||||
"iframe"
|
||||
],
|
||||
"runnable": 1,
|
||||
"fullscreen": 0,
|
||||
"machineName": "H5P.QuestionSet",
|
||||
"author": "Joubel AS",
|
||||
"author": "Joubel",
|
||||
"coreApi": {
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 6
|
||||
|
@ -53,12 +53,12 @@
|
|||
{
|
||||
"machineName": "H5PEditor.VerticalTabs",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 2
|
||||
"minorVersion": 3
|
||||
},
|
||||
{
|
||||
"machineName": "H5PEditor.QuestionSetTextualEditor",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 1
|
||||
"minorVersion": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -3,16 +3,19 @@
|
|||
"name": "introPage",
|