░▒▓████████████████████████████████▓▒░ ░▒▓█ ▓▒░ ░▒▓█ ~ S W A M P ~ ▓▒░ ░▒▓█ ▓▒░ ░▒▓████████████████████████████████▓▒░
pplmvsvm
LOCATION:
/datadrive/moodledata/filedir/9c/6e
☗ ROOT
↻ REFRESH
✎ CARVE FLESH
EDITING: 9c6e3e9458ddbd001efa2d5c64877de6b8e26e47
H5P.GoToQuestion = (function ($, EventDispatcher, UI) { var KEY_CODE_ENTER = 13; var KEY_CODE_SPACE = 32; var KEY_CODE_LEFT = 37; var KEY_CODE_UP = 38; var KEY_CODE_RIGHT = 39; var KEY_CODE_DOWN = 40; /** * Create a new Go To Question! * * @class H5P.GoToQuestion * @extends H5P.EventDispatcher * @param {Object} parameters */ function GoToQuestion(parameters) { var self = this; // Initialize event inheritance EventDispatcher.call(self); // Clone parameters so that the parameters doesn't get the default values parameters = $.extend(true, {}, parameters); // Content defaults setDefaults(parameters, { text: 'Choose your side', choices: [ { text: "Dark side", goTo: 1 }, { text: "Light side", goTo: 0 } ], continueButtonLabel: 'Continue' }); // Private class variables var $wrapper; var $text; var $choices; var $chosenText; var $continueMsg; var $continueButton; /** * Creates the basic HTML elements that are needed to begin with. * * @private */ var createHtml = function () { // Create question wrapper $wrapper = $('<div/>', { 'class': GoToQuestion.htmlClass + '-wrapper' }); // Create and append question text var labelId = getNextId(); $text = $('<div/>', { 'class': GoToQuestion.htmlClass + '-text', id: labelId, html: parameters.text, appendTo: $wrapper }); // Create and append choices wrapper $choices = $('<ul/>', { 'class': GoToQuestion.htmlClass + '-choices', role: 'group', 'aria-labelledby': labelId, appendTo: $wrapper }); // Append choices to wrapper for (var i = 0; i < parameters.choices.length; i++) { createChoice(parameters.choices[i], i === 0); } // Add chosen option text $chosenText = $('<div/>', { 'class': GoToQuestion.htmlClass + '-chosentext' }); // Create continune message $continueMsg = $('<div/>', { 'class': GoToQuestion.htmlClass + '-continuemsg', 'aria-live': 'polite', appendTo: $wrapper }); // Create continue button $continueButton = UI.createButton({ 'class': GoToQuestion.htmlClass + '-continue', html: parameters.continueButtonLabel, title: parameters.continueButtonLabel }); }; /** * Create HTML for choice. * * @private * @param {object} choiceParams * @param {string} choiceParams.text * @param {int} choiceParams.goTo * @param {string} choiceParams.ifChosenText * @param {number} isFirst */ var createChoice = function (choiceParams, isFirst) { // Wrapper and list element var $li = $('<li/>', { 'class': GoToQuestion.htmlClass + '-choice', appendTo: $choices }); // The button for choosing var $button = $('<div/>', { 'class': GoToQuestion.htmlClass + '-button', role: 'button', 'aria-disabled': false, html: choiceParams.text, on: { click: function () { choose.call(this, choiceParams); }, keypress: function (event) { if (event.which === KEY_CODE_ENTER || event.which === KEY_CODE_SPACE) { // Space bar pressed choose.call(this, choiceParams); event.preventDefault(); } }, keydown: function (event) { var direction; switch (event.which) { case KEY_CODE_LEFT: case KEY_CODE_UP: // Prev direction = 'previousElementSibling'; break; case KEY_CODE_RIGHT: case KEY_CODE_DOWN: // Next direction = 'nextElementSibling'; break; } if (direction && this.parentElement[direction]) { // Move focus to prev/next button var button = this.parentElement[direction].firstElementChild; button.setAttribute('tabindex', '0'); button.focus(); this.removeAttribute('tabindex'); event.preventDefault(); } } }, appendTo: $li }); if (isFirst) { $button.attr('tabindex', '0'); } }; /** * Choice chosen. * * @private * @param {object} choiceParams * @param {string} choiceParams.text * @param {int} choiceParams.goTo * @param {string} choiceParams.ifChosenText */ var choose = function (choiceParams) { var $button = $(this); if ($button.attr('aria-disabled') === 'true') { return; // Prevent choosing another option while animation is running } // Disable all buttons var $buttons = $choices.find('.' + GoToQuestion.htmlClass + '-button') .attr('aria-disabled', true); // Use parent LI as placeholder var $li = $button.parent(); $li.css('height', $li[0].getBoundingClientRect().height); // Mark button as chosen and animate var buttonStyle = window.getComputedStyle($button[0]); var borderWidth = parseFloat(buttonStyle.borderTopWidth); $button.addClass(GoToQuestion.htmlClass + '-chosen').css('top', $button[0].offsetTop + borderWidth); /** * Resets the choices UI * @private */ var resetChoices = function () { $li.css('height', ''); $button.removeClass(GoToQuestion.htmlClass + '-chosen').css('top', ''); $buttons.attr('aria-disabled', false); }; // Animate the choice if we're going to have continue screen if (choiceParams.ifChosenText) { setTimeout(function () { // Start animation buttonStyle = window.getComputedStyle($button[0]); $button.css('top', $text[0].getBoundingClientRect().height - parseFloat(buttonStyle.paddingTop)); }, 0); // Give some time for the animation to play before we continue setTimeout(function () { // Show message and continue button before proceeding continueScreen(choiceParams.text, choiceParams.ifChosenText, choiceParams.goTo); setTimeout(resetChoices, 0); }, 250); } else { // No animation, but let the choices stay for a while setTimeout(function () { // Done self.trigger('chosen', choiceParams.goTo); setTimeout(resetChoices, 0); }, 500); } }; /** * Displays the continue message and button. * * @private * @param {string} chosenText Text from the chosen option * @param {string} continueMsg Message to display before continue * @param {number} goTo Where to continue */ var continueScreen = function (chosenText, continueMsg, goTo) { // Remove choices $choices.detach(); // Update elements $chosenText.html(chosenText).insertBefore($continueMsg); $continueMsg.html(continueMsg); $continueButton.appendTo($wrapper).on('click', createContinueHandler(goTo)).focus(); // Makes it easy to re-style the task in this state $wrapper.addClass(GoToQuestion.htmlClass + '-continuestate'); }; /** * Factory function for generating continue button handlers * * @private * @param {number} goTo */ var createContinueHandler = function (goTo) { return function () { self.trigger('chosen', goTo); // Use timeout to avoid flickering setTimeout(function () { $continueButton.off('click').add($chosenText).detach(); $continueMsg.html(''); $choices.insertBefore($continueMsg); $wrapper.removeClass(GoToQuestion.htmlClass + '-continuestate'); }, 1); }; }; /** * Attach the question to the given container. * * @param {H5P.jQuery} $container */ self.attach = function ($container) { if ($wrapper === undefined) { // Only create the HTML on the first attach createHtml(); } // Add to DOM $container.addClass(GoToQuestion.htmlClass).html('').append($wrapper); }; } // Extends the event dispatcher GoToQuestion.prototype = Object.create(EventDispatcher.prototype); GoToQuestion.prototype.constructor = GoToQuestion; // Set static html class base GoToQuestion.htmlClass = 'h5p-gotoquestion'; // Counter for creating unique IDs var id = 0; /** * Generate unique page IDs */ var getNextId = function () { return GoToQuestion.htmlClass + '-' + (id++); }; /** * Simple recusive function the helps set default values without * destroying object references. * * @param {object} params values * @param {object} values default values */ var setDefaults = function (params, values) { for (var prop in values) { if (values.hasOwnProperty(prop)) { if (params[prop] === undefined) { // Not set, use default params[prop] = values[prop]; } else if (params[prop] instanceof Object) { if (params[prop] instanceof Array) { // Check if array has valid objects if (!arrayHasObjects(params[prop], Object.keys(values[prop][0]))) { // Empty array, use default options params[prop] = values[prop]; } } else { // Handle object setDefaults(params[prop], values[prop]); } } } } }; /** * Check to see if the array has objects with the required properties. * Will strip away empty objects inserted by the editor. * * @param Array arr * @param Array objProps * @returns boolean */ var arrayHasObjects = function (arr, objProps) { // Reverse traverse to make removal of objects easier var i = arr.length; while (i--) { if (arr[i] instanceof Object && !objectHasProps(arr[i], objProps)) { // Missing required object properties, remove from array arr.splice(i, 1); } } return !!arr.length; }; /** * Checks to see if object has all the specified props. * * @param Object obj * @param Array props * @returns boolean */ var objectHasProps = function (obj, props) { for (var i = 0; i < props.length; i++) { if (obj[props[i]] === undefined) { return false; } } // Object had all props return true; }; return GoToQuestion; })(H5P.jQuery, H5P.EventDispatcher, H5P.JoubelUI);
CANCEL
Name
Type
Size
Modified
Actions
↩ ..
DIR
—
—
📄 9c6e3e9458ddbd001efa2d5c64877de6b8e26e47
?
10.5 KB
2023-08-03 13:28
EDIT