', {
'class': 'h5p-question-explanation-text',
html: feedback.text,
appendTo: $explanationItem
});
}
}
};
createHTML();
/**
* Return the container HTMLElement
*
* @return {HTMLElement}
*/
self.getElement = function () {
return self.$explanation;
};
}
return Explainer;
})(H5P.jQuery);
;
(function (Question) {
/**
* Makes it easy to add animated score points for your question type.
*
* @class H5P.Question.ScorePoints
*/
Question.ScorePoints = function () {
var self = this;
var elements = [];
var showElementsTimer;
/**
* Create the element that displays the score point element for questions.
*
* @param {boolean} isCorrect
* @return {HTMLElement}
*/
self.getElement = function (isCorrect) {
var element = document.createElement('div');
element.classList.add(isCorrect ? 'h5p-question-plus-one' : 'h5p-question-minus-one');
element.classList.add('h5p-question-hidden-one');
elements.push(element);
// Schedule display animation of all added elements
if (showElementsTimer) {
clearTimeout(showElementsTimer);
}
showElementsTimer = setTimeout(showElements, 0);
return element;
};
/**
* @private
*/
var showElements = function () {
// Determine delay between triggering animations
var delay = 0;
var increment = 150;
var maxTime = 1000;
if (elements.length && elements.length > Math.ceil(maxTime / increment)) {
// Animations will run for more than ~1 second, reduce it.
increment = maxTime / elements.length;
}
for (var i = 0; i < elements.length; i++) {
// Use timer to trigger show
setTimeout(showElement(elements[i]), delay);
// Increse delay for next element
delay += increment;
}
};
/**
* Trigger transition animation for the given element
*
* @private
* @param {HTMLElement} element
* @return {function}
*/
var showElement = function (element) {
return function () {
element.classList.remove('h5p-question-hidden-one');
};
};
};
})(H5P.Question);
;
/*!
* @license SoundJS
* Visit http://createjs.com/ for documentation, updates and examples.
*
* Copyright (c) 2011-2015 gskinner.com, inc.
*
* Distributed under the terms of the MIT license.
* http://www.opensource.org/licenses/mit-license.html
*
* This notice shall be included in all copies or substantial portions of the Software.
*/
/**!
* SoundJS FlashAudioPlugin also includes swfobject (http://code.google.com/p/swfobject/)
*/
var old = this.createjs;
this.createjs=this.createjs||{},function(){var a=createjs.SoundJS=createjs.SoundJS||{};a.version="0.6.2",a.buildDate="Thu, 26 Nov 2015 20:44:31 GMT"}(),this.createjs=this.createjs||{},createjs.extend=function(a,b){"use strict";function c(){this.constructor=a}return c.prototype=b.prototype,a.prototype=new c},this.createjs=this.createjs||{},createjs.promote=function(a,b){"use strict";var c=a.prototype,d=Object.getPrototypeOf&&Object.getPrototypeOf(c)||c.__proto__;if(d){c[(b+="_")+"constructor"]=d.constructor;for(var e in d)c.hasOwnProperty(e)&&"function"==typeof d[e]&&(c[b+e]=d[e])}return a},this.createjs=this.createjs||{},createjs.indexOf=function(a,b){"use strict";for(var c=0,d=a.length;d>c;c++)if(b===a[c])return c;return-1},this.createjs=this.createjs||{},function(){"use strict";createjs.proxy=function(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){return a.apply(b,Array.prototype.slice.call(arguments,0).concat(c))}}}(),this.createjs=this.createjs||{},function(){"use strict";function BrowserDetect(){throw"BrowserDetect cannot be instantiated"}var a=BrowserDetect.agent=window.navigator.userAgent;BrowserDetect.isWindowPhone=a.indexOf("IEMobile")>-1||a.indexOf("Windows Phone")>-1,BrowserDetect.isFirefox=a.indexOf("Firefox")>-1,BrowserDetect.isOpera=null!=window.opera,BrowserDetect.isChrome=a.indexOf("Chrome")>-1,BrowserDetect.isIOS=(a.indexOf("iPod")>-1||a.indexOf("iPhone")>-1||a.indexOf("iPad")>-1)&&!BrowserDetect.isWindowPhone,BrowserDetect.isAndroid=a.indexOf("Android")>-1&&!BrowserDetect.isWindowPhone,BrowserDetect.isBlackberry=a.indexOf("Blackberry")>-1,createjs.BrowserDetect=BrowserDetect}(),this.createjs=this.createjs||{},function(){"use strict";function EventDispatcher(){this._listeners=null,this._captureListeners=null}var a=EventDispatcher.prototype;EventDispatcher.initialize=function(b){b.addEventListener=a.addEventListener,b.on=a.on,b.removeEventListener=b.off=a.removeEventListener,b.removeAllEventListeners=a.removeAllEventListeners,b.hasEventListener=a.hasEventListener,b.dispatchEvent=a.dispatchEvent,b._dispatchEvent=a._dispatchEvent,b.willTrigger=a.willTrigger},a.addEventListener=function(a,b,c){var d;d=c?this._captureListeners=this._captureListeners||{}:this._listeners=this._listeners||{};var e=d[a];return e&&this.removeEventListener(a,b,c),e=d[a],e?e.push(b):d[a]=[b],b},a.on=function(a,b,c,d,e,f){return b.handleEvent&&(c=c||b,b=b.handleEvent),c=c||this,this.addEventListener(a,function(a){b.call(c,a,e),d&&a.remove()},f)},a.removeEventListener=function(a,b,c){var d=c?this._captureListeners:this._listeners;if(d){var e=d[a];if(e)for(var f=0,g=e.length;g>f;f++)if(e[f]==b){1==g?delete d[a]:e.splice(f,1);break}}},a.off=a.removeEventListener,a.removeAllEventListeners=function(a){a?(this._listeners&&delete this._listeners[a],this._captureListeners&&delete this._captureListeners[a]):this._listeners=this._captureListeners=null},a.dispatchEvent=function(a,b,c){if("string"==typeof a){var d=this._listeners;if(!(b||d&&d[a]))return!0;a=new createjs.Event(a,b,c)}else a.target&&a.clone&&(a=a.clone());try{a.target=this}catch(e){}if(a.bubbles&&this.parent){for(var f=this,g=[f];f.parent;)g.push(f=f.parent);var h,i=g.length;for(h=i-1;h>=0&&!a.propagationStopped;h--)g[h]._dispatchEvent(a,1+(0==h));for(h=1;i>h&&!a.propagationStopped;h++)g[h]._dispatchEvent(a,3)}else this._dispatchEvent(a,2);return!a.defaultPrevented},a.hasEventListener=function(a){var b=this._listeners,c=this._captureListeners;return!!(b&&b[a]||c&&c[a])},a.willTrigger=function(a){for(var b=this;b;){if(b.hasEventListener(a))return!0;b=b.parent}return!1},a.toString=function(){return"[EventDispatcher]"},a._dispatchEvent=function(a,b){var c,d=1==b?this._captureListeners:this._listeners;if(a&&d){var e=d[a.type];if(!e||!(c=e.length))return;try{a.currentTarget=this}catch(f){}try{a.eventPhase=b}catch(f){}a.removed=!1,e=e.slice();for(var g=0;c>g&&!a.immediatePropagationStopped;g++){var h=e[g];h.handleEvent?h.handleEvent(a):h(a),a.removed&&(this.off(a.type,h,1==b),a.removed=!1)}}},createjs.EventDispatcher=EventDispatcher}(),this.createjs=this.createjs||{},function(){"use strict";function Event(a,b,c){this.type=a,this.target=null,this.currentTarget=null,this.eventPhase=0,this.bubbles=!!b,this.cancelable=!!c,this.timeStamp=(new Date).getTime(),this.defaultPrevented=!1,this.propagationStopped=!1,this.immediatePropagationStopped=!1,this.removed=!1}var a=Event.prototype;a.preventDefault=function(){this.defaultPrevented=this.cancelable&&!0},a.stopPropagation=function(){this.propagationStopped=!0},a.stopImmediatePropagation=function(){this.immediatePropagationStopped=this.propagationStopped=!0},a.remove=function(){this.removed=!0},a.clone=function(){return new Event(this.type,this.bubbles,this.cancelable)},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[Event (type="+this.type+")]"},createjs.Event=Event}(),this.createjs=this.createjs||{},function(){"use strict";function ErrorEvent(a,b,c){this.Event_constructor("error"),this.title=a,this.message=b,this.data=c}var a=createjs.extend(ErrorEvent,createjs.Event);a.clone=function(){return new createjs.ErrorEvent(this.title,this.message,this.data)},createjs.ErrorEvent=createjs.promote(ErrorEvent,"Event")}(),this.createjs=this.createjs||{},function(){"use strict";function ProgressEvent(a,b){this.Event_constructor("progress"),this.loaded=a,this.total=null==b?1:b,this.progress=0==b?0:this.loaded/this.total}var a=createjs.extend(ProgressEvent,createjs.Event);a.clone=function(){return new createjs.ProgressEvent(this.loaded,this.total)},createjs.ProgressEvent=createjs.promote(ProgressEvent,"Event")}(window),this.createjs=this.createjs||{},function(){"use strict";function LoadItem(){this.src=null,this.type=null,this.id=null,this.maintainOrder=!1,this.callback=null,this.data=null,this.method=createjs.LoadItem.GET,this.values=null,this.headers=null,this.withCredentials=!1,this.mimeType=null,this.crossOrigin=null,this.loadTimeout=b.LOAD_TIMEOUT_DEFAULT}var a=LoadItem.prototype={},b=LoadItem;b.LOAD_TIMEOUT_DEFAULT=8e3,b.create=function(a){if("string"==typeof a){var c=new LoadItem;return c.src=a,c}if(a instanceof b)return a;if(a instanceof Object&&a.src)return null==a.loadTimeout&&(a.loadTimeout=b.LOAD_TIMEOUT_DEFAULT),a;throw new Error("Type not recognized.")},a.set=function(a){for(var b in a)this[b]=a[b];return this},createjs.LoadItem=b}(),function(){var a={};a.ABSOLUTE_PATT=/^(?:\w+:)?\/{2}/i,a.RELATIVE_PATT=/^[.\/]*?\//i,a.EXTENSION_PATT=/\/?[^\/]+\.(\w{1,5})$/i,a.parseURI=function(b){var c={absolute:!1,relative:!1};if(null==b)return c;var d=b.indexOf("?");d>-1&&(b=b.substr(0,d));var e;return a.ABSOLUTE_PATT.test(b)?c.absolute=!0:a.RELATIVE_PATT.test(b)&&(c.relative=!0),(e=b.match(a.EXTENSION_PATT))&&(c.extension=e[1].toLowerCase()),c},a.formatQueryString=function(a,b){if(null==a)throw new Error("You must specify data.");var c=[];for(var d in a)c.push(d+"="+escape(a[d]));return b&&(c=c.concat(b)),c.join("&")},a.buildPath=function(a,b){if(null==b)return a;var c=[],d=a.indexOf("?");if(-1!=d){var e=a.slice(d+1);c=c.concat(e.split("&"))}return-1!=d?a.slice(0,d)+"?"+this.formatQueryString(b,c):a+"?"+this.formatQueryString(b,c)},a.isCrossDomain=function(a){var b=document.createElement("a");b.href=a.src;var c=document.createElement("a");c.href=location.href;var d=""!=b.hostname&&(b.port!=c.port||b.protocol!=c.protocol||b.hostname!=c.hostname);return d},a.isLocal=function(a){var b=document.createElement("a");return b.href=a.src,""==b.hostname&&"file:"==b.protocol},a.isBinary=function(a){switch(a){case createjs.AbstractLoader.IMAGE:case createjs.AbstractLoader.BINARY:return!0;default:return!1}},a.isImageTag=function(a){return a instanceof HTMLImageElement},a.isAudioTag=function(a){return window.HTMLAudioElement?a instanceof HTMLAudioElement:!1},a.isVideoTag=function(a){return window.HTMLVideoElement?a instanceof HTMLVideoElement:!1},a.isText=function(a){switch(a){case createjs.AbstractLoader.TEXT:case createjs.AbstractLoader.JSON:case createjs.AbstractLoader.MANIFEST:case createjs.AbstractLoader.XML:case createjs.AbstractLoader.CSS:case createjs.AbstractLoader.SVG:case createjs.AbstractLoader.JAVASCRIPT:case createjs.AbstractLoader.SPRITESHEET:return!0;default:return!1}},a.getTypeByExtension=function(a){if(null==a)return createjs.AbstractLoader.TEXT;switch(a.toLowerCase()){case"jpeg":case"jpg":case"gif":case"png":case"webp":case"bmp":return createjs.AbstractLoader.IMAGE;case"ogg":case"mp3":case"webm":return createjs.AbstractLoader.SOUND;case"mp4":case"webm":case"ts":return createjs.AbstractLoader.VIDEO;case"json":return createjs.AbstractLoader.JSON;case"xml":return createjs.AbstractLoader.XML;case"css":return createjs.AbstractLoader.CSS;case"js":return createjs.AbstractLoader.JAVASCRIPT;case"svg":return createjs.AbstractLoader.SVG;default:return createjs.AbstractLoader.TEXT}},createjs.RequestUtils=a}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractLoader(a,b,c){this.EventDispatcher_constructor(),this.loaded=!1,this.canceled=!1,this.progress=0,this.type=c,this.resultFormatter=null,this._item=a?createjs.LoadItem.create(a):null,this._preferXHR=b,this._result=null,this._rawResult=null,this._loadedItems=null,this._tagSrcAttribute=null,this._tag=null}var a=createjs.extend(AbstractLoader,createjs.EventDispatcher),b=AbstractLoader;b.POST="POST",b.GET="GET",b.BINARY="binary",b.CSS="css",b.IMAGE="image",b.JAVASCRIPT="javascript",b.JSON="json",b.JSONP="jsonp",b.MANIFEST="manifest",b.SOUND="sound",b.VIDEO="video",b.SPRITESHEET="spritesheet",b.SVG="svg",b.TEXT="text",b.XML="xml",a.getItem=function(){return this._item},a.getResult=function(a){return a?this._rawResult:this._result},a.getTag=function(){return this._tag},a.setTag=function(a){this._tag=a},a.load=function(){this._createRequest(),this._request.on("complete",this,this),this._request.on("progress",this,this),this._request.on("loadStart",this,this),this._request.on("abort",this,this),this._request.on("timeout",this,this),this._request.on("error",this,this);var a=new createjs.Event("initialize");a.loader=this._request,this.dispatchEvent(a),this._request.load()},a.cancel=function(){this.canceled=!0,this.destroy()},a.destroy=function(){this._request&&(this._request.removeAllEventListeners(),this._request.destroy()),this._request=null,this._item=null,this._rawResult=null,this._result=null,this._loadItems=null,this.removeAllEventListeners()},a.getLoadedItems=function(){return this._loadedItems},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.TagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._createTag=function(){return null},a._sendLoadStart=function(){this._isCanceled()||this.dispatchEvent("loadstart")},a._sendProgress=function(a){if(!this._isCanceled()){var b=null;"number"==typeof a?(this.progress=a,b=new createjs.ProgressEvent(this.progress)):(b=a,this.progress=a.loaded/a.total,b.progress=this.progress,(isNaN(this.progress)||1/0==this.progress)&&(this.progress=0)),this.hasEventListener("progress")&&this.dispatchEvent(b)}},a._sendComplete=function(){if(!this._isCanceled()){this.loaded=!0;var a=new createjs.Event("complete");a.rawResult=this._rawResult,null!=this._result&&(a.result=this._result),this.dispatchEvent(a)}},a._sendError=function(a){!this._isCanceled()&&this.hasEventListener("error")&&(null==a&&(a=new createjs.ErrorEvent("PRELOAD_ERROR_EMPTY")),this.dispatchEvent(a))},a._isCanceled=function(){return null==window.createjs||this.canceled?!0:!1},a.resultFormatter=null,a.handleEvent=function(a){switch(a.type){case"complete":this._rawResult=a.target._response;var b=this.resultFormatter&&this.resultFormatter(this);b instanceof Function?b.call(this,createjs.proxy(this._resultFormatSuccess,this),createjs.proxy(this._resultFormatFailed,this)):(this._result=b||this._rawResult,this._sendComplete());break;case"progress":this._sendProgress(a);break;case"error":this._sendError(a);break;case"loadstart":this._sendLoadStart();break;case"abort":case"timeout":this._isCanceled()||this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_"+a.type.toUpperCase()+"_ERROR"))}},a._resultFormatSuccess=function(a){this._result=a,this._sendComplete()},a._resultFormatFailed=function(a){this._sendError(a)},a.buildPath=function(a,b){return createjs.RequestUtils.buildPath(a,b)},a.toString=function(){return"[PreloadJS AbstractLoader]"},createjs.AbstractLoader=createjs.promote(AbstractLoader,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function AbstractMediaLoader(a,b,c){this.AbstractLoader_constructor(a,b,c),this.resultFormatter=this._formatResult,this._tagSrcAttribute="src",this.on("initialize",this._updateXHR,this)}var a=createjs.extend(AbstractMediaLoader,createjs.AbstractLoader);a.load=function(){this._tag||(this._tag=this._createTag(this._item.src)),this._tag.preload="auto",this._tag.load(),this.AbstractLoader_load()},a._createTag=function(){},a._createRequest=function(){this._request=this._preferXHR?new createjs.XHRRequest(this._item):new createjs.MediaTagRequest(this._item,this._tag||this._createTag(),this._tagSrcAttribute)},a._updateXHR=function(a){a.loader.setResponseType&&a.loader.setResponseType("blob")},a._formatResult=function(a){if(this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.onstalled=null,this._preferXHR){var b=window.URL||window.webkitURL,c=a.getResult(!0);a.getTag().src=b.createObjectURL(c)}return a.getTag()},createjs.AbstractMediaLoader=createjs.promote(AbstractMediaLoader,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractRequest=function(a){this._item=a},a=createjs.extend(AbstractRequest,createjs.EventDispatcher);a.load=function(){},a.destroy=function(){},a.cancel=function(){},createjs.AbstractRequest=createjs.promote(AbstractRequest,"EventDispatcher")}(),this.createjs=this.createjs||{},function(){"use strict";function TagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this),this._addedToDOM=!1,this._startTagVisibility=null}var a=createjs.extend(TagRequest,createjs.AbstractRequest);a.load=function(){this._tag.onload=createjs.proxy(this._handleTagComplete,this),this._tag.onreadystatechange=createjs.proxy(this._handleReadyStateChange,this),this._tag.onerror=createjs.proxy(this._handleError,this);var a=new createjs.Event("initialize");a.loader=this._tag,this.dispatchEvent(a),this._hideTag(),this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout),this._tag[this._tagSrcAttribute]=this._item.src,null==this._tag.parentNode&&(window.document.body.appendChild(this._tag),this._addedToDOM=!0)},a.destroy=function(){this._clean(),this._tag=null,this.AbstractRequest_destroy()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleError=function(){this._clean(),this.dispatchEvent("error")},a._handleTagComplete=function(){this._rawResult=this._tag,this._result=this.resultFormatter&&this.resultFormatter(this)||this._rawResult,this._clean(),this._showTag(),this.dispatchEvent("complete")},a._handleTimeout=function(){this._clean(),this.dispatchEvent(new createjs.Event("timeout"))},a._clean=function(){this._tag.onload=null,this._tag.onreadystatechange=null,this._tag.onerror=null,this._addedToDOM&&null!=this._tag.parentNode&&this._tag.parentNode.removeChild(this._tag),clearTimeout(this._loadTimeout)},a._hideTag=function(){this._startTagVisibility=this._tag.style.visibility,this._tag.style.visibility="hidden"},a._showTag=function(){this._tag.style.visibility=this._startTagVisibility},a._handleStalled=function(){},createjs.TagRequest=createjs.promote(TagRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function MediaTagRequest(a,b,c){this.AbstractRequest_constructor(a),this._tag=b,this._tagSrcAttribute=c,this._loadedHandler=createjs.proxy(this._handleTagComplete,this)}var a=createjs.extend(MediaTagRequest,createjs.TagRequest);a.load=function(){var a=createjs.proxy(this._handleStalled,this);this._stalledCallback=a;var b=createjs.proxy(this._handleProgress,this);this._handleProgress=b,this._tag.addEventListener("stalled",a),this._tag.addEventListener("progress",b),this._tag.addEventListener&&this._tag.addEventListener("canplaythrough",this._loadedHandler,!1),this.TagRequest_load()},a._handleReadyStateChange=function(){clearTimeout(this._loadTimeout);var a=this._tag;("loaded"==a.readyState||"complete"==a.readyState)&&this._handleTagComplete()},a._handleStalled=function(){},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._clean=function(){this._tag.removeEventListener&&this._tag.removeEventListener("canplaythrough",this._loadedHandler),this._tag.removeEventListener("stalled",this._stalledCallback),this._tag.removeEventListener("progress",this._progressCallback),this.TagRequest__clean()},createjs.MediaTagRequest=createjs.promote(MediaTagRequest,"TagRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function XHRRequest(a){this.AbstractRequest_constructor(a),this._request=null,this._loadTimeout=null,this._xhrLevel=1,this._response=null,this._rawResponse=null,this._canceled=!1,this._handleLoadStartProxy=createjs.proxy(this._handleLoadStart,this),this._handleProgressProxy=createjs.proxy(this._handleProgress,this),this._handleAbortProxy=createjs.proxy(this._handleAbort,this),this._handleErrorProxy=createjs.proxy(this._handleError,this),this._handleTimeoutProxy=createjs.proxy(this._handleTimeout,this),this._handleLoadProxy=createjs.proxy(this._handleLoad,this),this._handleReadyStateChangeProxy=createjs.proxy(this._handleReadyStateChange,this),!this._createXHR(a)}var a=createjs.extend(XHRRequest,createjs.AbstractRequest);XHRRequest.ACTIVEX_VERSIONS=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],a.getResult=function(a){return a&&this._rawResponse?this._rawResponse:this._response},a.cancel=function(){this.canceled=!0,this._clean(),this._request.abort()},a.load=function(){if(null==this._request)return void this._handleError();null!=this._request.addEventListener?(this._request.addEventListener("loadstart",this._handleLoadStartProxy,!1),this._request.addEventListener("progress",this._handleProgressProxy,!1),this._request.addEventListener("abort",this._handleAbortProxy,!1),this._request.addEventListener("error",this._handleErrorProxy,!1),this._request.addEventListener("timeout",this._handleTimeoutProxy,!1),this._request.addEventListener("load",this._handleLoadProxy,!1),this._request.addEventListener("readystatechange",this._handleReadyStateChangeProxy,!1)):(this._request.onloadstart=this._handleLoadStartProxy,this._request.onprogress=this._handleProgressProxy,this._request.onabort=this._handleAbortProxy,this._request.onerror=this._handleErrorProxy,this._request.ontimeout=this._handleTimeoutProxy,this._request.onload=this._handleLoadProxy,this._request.onreadystatechange=this._handleReadyStateChangeProxy),1==this._xhrLevel&&(this._loadTimeout=setTimeout(createjs.proxy(this._handleTimeout,this),this._item.loadTimeout));try{this._item.values&&this._item.method!=createjs.AbstractLoader.GET?this._item.method==createjs.AbstractLoader.POST&&this._request.send(createjs.RequestUtils.formatQueryString(this._item.values)):this._request.send()}catch(a){this.dispatchEvent(new createjs.ErrorEvent("XHR_SEND",null,a))}},a.setResponseType=function(a){"blob"===a&&(a=window.URL?"blob":"arraybuffer",this._responseType=a),this._request.responseType=a},a.getAllResponseHeaders=function(){return this._request.getAllResponseHeaders instanceof Function?this._request.getAllResponseHeaders():null},a.getResponseHeader=function(a){return this._request.getResponseHeader instanceof Function?this._request.getResponseHeader(a):null},a._handleProgress=function(a){if(a&&!(a.loaded>0&&0==a.total)){var b=new createjs.ProgressEvent(a.loaded,a.total);this.dispatchEvent(b)}},a._handleLoadStart=function(){clearTimeout(this._loadTimeout),this.dispatchEvent("loadstart")},a._handleAbort=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("XHR_ABORTED",null,a))},a._handleError=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent(a.message))},a._handleReadyStateChange=function(){4==this._request.readyState&&this._handleLoad()},a._handleLoad=function(){if(!this.loaded){this.loaded=!0;var a=this._checkError();if(a)return void this._handleError(a);if(this._response=this._getResponse(),"arraybuffer"===this._responseType)try{this._response=new Blob([this._response])}catch(b){if(window.BlobBuilder=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,"TypeError"===b.name&&window.BlobBuilder){var c=new BlobBuilder;c.append(this._response),this._response=c.getBlob()}}this._clean(),this.dispatchEvent(new createjs.Event("complete"))}},a._handleTimeout=function(a){this._clean(),this.dispatchEvent(new createjs.ErrorEvent("PRELOAD_TIMEOUT",null,a))},a._checkError=function(){var a=parseInt(this._request.status);switch(a){case 404:case 0:return new Error(a)}return null},a._getResponse=function(){if(null!=this._response)return this._response;if(null!=this._request.response)return this._request.response;try{if(null!=this._request.responseText)return this._request.responseText}catch(a){}try{if(null!=this._request.responseXML)return this._request.responseXML}catch(a){}return null},a._createXHR=function(a){var b=createjs.RequestUtils.isCrossDomain(a),c={},d=null;if(window.XMLHttpRequest)d=new XMLHttpRequest,b&&void 0===d.withCredentials&&window.XDomainRequest&&(d=new XDomainRequest);else{for(var e=0,f=s.ACTIVEX_VERSIONS.length;f>e;e++){var g=s.ACTIVEX_VERSIONS[e];try{d=new ActiveXObject(g);break}catch(h){}}if(null==d)return!1}null==a.mimeType&&createjs.RequestUtils.isText(a.type)&&(a.mimeType="text/plain; charset=utf-8"),a.mimeType&&d.overrideMimeType&&d.overrideMimeType(a.mimeType),this._xhrLevel="string"==typeof d.responseType?2:1;var i=null;if(i=a.method==createjs.AbstractLoader.GET?createjs.RequestUtils.buildPath(a.src,a.values):a.src,d.open(a.method||createjs.AbstractLoader.GET,i,!0),b&&d instanceof XMLHttpRequest&&1==this._xhrLevel&&(c.Origin=location.origin),a.values&&a.method==createjs.AbstractLoader.POST&&(c["Content-Type"]="application/x-www-form-urlencoded"),b||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest"),a.headers)for(var j in a.headers)c[j]=a.headers[j];for(j in c)d.setRequestHeader(j,c[j]);return d instanceof XMLHttpRequest&&void 0!==a.withCredentials&&(d.withCredentials=a.withCredentials),this._request=d,!0},a._clean=function(){clearTimeout(this._loadTimeout),null!=this._request.removeEventListener?(this._request.removeEventListener("loadstart",this._handleLoadStartProxy),this._request.removeEventListener("progress",this._handleProgressProxy),this._request.removeEventListener("abort",this._handleAbortProxy),this._request.removeEventListener("error",this._handleErrorProxy),this._request.removeEventListener("timeout",this._handleTimeoutProxy),this._request.removeEventListener("load",this._handleLoadProxy),this._request.removeEventListener("readystatechange",this._handleReadyStateChangeProxy)):(this._request.onloadstart=null,this._request.onprogress=null,this._request.onabort=null,this._request.onerror=null,this._request.ontimeout=null,this._request.onload=null,this._request.onreadystatechange=null)},a.toString=function(){return"[PreloadJS XHRRequest]"},createjs.XHRRequest=createjs.promote(XHRRequest,"AbstractRequest")}(),this.createjs=this.createjs||{},function(){"use strict";function SoundLoader(a,b){this.AbstractMediaLoader_constructor(a,b,createjs.AbstractLoader.SOUND),createjs.RequestUtils.isAudioTag(a)?this._tag=a:createjs.RequestUtils.isAudioTag(a.src)?this._tag=a:createjs.RequestUtils.isAudioTag(a.tag)&&(this._tag=createjs.RequestUtils.isAudioTag(a)?a:a.src),null!=this._tag&&(this._preferXHR=!1)}var a=createjs.extend(SoundLoader,createjs.AbstractMediaLoader),b=SoundLoader;b.canLoadItem=function(a){return a.type==createjs.AbstractLoader.SOUND},a._createTag=function(a){var b=document.createElement("audio");return b.autoplay=!1,b.preload="none",b.src=a,b},createjs.SoundLoader=createjs.promote(SoundLoader,"AbstractMediaLoader")}(),this.createjs=this.createjs||{},function(){"use strict";var PlayPropsConfig=function(){this.interrupt=null,this.delay=null,this.offset=null,this.loop=null,this.volume=null,this.pan=null,this.startTime=null,this.duration=null},a=PlayPropsConfig.prototype={},b=PlayPropsConfig;b.create=function(a){if(a instanceof b||a instanceof Object){var c=new createjs.PlayPropsConfig;return c.set(a),c}throw new Error("Type not recognized.")},a.set=function(a){for(var b in a)this[b]=a[b];return this},a.toString=function(){return"[PlayPropsConfig]"},createjs.PlayPropsConfig=b}(),this.createjs=this.createjs||{},function(){"use strict";function Sound(){throw"Sound cannot be instantiated"}function a(a,b){this.init(a,b)}var b=Sound;b.INTERRUPT_ANY="any",b.INTERRUPT_EARLY="early",b.INTERRUPT_LATE="late",b.INTERRUPT_NONE="none",b.PLAY_INITED="playInited",b.PLAY_SUCCEEDED="playSucceeded",b.PLAY_INTERRUPTED="playInterrupted",b.PLAY_FINISHED="playFinished",b.PLAY_FAILED="playFailed",b.SUPPORTED_EXTENSIONS=["mp3","ogg","opus","mpeg","wav","m4a","mp4","aiff","wma","mid"],b.EXTENSION_MAP={m4a:"mp4"},b.FILE_PATTERN=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?))?([\/.]*?(?:[^?]+)?\/)?((?:[^\/?]+)\.(\w+))(?:\?(\S+)?)?$/,b.defaultInterruptBehavior=b.INTERRUPT_NONE,b.alternateExtensions=[],b.activePlugin=null,b._masterVolume=1,Object.defineProperty(b,"volume",{get:function(){return this._masterVolume},set:function(a){if(null==Number(a))return!1;if(a=Math.max(0,Math.min(1,a)),b._masterVolume=a,!this.activePlugin||!this.activePlugin.setVolume||!this.activePlugin.setVolume(a))for(var c=this._instances,d=0,e=c.length;e>d;d++)c[d].setMasterVolume(a)}}),b._masterMute=!1,Object.defineProperty(b,"muted",{get:function(){return this._masterMute},set:function(a){if(null==a)return!1;if(this._masterMute=a,!this.activePlugin||!this.activePlugin.setMute||!this.activePlugin.setMute(a))for(var b=this._instances,c=0,d=b.length;d>c;c++)b[c].setMasterMute(a);return!0}}),Object.defineProperty(b,"capabilities",{get:function(){return null==b.activePlugin?null:b.activePlugin._capabilities},set:function(){return!1}}),b._pluginsRegistered=!1,b._lastID=0,b._instances=[],b._idHash={},b._preloadHash={},b._defaultPlayPropsHash={},b.addEventListener=null,b.removeEventListener=null,b.removeAllEventListeners=null,b.dispatchEvent=null,b.hasEventListener=null,b._listeners=null,createjs.EventDispatcher.initialize(b),b.getPreloadHandlers=function(){return{callback:createjs.proxy(b.initLoad,b),types:["sound"],extensions:b.SUPPORTED_EXTENSIONS}},b._handleLoadComplete=function(a){var c=a.target.getItem().src;if(b._preloadHash[c])for(var d=0,e=b._preloadHash[c].length;e>d;d++){var f=b._preloadHash[c][d];if(b._preloadHash[c][d]=!0,b.hasEventListener("fileload")){var a=new createjs.Event("fileload");a.src=f.src,a.id=f.id,a.data=f.data,a.sprite=f.sprite,b.dispatchEvent(a)}}},b._handleLoadError=function(a){var c=a.target.getItem().src;if(b._preloadHash[c])for(var d=0,e=b._preloadHash[c].length;e>d;d++){var f=b._preloadHash[c][d];if(b._preloadHash[c][d]=!1,b.hasEventListener("fileerror")){var a=new createjs.Event("fileerror");a.src=f.src,a.id=f.id,a.data=f.data,a.sprite=f.sprite,b.dispatchEvent(a)}}},b._registerPlugin=function(a){return a.isSupported()?(b.activePlugin=new a,!0):!1},b.registerPlugins=function(a){b._pluginsRegistered=!0;for(var c=0,d=a.length;d>c;c++)if(b._registerPlugin(a[c]))return!0;return!1},b.initializeDefaultPlugins=function(){return null!=b.activePlugin?!0:b._pluginsRegistered?!1:b.registerPlugins([createjs.WebAudioPlugin,createjs.HTMLAudioPlugin])?!0:!1},b.isReady=function(){return null!=b.activePlugin},b.getCapabilities=function(){return null==b.activePlugin?null:b.activePlugin._capabilities},b.getCapability=function(a){return null==b.activePlugin?null:b.activePlugin._capabilities[a]},b.initLoad=function(a){return b._registerSound(a)},b._registerSound=function(c){if(!b.initializeDefaultPlugins())return!1;var d;if(c.src instanceof Object?(d=b._parseSrc(c.src),d.src=c.path+d.src):d=b._parsePath(c.src),null==d)return!1;c.src=d.src,c.type="sound";var e=c.data,f=null;if(null!=e&&(isNaN(e.channels)?isNaN(e)||(f=parseInt(e)):f=parseInt(e.channels),e.audioSprite))for(var g,h=e.audioSprite.length;h--;)g=e.audioSprite[h],b._idHash[g.id]={src:c.src,startTime:parseInt(g.startTime),duration:parseInt(g.duration)},g.defaultPlayProps&&(b._defaultPlayPropsHash[g.id]=createjs.PlayPropsConfig.create(g.defaultPlayProps));null!=c.id&&(b._idHash[c.id]={src:c.src});var i=b.activePlugin.register(c);return a.create(c.src,f),null!=e&&isNaN(e)?c.data.channels=f||a.maxPerChannel():c.data=f||a.maxPerChannel(),i.type&&(c.type=i.type),c.defaultPlayProps&&(b._defaultPlayPropsHash[c.src]=createjs.PlayPropsConfig.create(c.defaultPlayProps)),i},b.registerSound=function(a,c,d,e,f){var g={src:a,id:c,data:d,defaultPlayProps:f};a instanceof Object&&a.src&&(e=c,g=a),g=createjs.LoadItem.create(g),g.path=e,null==e||g.src instanceof Object||(g.src=e+a);var h=b._registerSound(g);if(!h)return!1;if(b._preloadHash[g.src]||(b._preloadHash[g.src]=[]),b._preloadHash[g.src].push(g),1==b._preloadHash[g.src].length)h.on("complete",createjs.proxy(this._handleLoadComplete,this)),h.on("error",createjs.proxy(this._handleLoadError,this)),b.activePlugin.preload(h);else if(1==b._preloadHash[g.src][0])return!0;return g},b.registerSounds=function(a,b){var c=[];a.path&&(b?b+=a.path:b=a.path,a=a.manifest);for(var d=0,e=a.length;e>d;d++)c[d]=createjs.Sound.registerSound(a[d].src,a[d].id,a[d].data,b,a[d].defaultPlayProps);return c},b.removeSound=function(c,d){if(null==b.activePlugin)return!1;c instanceof Object&&c.src&&(c=c.src);var e;if(c instanceof Object?e=b._parseSrc(c):(c=b._getSrcById(c).src,e=b._parsePath(c)),null==e)return!1;c=e.src,null!=d&&(c=d+c);for(var f in b._idHash)b._idHash[f].src==c&&delete b._idHash[f];return a.removeSrc(c),delete b._preloadHash[c],b.activePlugin.removeSound(c),!0},b.removeSounds=function(a,b){var c=[];a.path&&(b?b+=a.path:b=a.path,a=a.manifest);for(var d=0,e=a.length;e>d;d++)c[d]=createjs.Sound.removeSound(a[d].src,b);return c},b.removeAllSounds=function(){b._idHash={},b._preloadHash={},a.removeAll(),b.activePlugin&&b.activePlugin.removeAllSounds()},b.loadComplete=function(a){if(!b.isReady())return!1;var c=b._parsePath(a);return a=c?b._getSrcById(c.src).src:b._getSrcById(a).src,void 0==b._preloadHash[a]?!1:1==b._preloadHash[a][0]},b._parsePath=function(a){"string"!=typeof a&&(a=a.toString());var c=a.match(b.FILE_PATTERN);if(null==c)return!1;for(var d=c[4],e=c[5],f=b.capabilities,g=0;!f[e];)if(e=b.alternateExtensions[g++],g>b.alternateExtensions.length)return null;a=a.replace("."+c[5],"."+e);var h={name:d,src:a,extension:e};return h},b._parseSrc=function(a){var c={name:void 0,src:void 0,extension:void 0},d=b.capabilities;for(var e in a)if(a.hasOwnProperty(e)&&d[e]){c.src=a[e],c.extension=e;break}if(!c.src)return!1;var f=c.src.lastIndexOf("/");return c.name=-1!=f?c.src.slice(f+1):c.src,c},b.play=function(a,c,d,e,f,g,h,i,j){var k;k=createjs.PlayPropsConfig.create(c instanceof Object||c instanceof createjs.PlayPropsConfig?c:{interrupt:c,delay:d,offset:e,loop:f,volume:g,pan:h,startTime:i,duration:j});var l=b.createInstance(a,k.startTime,k.duration),m=b._playInstance(l,k);return m||l._playFailed(),l},b.createInstance=function(c,d,e){if(!b.initializeDefaultPlugins())return new createjs.DefaultSoundInstance(c,d,e);var f=b._defaultPlayPropsHash[c];c=b._getSrcById(c);var g=b._parsePath(c.src),h=null;
return null!=g&&null!=g.src?(a.create(g.src),null==d&&(d=c.startTime),h=b.activePlugin.create(g.src,d,e||c.duration),f=f||b._defaultPlayPropsHash[g.src],f&&h.applyPlayProps(f)):h=new createjs.DefaultSoundInstance(c,d,e),h.uniqueId=b._lastID++,h},b.stop=function(){for(var a=this._instances,b=a.length;b--;)a[b].stop()},b.setVolume=function(a){if(null==Number(a))return!1;if(a=Math.max(0,Math.min(1,a)),b._masterVolume=a,!this.activePlugin||!this.activePlugin.setVolume||!this.activePlugin.setVolume(a))for(var c=this._instances,d=0,e=c.length;e>d;d++)c[d].setMasterVolume(a)},b.getVolume=function(){return this._masterVolume},b.setMute=function(a){if(null==a)return!1;if(this._masterMute=a,!this.activePlugin||!this.activePlugin.setMute||!this.activePlugin.setMute(a))for(var b=this._instances,c=0,d=b.length;d>c;c++)b[c].setMasterMute(a);return!0},b.getMute=function(){return this._masterMute},b.setDefaultPlayProps=function(a,c){a=b._getSrcById(a),b._defaultPlayPropsHash[b._parsePath(a.src).src]=createjs.PlayPropsConfig.create(c)},b.getDefaultPlayProps=function(a){return a=b._getSrcById(a),b._defaultPlayPropsHash[b._parsePath(a.src).src]},b._playInstance=function(a,c){var d=b._defaultPlayPropsHash[a.src]||{};if(null==c.interrupt&&(c.interrupt=d.interrupt||b.defaultInterruptBehavior),null==c.delay&&(c.delay=d.delay||0),null==c.offset&&(c.offset=a.getPosition()),null==c.loop&&(c.loop=a.loop),null==c.volume&&(c.volume=a.volume),null==c.pan&&(c.pan=a.pan),0==c.delay){var e=b._beginPlaying(a,c);if(!e)return!1}else{var f=setTimeout(function(){b._beginPlaying(a,c)},c.delay);a.delayTimeoutId=f}return this._instances.push(a),!0},b._beginPlaying=function(b,c){if(!a.add(b,c.interrupt))return!1;var d=b._beginPlaying(c);if(!d){var e=createjs.indexOf(this._instances,b);return e>-1&&this._instances.splice(e,1),!1}return!0},b._getSrcById=function(a){return b._idHash[a]||{src:a}},b._playFinished=function(b){a.remove(b);var c=createjs.indexOf(this._instances,b);c>-1&&this._instances.splice(c,1)},createjs.Sound=Sound,a.channels={},a.create=function(b,c){var d=a.get(b);return null==d?(a.channels[b]=new a(b,c),!0):!1},a.removeSrc=function(b){var c=a.get(b);return null==c?!1:(c._removeAll(),delete a.channels[b],!0)},a.removeAll=function(){for(var b in a.channels)a.channels[b]._removeAll();a.channels={}},a.add=function(b,c){var d=a.get(b.src);return null==d?!1:d._add(b,c)},a.remove=function(b){var c=a.get(b.src);return null==c?!1:(c._remove(b),!0)},a.maxPerChannel=function(){return c.maxDefault},a.get=function(b){return a.channels[b]};var c=a.prototype;c.constructor=a,c.src=null,c.max=null,c.maxDefault=100,c.length=0,c.init=function(a,b){this.src=a,this.max=b||this.maxDefault,-1==this.max&&(this.max=this.maxDefault),this._instances=[]},c._get=function(a){return this._instances[a]},c._add=function(a,b){return this._getSlot(b,a)?(this._instances.push(a),this.length++,!0):!1},c._remove=function(a){var b=createjs.indexOf(this._instances,a);return-1==b?!1:(this._instances.splice(b,1),this.length--,!0)},c._removeAll=function(){for(var a=this.length-1;a>=0;a--)this._instances[a].stop()},c._getSlot=function(a){var b,c;if(a!=Sound.INTERRUPT_NONE&&(c=this._get(0),null==c))return!0;for(var d=0,e=this.max;e>d;d++){if(b=this._get(d),null==b)return!0;if(b.playState==Sound.PLAY_FINISHED||b.playState==Sound.PLAY_INTERRUPTED||b.playState==Sound.PLAY_FAILED){c=b;break}a!=Sound.INTERRUPT_NONE&&(a==Sound.INTERRUPT_EARLY&&b.getPosition()
c.getPosition())&&(c=b)}return null!=c?(c._interrupt(),this._remove(c),!0):!1},c.toString=function(){return"[Sound SoundChannel]"}}(),this.createjs=this.createjs||{},function(){"use strict";var AbstractSoundInstance=function(a,b,c,d){this.EventDispatcher_constructor(),this.src=a,this.uniqueId=-1,this.playState=null,this.delayTimeoutId=null,this._volume=1,Object.defineProperty(this,"volume",{get:this.getVolume,set:this.setVolume}),this._pan=0,Object.defineProperty(this,"pan",{get:this.getPan,set:this.setPan}),this._startTime=Math.max(0,b||0),Object.defineProperty(this,"startTime",{get:this.getStartTime,set:this.setStartTime}),this._duration=Math.max(0,c||0),Object.defineProperty(this,"duration",{get:this.getDuration,set:this.setDuration}),this._playbackResource=null,Object.defineProperty(this,"playbackResource",{get:this.getPlaybackResource,set:this.setPlaybackResource}),d!==!1&&d!==!0&&this.setPlaybackResource(d),this._position=0,Object.defineProperty(this,"position",{get:this.getPosition,set:this.setPosition}),this._loop=0,Object.defineProperty(this,"loop",{get:this.getLoop,set:this.setLoop}),this._muted=!1,Object.defineProperty(this,"muted",{get:this.getMuted,set:this.setMuted}),this._paused=!1,Object.defineProperty(this,"paused",{get:this.getPaused,set:this.setPaused})},a=createjs.extend(AbstractSoundInstance,createjs.EventDispatcher);a.play=function(a,b,c,d,e,f){var g;return g=createjs.PlayPropsConfig.create(a instanceof Object||a instanceof createjs.PlayPropsConfig?a:{interrupt:a,delay:b,offset:c,loop:d,volume:e,pan:f}),this.playState==createjs.Sound.PLAY_SUCCEEDED?(this.applyPlayProps(g),void(this._paused&&this.setPaused(!1))):(this._cleanUp(),createjs.Sound._playInstance(this,g),this)},a.stop=function(){return this._position=0,this._paused=!1,this._handleStop(),this._cleanUp(),this.playState=createjs.Sound.PLAY_FINISHED,this},a.destroy=function(){this._cleanUp(),this.src=null,this.playbackResource=null,this.removeAllEventListeners()},a.applyPlayProps=function(a){return null!=a.offset&&this.setPosition(a.offset),null!=a.loop&&this.setLoop(a.loop),null!=a.volume&&this.setVolume(a.volume),null!=a.pan&&this.setPan(a.pan),null!=a.startTime&&(this.setStartTime(a.startTime),this.setDuration(a.duration)),this},a.toString=function(){return"[AbstractSoundInstance]"},a.getPaused=function(){return this._paused},a.setPaused=function(a){return a!==!0&&a!==!1||this._paused==a||1==a&&this.playState!=createjs.Sound.PLAY_SUCCEEDED?void 0:(this._paused=a,a?this._pause():this._resume(),clearTimeout(this.delayTimeoutId),this)},a.setVolume=function(a){return a==this._volume?this:(this._volume=Math.max(0,Math.min(1,a)),this._muted||this._updateVolume(),this)},a.getVolume=function(){return this._volume},a.setMuted=function(a){return a===!0||a===!1?(this._muted=a,this._updateVolume(),this):void 0},a.getMuted=function(){return this._muted},a.setPan=function(a){return a==this._pan?this:(this._pan=Math.max(-1,Math.min(1,a)),this._updatePan(),this)},a.getPan=function(){return this._pan},a.getPosition=function(){return this._paused||this.playState!=createjs.Sound.PLAY_SUCCEEDED||(this._position=this._calculateCurrentPosition()),this._position},a.setPosition=function(a){return this._position=Math.max(0,a),this.playState==createjs.Sound.PLAY_SUCCEEDED&&this._updatePosition(),this},a.getStartTime=function(){return this._startTime},a.setStartTime=function(a){return a==this._startTime?this:(this._startTime=Math.max(0,a||0),this._updateStartTime(),this)},a.getDuration=function(){return this._duration},a.setDuration=function(a){return a==this._duration?this:(this._duration=Math.max(0,a||0),this._updateDuration(),this)},a.setPlaybackResource=function(a){return this._playbackResource=a,0==this._duration&&this._setDurationFromSource(),this},a.getPlaybackResource=function(){return this._playbackResource},a.getLoop=function(){return this._loop},a.setLoop=function(a){null!=this._playbackResource&&(0!=this._loop&&0==a?this._removeLooping(a):0==this._loop&&0!=a&&this._addLooping(a)),this._loop=a},a._sendEvent=function(a){var b=new createjs.Event(a);this.dispatchEvent(b)},a._cleanUp=function(){clearTimeout(this.delayTimeoutId),this._handleCleanUp(),this._paused=!1,createjs.Sound._playFinished(this)},a._interrupt=function(){this._cleanUp(),this.playState=createjs.Sound.PLAY_INTERRUPTED,this._sendEvent("interrupted")},a._beginPlaying=function(a){return this.setPosition(a.offset),this.setLoop(a.loop),this.setVolume(a.volume),this.setPan(a.pan),null!=a.startTime&&(this.setStartTime(a.startTime),this.setDuration(a.duration)),null!=this._playbackResource&&this._positionc;c++){var e=this._soundInstances[b][c];e.setPlaybackResource(this._audioSources[b])}},a._handlePreloadError=function(){},a._updateVolume=function(){},createjs.AbstractPlugin=AbstractPlugin}(),this.createjs=this.createjs||{},function(){"use strict";function a(a){this.AbstractLoader_constructor(a,!0,createjs.AbstractLoader.SOUND)}var b=createjs.extend(a,createjs.AbstractLoader);a.context=null,b.toString=function(){return"[WebAudioLoader]"},b._createRequest=function(){this._request=new createjs.XHRRequest(this._item,!1),this._request.setResponseType("arraybuffer")},b._sendComplete=function(){a.context.decodeAudioData(this._rawResult,createjs.proxy(this._handleAudioDecoded,this),createjs.proxy(this._sendError,this))},b._handleAudioDecoded=function(a){this._result=a,this.AbstractLoader__sendComplete()},createjs.WebAudioLoader=createjs.promote(a,"AbstractLoader")}(),this.createjs=this.createjs||{},function(){"use strict";function WebAudioSoundInstance(a,c,d,e){this.AbstractSoundInstance_constructor(a,c,d,e),this.gainNode=b.context.createGain(),this.panNode=b.context.createPanner(),this.panNode.panningModel=b._panningModel,this.panNode.connect(this.gainNode),this._updatePan(),this.sourceNode=null,this._soundCompleteTimeout=null,this._sourceNodeNext=null,this._playbackStartTime=0,this._endedHandler=createjs.proxy(this._handleSoundComplete,this)}var a=createjs.extend(WebAudioSoundInstance,createjs.AbstractSoundInstance),b=WebAudioSoundInstance;b.context=null,b._scratchBuffer=null,b.destinationNode=null,b._panningModel="equalpower",a.destroy=function(){this.AbstractSoundInstance_destroy(),this.panNode.disconnect(0),this.panNode=null,this.gainNode.disconnect(0),this.gainNode=null},a.toString=function(){return"[WebAudioSoundInstance]"},a._updatePan=function(){this.panNode.setPosition(this._pan,0,-.5)},a._removeLooping=function(){this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext)},a._addLooping=function(){this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._sourceNodeNext=this._createAndPlayAudioNode(this._playbackStartTime,0))},a._setDurationFromSource=function(){this._duration=1e3*this.playbackResource.duration},a._handleCleanUp=function(){this.sourceNode&&this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext)),0!=this.gainNode.numberOfOutputs&&this.gainNode.disconnect(0),clearTimeout(this._soundCompleteTimeout),this._playbackStartTime=0},a._cleanUpAudioNode=function(a){if(a){a.stop(0),a.disconnect(0);try{a.buffer=b._scratchBuffer}catch(c){}a=null}return a},a._handleSoundReady=function(){this.gainNode.connect(b.destinationNode);var a=.001*this._duration,c=.001*this._position;c>a&&(c=a),this.sourceNode=this._createAndPlayAudioNode(b.context.currentTime-a,c),this._playbackStartTime=this.sourceNode.startTime-c,this._soundCompleteTimeout=setTimeout(this._endedHandler,1e3*(a-c)),0!=this._loop&&(this._sourceNodeNext=this._createAndPlayAudioNode(this._playbackStartTime,0))},a._createAndPlayAudioNode=function(a,c){var d=b.context.createBufferSource();d.buffer=this.playbackResource,d.connect(this.panNode);var e=.001*this._duration;return d.startTime=a+e,d.start(d.startTime,c+.001*this._startTime,e-c),d},a._pause=function(){this._position=1e3*(b.context.currentTime-this._playbackStartTime),this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext),0!=this.gainNode.numberOfOutputs&&this.gainNode.disconnect(0),clearTimeout(this._soundCompleteTimeout)},a._resume=function(){this._handleSoundReady()},a._updateVolume=function(){var a=this._muted?0:this._volume;a!=this.gainNode.gain.value&&(this.gainNode.gain.value=a)},a._calculateCurrentPosition=function(){return 1e3*(b.context.currentTime-this._playbackStartTime)},a._updatePosition=function(){this.sourceNode=this._cleanUpAudioNode(this.sourceNode),this._sourceNodeNext=this._cleanUpAudioNode(this._sourceNodeNext),clearTimeout(this._soundCompleteTimeout),this._paused||this._handleSoundReady()},a._handleLoop=function(){this._cleanUpAudioNode(this.sourceNode),this.sourceNode=this._sourceNodeNext,this._playbackStartTime=this.sourceNode.startTime,this._sourceNodeNext=this._createAndPlayAudioNode(this._playbackStartTime,0),this._soundCompleteTimeout=setTimeout(this._endedHandler,this._duration)},a._updateDuration=function(){this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._pause(),this._resume())},createjs.WebAudioSoundInstance=createjs.promote(WebAudioSoundInstance,"AbstractSoundInstance")}(),this.createjs=this.createjs||{},function(){"use strict";function WebAudioPlugin(){this.AbstractPlugin_constructor(),this._panningModel=b._panningModel,this.context=b.context,this.dynamicsCompressorNode=this.context.createDynamicsCompressor(),this.dynamicsCompressorNode.connect(this.context.destination),this.gainNode=this.context.createGain(),this.gainNode.connect(this.dynamicsCompressorNode),createjs.WebAudioSoundInstance.destinationNode=this.gainNode,this._capabilities=b._capabilities,this._loaderClass=createjs.WebAudioLoader,this._soundInstanceClass=createjs.WebAudioSoundInstance,this._addPropsToClasses()}var a=createjs.extend(WebAudioPlugin,createjs.AbstractPlugin),b=WebAudioPlugin;b._capabilities=null,b._panningModel="equalpower",b.context=null,b._scratchBuffer=null,b._unlocked=!1,b.isSupported=function(){var a=createjs.BrowserDetect.isIOS||createjs.BrowserDetect.isAndroid||createjs.BrowserDetect.isBlackberry;return"file:"!=location.protocol||a||this._isFileXHRSupported()?(b._generateCapabilities(),null==b.context?!1:!0):!1},b.playEmptySound=function(){if(null!=b.context){var a=b.context.createBufferSource();a.buffer=b._scratchBuffer,a.connect(b.context.destination),a.start(0,0,0)}},b._isFileXHRSupported=function(){var a=!0,b=new XMLHttpRequest;try{b.open("GET","WebAudioPluginTest.fail",!1)}catch(c){return a=!1}b.onerror=function(){a=!1},b.onload=function(){a=404==this.status||200==this.status||0==this.status&&""!=this.response};try{b.send()}catch(c){a=!1}return a},b._generateCapabilities=function(){if(null==b._capabilities){var a=document.createElement("audio");if(null==a.canPlayType)return null;if(null==b.context)if(window.AudioContext)b.context=new AudioContext;else{if(!window.webkitAudioContext)return null;b.context=new webkitAudioContext}null==b._scratchBuffer&&(b._scratchBuffer=b.context.createBuffer(1,1,22050)),b._compatibilitySetUp(),"ontouchstart"in window&&"running"!=b.context.state&&(b._unlock(),document.addEventListener("mousedown",b._unlock,!0),document.addEventListener("touchend",b._unlock,!0)),b._capabilities={panning:!0,volume:!0,tracks:-1};for(var c=createjs.Sound.SUPPORTED_EXTENSIONS,d=createjs.Sound.EXTENSION_MAP,e=0,f=c.length;f>e;e++){var g=c[e],h=d[g]||g;b._capabilities[g]="no"!=a.canPlayType("audio/"+g)&&""!=a.canPlayType("audio/"+g)||"no"!=a.canPlayType("audio/"+h)&&""!=a.canPlayType("audio/"+h)}b.context.destination.numberOfChannels<2&&(b._capabilities.panning=!1)}},b._compatibilitySetUp=function(){if(b._panningModel="equalpower",!b.context.createGain){b.context.createGain=b.context.createGainNode;var a=b.context.createBufferSource();a.__proto__.start=a.__proto__.noteGrainOn,a.__proto__.stop=a.__proto__.noteOff,b._panningModel=0}},b._unlock=function(){b._unlocked||(b.playEmptySound(),"running"==b.context.state&&(document.removeEventListener("mousedown",b._unlock,!0),document.removeEventListener("touchend",b._unlock,!0),b._unlocked=!0))},a.toString=function(){return"[WebAudioPlugin]"},a._addPropsToClasses=function(){var a=this._soundInstanceClass;a.context=this.context,a._scratchBuffer=b._scratchBuffer,a.destinationNode=this.gainNode,a._panningModel=this._panningModel,this._loaderClass.context=this.context},a._updateVolume=function(){var a=createjs.Sound._masterMute?0:this._volume;a!=this.gainNode.gain.value&&(this.gainNode.gain.value=a)},createjs.WebAudioPlugin=createjs.promote(WebAudioPlugin,"AbstractPlugin")}(),this.createjs=this.createjs||{},function(){"use strict";function HTMLAudioTagPool(){throw"HTMLAudioTagPool cannot be instantiated"}function a(){this._tags=[]}var b=HTMLAudioTagPool;b._tags={},b._tagPool=new a,b._tagUsed={},b.get=function(a){var c=b._tags[a];return null==c?(c=b._tags[a]=b._tagPool.get(),c.src=a):b._tagUsed[a]?(c=b._tagPool.get(),c.src=a):b._tagUsed[a]=!0,c},b.set=function(a,c){c==b._tags[a]?b._tagUsed[a]=!1:b._tagPool.set(c)},b.remove=function(a){var c=b._tags[a];return null==c?!1:(b._tagPool.set(c),delete b._tags[a],delete b._tagUsed[a],!0)},b.getDuration=function(a){var c=b._tags[a];return null!=c&&c.duration?1e3*c.duration:0},createjs.HTMLAudioTagPool=HTMLAudioTagPool;var c=a.prototype;c.constructor=a,c.get=function(){var a;return a=0==this._tags.length?this._createTag():this._tags.pop(),null==a.parentNode&&document.body.appendChild(a),a},c.set=function(a){var b=createjs.indexOf(this._tags,a);-1==b&&(this._tags.src=null,this._tags.push(a))},c.toString=function(){return"[TagPool]"},c._createTag=function(){var a=document.createElement("audio");return a.autoplay=!1,a.preload="none",a}}(),this.createjs=this.createjs||{},function(){"use strict";function HTMLAudioSoundInstance(a,b,c,d){this.AbstractSoundInstance_constructor(a,b,c,d),this._audioSpriteStopTime=null,this._delayTimeoutId=null,this._endedHandler=createjs.proxy(this._handleSoundComplete,this),this._readyHandler=createjs.proxy(this._handleTagReady,this),this._stalledHandler=createjs.proxy(this._playFailed,this),this._audioSpriteEndHandler=createjs.proxy(this._handleAudioSpriteLoop,this),this._loopHandler=createjs.proxy(this._handleSoundComplete,this),c?this._audioSpriteStopTime=.001*(b+c):this._duration=createjs.HTMLAudioTagPool.getDuration(this.src)}var a=createjs.extend(HTMLAudioSoundInstance,createjs.AbstractSoundInstance);a.setMasterVolume=function(){this._updateVolume()},a.setMasterMute=function(){this._updateVolume()},a.toString=function(){return"[HTMLAudioSoundInstance]"},a._removeLooping=function(){null!=this._playbackResource&&(this._playbackResource.loop=!1,this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1))},a._addLooping=function(){null==this._playbackResource||this._audioSpriteStopTime||(this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),this._playbackResource.loop=!0)},a._handleCleanUp=function(){var a=this._playbackResource;if(null!=a){a.pause(),a.loop=!1,a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),a.removeEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1);try{a.currentTime=this._startTime}catch(b){}createjs.HTMLAudioTagPool.set(this.src,a),this._playbackResource=null}},a._beginPlaying=function(a){return this._playbackResource=createjs.HTMLAudioTagPool.get(this.src),this.AbstractSoundInstance__beginPlaying(a)},a._handleSoundReady=function(){if(4!==this._playbackResource.readyState){var a=this._playbackResource;return a.addEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),a.addEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),a.preload="auto",void a.load()}this._updateVolume(),this._playbackResource.currentTime=.001*(this._startTime+this._position),this._audioSpriteStopTime?this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1):(this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),0!=this._loop&&(this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),this._playbackResource.loop=!0)),this._playbackResource.play()},a._handleTagReady=function(){this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_READY,this._readyHandler,!1),this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_STALLED,this._stalledHandler,!1),this._handleSoundReady()},a._pause=function(){this._playbackResource.pause()},a._resume=function(){this._playbackResource.play()},a._updateVolume=function(){if(null!=this._playbackResource){var a=this._muted||createjs.Sound._masterMute?0:this._volume*createjs.Sound._masterVolume;a!=this._playbackResource.volume&&(this._playbackResource.volume=a)}},a._calculateCurrentPosition=function(){return 1e3*this._playbackResource.currentTime-this._startTime},a._updatePosition=function(){this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._handleSetPositionSeek,!1);try{this._playbackResource.currentTime=.001*(this._position+this._startTime)}catch(a){this._handleSetPositionSeek(null)}},a._handleSetPositionSeek=function(){null!=this._playbackResource&&(this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._handleSetPositionSeek,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1))},a._handleAudioSpriteLoop=function(){this._playbackResource.currentTime<=this._audioSpriteStopTime||(this._playbackResource.pause(),0==this._loop?this._handleSoundComplete(null):(this._position=0,this._loop--,this._playbackResource.currentTime=.001*this._startTime,this._paused||this._playbackResource.play(),this._sendEvent("loop")))},a._handleLoop=function(){0==this._loop&&(this._playbackResource.loop=!1,this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_SEEKED,this._loopHandler,!1))},a._updateStartTime=function(){this._audioSpriteStopTime=.001*(this._startTime+this._duration),this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1))},a._updateDuration=function(){this._audioSpriteStopTime=.001*(this._startTime+this._duration),this.playState==createjs.Sound.PLAY_SUCCEEDED&&(this._playbackResource.removeEventListener(createjs.HTMLAudioPlugin._AUDIO_ENDED,this._endedHandler,!1),this._playbackResource.addEventListener(createjs.HTMLAudioPlugin._TIME_UPDATE,this._audioSpriteEndHandler,!1))},a._setDurationFromSource=function(){this._duration=createjs.HTMLAudioTagPool.getDuration(this.src),this._playbackResource=null},createjs.HTMLAudioSoundInstance=createjs.promote(HTMLAudioSoundInstance,"AbstractSoundInstance")}(),this.createjs=this.createjs||{},function(){"use strict";function HTMLAudioPlugin(){this.AbstractPlugin_constructor(),this.defaultNumChannels=2,this._capabilities=b._capabilities,this._loaderClass=createjs.SoundLoader,this._soundInstanceClass=createjs.HTMLAudioSoundInstance}var a=createjs.extend(HTMLAudioPlugin,createjs.AbstractPlugin),b=HTMLAudioPlugin;b.MAX_INSTANCES=30,b._AUDIO_READY="canplaythrough",b._AUDIO_ENDED="ended",b._AUDIO_SEEKED="seeked",b._AUDIO_STALLED="stalled",b._TIME_UPDATE="timeupdate",b._capabilities=null,b.isSupported=function(){return b._generateCapabilities(),null!=b._capabilities},b._generateCapabilities=function(){if(null==b._capabilities){var a=document.createElement("audio");if(null==a.canPlayType)return null;b._capabilities={panning:!1,volume:!0,tracks:-1};for(var c=createjs.Sound.SUPPORTED_EXTENSIONS,d=createjs.Sound.EXTENSION_MAP,e=0,f=c.length;f>e;e++){var g=c[e],h=d[g]||g;b._capabilities[g]="no"!=a.canPlayType("audio/"+g)&&""!=a.canPlayType("audio/"+g)||"no"!=a.canPlayType("audio/"+h)&&""!=a.canPlayType("audio/"+h)}}},a.register=function(a){var b=createjs.HTMLAudioTagPool.get(a.src),c=this.AbstractPlugin_register(a);return c.setTag(b),c},a.removeSound=function(a){this.AbstractPlugin_removeSound(a),createjs.HTMLAudioTagPool.remove(a)},a.create=function(a,b,c){var d=this.AbstractPlugin_create(a,b,c);return d.setPlaybackResource(null),d},a.toString=function(){return"[HTMLAudioPlugin]"},a.setVolume=a.getVolume=a.setMute=null,createjs.HTMLAudioPlugin=createjs.promote(HTMLAudioPlugin,"AbstractPlugin")}();
H5P.SoundJS = this.createjs.Sound;
this.createjs = old || this.createjs;
;
var H5P = H5P || {};
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
H5P.SingleChoiceSet.StopWatch = (function () {
/**
* @class {H5P.SingleChoiceSet.StopWatch}
* @constructor
*/
function StopWatch() {
/**
* @property {number} duration in ms
*/
this.duration = 0;
}
/**
* Starts the stop watch
*
* @public
* @return {H5P.SingleChoiceSet.StopWatch}
*/
StopWatch.prototype.start = function () {
/**
* @property {number}
*/
this.startTime = Date.now();
return this;
};
/**
* Stops the stopwatch, and returns the duration in seconds.
*
* @public
* @return {number}
*/
StopWatch.prototype.stop = function () {
this.duration = this.duration + Date.now() - this.startTime;
return this.passedTime();
};
/**
* Sets the duration to 0
*
* @public
*/
StopWatch.prototype.reset = function () {
this.duration = 0;
};
/**
* Returns the passed time in seconds
*
* @public
* @return {number}
*/
StopWatch.prototype.passedTime = function () {
return Math.round(this.duration / 10) / 100;
};
return StopWatch;
})();
;
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
H5P.SingleChoiceSet.SoundEffects = (function () {
let isDefined = false;
const SoundEffects = {
types: [
'positive-short',
'negative-short'
]
};
const players = {};
/**
* Setup defined sounds
*
* @param {string} libraryPath
* @return {boolean} True if setup was successfull, otherwise false
*/
SoundEffects.setup = function (libraryPath) {
if (isDefined) {
return false;
}
isDefined = true;
SoundEffects.types.forEach(async function (type) {
const player = new Audio();
const extension = player.canPlayType('audio/ogg') ? 'ogg' : 'mp3';
const response = await fetch(libraryPath + 'sounds/' + type + '.' + extension);
const data = await response.blob();
player.src = URL.createObjectURL(data);
players[type] = player;
});
return true;
};
/**
* Play a sound
*
* @param {string} type Name of the sound as defined in [SoundEffects.types]{@link H5P.SoundEffects.SoundEffects#types}
* @param {number} delay Delay in milliseconds
*/
SoundEffects.play = function (type, delay) {
if (!players[type]) {
return;
}
setTimeout(function () {
players[type].play();
}, delay || 0);
};
return SoundEffects;
})();
;
var H5P = H5P || {};
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
H5P.SingleChoiceSet.XApiEventBuilder = (function ($, EventDispatcher) {
/**
* @typedef {object} LocalizedString
* @property {string} en-US
*/
/**
* @class {H5P.SingleChoiceSet.XApiEventDefinitionBuilder}
* @constructor
*/
function XApiEventDefinitionBuilder() {
EventDispatcher.call(this);
/**
* @property {object} attributes
* @property {string} attributes.name
* @property {string} attributes.description
* @property {string} attributes.interactionType
* @property {string} attributes.correctResponsesPattern
* @property {object} attributes.optional
*/
this.attributes = {};
}
XApiEventDefinitionBuilder.prototype = Object.create(EventDispatcher.prototype);
XApiEventDefinitionBuilder.prototype.constructor = XApiEventDefinitionBuilder;
/**
* Sets name
* @param {string} name
* @return {XApiEventDefinitionBuilder}
*/
XApiEventDefinitionBuilder.prototype.name = function (name) {
this.attributes.name = name;
return this;
};
/**
* Question text and any additional information to generate the report.
* @param {string} description
* @return {XApiEventDefinitionBuilder}
*/
XApiEventDefinitionBuilder.prototype.description = function (description) {
this.attributes.description = description;
return this;
};
/**
* Type of the interaction.
* @param {string} interactionType
* @see {@link https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#interaction-types|xAPI Spec}
* @return {XApiEventDefinitionBuilder}
*/
XApiEventDefinitionBuilder.prototype.interactionType = function (interactionType) {
this.attributes.interactionType = interactionType;
return this;
};
/**
* A pattern for determining the correct answers of the interaction
* @param {string[]} correctResponsesPattern
* @see {@link https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#response-patterns|xAPI Spec}
* @return {XApiEventDefinitionBuilder}
*/
XApiEventDefinitionBuilder.prototype.correctResponsesPattern = function (correctResponsesPattern) {
this.attributes.correctResponsesPattern = correctResponsesPattern;
return this;
};
/**
* Sets optional attributes
* @param {object} optional Can have one of the following configuration objects: choices, scale, source, target, steps
* @return {XApiEventDefinitionBuilder}
*/
XApiEventDefinitionBuilder.prototype.optional = function (optional) {
this.attributes.optional = optional;
return this;
};
/**
* @return {object}
*/
XApiEventDefinitionBuilder.prototype.build = function () {
var definition = {};
// sets attributes
setAttribute(definition, 'name', localizeToEnUS(this.attributes.name));
setAttribute(definition, 'description', localizeToEnUS(this.attributes.description));
setAttribute(definition, 'interactionType', this.attributes.interactionType);
setAttribute(definition, 'correctResponsesPattern', this.attributes.correctResponsesPattern);
setAttribute(definition, 'type', 'http://adlnet.gov/expapi/activities/cmi.interaction');
// adds the optional object to the definition
if (this.attributes.optional) {
$.extend(definition, this.attributes.optional);
}
return definition;
};
// -----------------------------------------------------
/**
*
* @constructor
*/
function XApiEventResultBuilder() {
EventDispatcher.call(this);
/**
* @property {object} attributes
* @property {string} attributes.completion
* @property {boolean} attributes.success
* @property {boolean} attributes.response
* @property {number} attributes.rawScore
* @property {number} attributes.maxScore
*/
this.attributes = {};
}
XApiEventResultBuilder.prototype = Object.create(EventDispatcher.prototype);
XApiEventResultBuilder.prototype.constructor = XApiEventResultBuilder;
/**
* @param {boolean} completion
* @return {XApiEventResultBuilder}
*/
XApiEventResultBuilder.prototype.completion = function (completion) {
this.attributes.completion = completion;
return this;
};
/**
* @param {boolean} success
* @return {XApiEventResultBuilder}
*/
XApiEventResultBuilder.prototype.success = function (success) {
this.attributes.success = success;
return this;
};
/**
* @param {number} duration The duraction in seconds
* @return {XApiEventResultBuilder}
*/
XApiEventResultBuilder.prototype.duration = function (duration) {
this.attributes.duration = duration;
return this;
};
/**
* Sets response
* @param {string|string[]} response
* @return {XApiEventResultBuilder}
*/
XApiEventResultBuilder.prototype.response = function (response) {
this.attributes.response = (typeof response === 'string') ? response : response.join('[,]');
return this;
};
/**
* Sets the score, and max score
* @param {number} score
* @param {number} maxScore
* @return {XApiEventResultBuilder}
*/
XApiEventResultBuilder.prototype.score = function (score, maxScore) {
this.attributes.rawScore = score;
this.attributes.maxScore = maxScore;
return this;
};
/**
* Builds the result object
* @return {object}
*/
XApiEventResultBuilder.prototype.build = function () {
var result = {};
setAttribute(result, 'response', this.attributes.response);
setAttribute(result, 'completion', this.attributes.completion);
setAttribute(result, 'success', this.attributes.success);
if (isDefined(this.attributes.duration)) {
setAttribute(result, 'duration','PT' + this.attributes.duration + 'S');
}
// sets score
if (isDefined(this.attributes.rawScore)) {
result.score = {};
setAttribute(result.score, 'raw', this.attributes.rawScore);
if (isDefined(this.attributes.maxScore) && this.attributes.maxScore > 0) {
setAttribute(result.score, 'min', 0);
setAttribute(result.score, 'max', this.attributes.maxScore);
setAttribute(result.score, 'min', 0);
setAttribute(result.score, 'scaled', Math.round(this.attributes.rawScore / this.attributes.maxScore * 10000) / 10000);
}
}
return result;
};
// -----------------------------------------------------
/**
* @class {H5P.SingleChoiceSet.XApiEventBuilder}
*/
function XApiEventBuilder() {
EventDispatcher.call(this);
/**
* @property {object} attributes
* @property {string} attributes.contentId
* @property {string} attributes.subContentId
*/
this.attributes = {};
}
XApiEventBuilder.prototype = Object.create(EventDispatcher.prototype);
XApiEventBuilder.prototype.constructor = XApiEventBuilder;
/**
* @param {object} verb
*
* @public
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.prototype.verb = function (verb) {
this.attributes.verb = verb;
return this;
};
/**
* @param {string} name
* @param {string} mbox
* @param {string} objectType
*
* @public
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.prototype.actor = function (name, mbox, objectType) {
this.attributes.actor = {
name: name,
mbox: mbox,
objectType: objectType
};
return this;
};
/**
* Sets contentId
* @param {string} contentId
* @param {string} [subContentId]
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.prototype.contentId = function (contentId, subContentId) {
this.attributes.contentId = contentId;
this.attributes.subContentId = subContentId;
return this;
};
/**
* Sets parent in context
*
* @param {string} parentContentId
* @param {string} [parentSubContentId]
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.prototype.context = function (parentContentId, parentSubContentId) {
this.attributes.parentContentId = parentContentId;
this.attributes.parentSubContentId = parentSubContentId;
return this;
};
/**
* @param {object} result
*
* @public
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.prototype.result = function (result) {
this.attributes.result = result;
return this;
};
/**
* @param {object} objectDefinition
*
* @public
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.prototype.objectDefinition = function (objectDefinition) {
this.attributes.objectDefinition = objectDefinition;
return this;
};
/**
* Returns the buildt event
* @public
* @return {H5P.XAPIEvent}
*/
XApiEventBuilder.prototype.build = function () {
var event = new H5P.XAPIEvent();
event.setActor();
event.setVerb(this.attributes.verb);
// sets context
if (this.attributes.parentContentId || this.attributes.parentSubContentId) {
event.data.statement.context = {
'contextActivities': {
'parent': [
{
'id': getContentXAPIId(this.attributes.parentContentId, this.attributes.parentSubContentId),
'objectType': "Activity"
}
]
}
};
}
event.data.statement.object = {
'id': getContentXAPIId(this.attributes.contentId, this.attributes.subContentId),
'objectType': 'Activity'
};
setAttribute(event.data, 'actor', this.attributes.actor);
setAttribute(event.data.statement, 'result', this.attributes.result);
setAttribute(event.data.statement.object, 'definition', this.attributes.objectDefinition);
// sets h5p specific attributes
if (event.data.statement.object.definition && (this.attributes.contentId || this.attributes.subContentId)) {
var extensions = event.data.statement.object.definition.extensions = {};
setAttribute(extensions, 'http://h5p.org/x-api/h5p-local-content-id', this.attributes.contentId);
setAttribute(extensions, 'http://h5p.org/x-api/h5p-subContentId', this.attributes.subContentId);
}
return event;
};
/**
* Creates a Localized String object for en-US
*
* @param str
* @return {LocalizedString}
*/
var localizeToEnUS = function (str) {
if (str != undefined) {
return {
'en-US': cleanString(str)
};
}
};
/**
* Generates an id for the content
* @param {string} contentId
* @param {string} [subContentId]
*
* @see {@link https://github.com/h5p/h5p-php-library/blob/master/js/h5p-x-api-event.js#L240-L249}
* @return {string}
*/
var getContentXAPIId = function (contentId, subContentId) {
const cid = 'cid-' + contentId;
if (contentId && H5PIntegration && H5PIntegration.contents && H5PIntegration.contents[cid]) {
var id = H5PIntegration.contents[cid].url;
if (subContentId) {
id += '?subContentId=' + subContentId;
}
return id;
}
};
/**
* Removes html elements from string
*
* @param {string} str
* @return {string}
*/
var cleanString = function (str) {
return $('' + str + '
').text().trim();
};
var isDefined = function (val) {
return typeof val !== 'undefined';
};
function setAttribute(obj, key, value, required) {
if (isDefined(value)) {
obj[key] = value;
}
else if (required) {
console.error("xApiEventBuilder: No value for [" + key + "] in", obj);
}
}
/**
* Creates a new XApiEventBuilder
*
* @public
* @static
* @return {H5P.SingleChoiceSet.XApiEventBuilder}
*/
XApiEventBuilder.create = function () {
return new XApiEventBuilder();
};
/**
* Creates a new XApiEventDefinitionBuilder
*
* @public
* @static
* @return {XApiEventDefinitionBuilder}
*/
XApiEventBuilder.createDefinition = function () {
return new XApiEventDefinitionBuilder();
};
/**
* Creates a new XApiEventDefinitionBuilder
*
* @public
* @static
* @return {XApiEventResultBuilder}
*/
XApiEventBuilder.createResult = function () {
return new XApiEventResultBuilder();
};
/**
* Returns choice to be used with 'cmi.interaction' for Activity of type 'choice'
*
* @param {string} id
* @param {string} description
*
* @public
* @static
* @see {@link https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#choice|xAPI-Spec}
* @return {object}
*/
XApiEventBuilder.createChoice = function (id, description) {
return {
id: id,
description: localizeToEnUS(description)
};
};
/**
* Takes an array of correct ids, and joins them to a 'correct response pattern'
*
* @param {string[]} ids
*
* @public
* @static
* @see {@link https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#choice|xAPI-Spec}
* @return {string}
*/
XApiEventBuilder.createCorrectResponsePattern = function (ids) {
return ids.join('[,]');
};
/**
* Interaction types
*
* @readonly
* @enum {String}
*/
XApiEventBuilder.interactionTypes = {
CHOICE: 'choice',
COMPOUND: 'compound',
FILL_IN: 'fill-in',
MATCHING: 'matching',
TRUE_FALSE: 'true-false'
};
/**
* Verbs
*
* @readonly
* @enum {String}
*/
XApiEventBuilder.verbs = {
ANSWERED: 'answered'
};
return XApiEventBuilder;
})(H5P.jQuery, H5P.EventDispatcher);
;
var H5P = H5P || {};
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
/**
* SingleChoiceResultSlide - Represents the result slide
*/
H5P.SingleChoiceSet.ResultSlide = (function ($, EventDispatcher) {
/**
* @constructor
* @param {number} maxscore Max score
*/
function ResultSlide(maxscore) {
EventDispatcher.call(this);
this.$feedbackContainer = $('', {
'class': 'h5p-sc-feedback-container',
'tabindex': '-1'
});
this.$buttonContainer = $('
', {
'class': 'h5p-sc-button-container'
});
var $resultContainer = $('
', {
'class': 'h5p-sc-result-container'
}).append(this.$feedbackContainer)
.append(this.$buttonContainer);
this.$resultSlide = $('
', {
'class': 'h5p-sc-slide h5p-sc-set-results',
'css': {left: (maxscore * 100) + '%'}
}).append($resultContainer);
}
// inherits from EventDispatchers prototype
ResultSlide.prototype = Object.create(EventDispatcher.prototype);
// set the constructor
ResultSlide.prototype.constructor = ResultSlide;
/**
* Focus feedback container.
*/
ResultSlide.prototype.focusScore = function () {
this.$feedbackContainer.focus();
};
/**
* Append the resultslide to a container
*
* @param {jQuery} $container The container
* @return {jQuery} This dom element
*/
ResultSlide.prototype.appendTo = function ($container) {
this.$resultSlide.appendTo($container);
return this.$resultSlide;
};
return ResultSlide;
})(H5P.jQuery, H5P.EventDispatcher);
;
var H5P = H5P || {};
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
H5P.SingleChoiceSet.SolutionView = (function ($, EventDispatcher) {
/**
* Constructor function.
*/
function SolutionView(id, choices, l10n) {
EventDispatcher.call(this);
var self = this;
self.id = id;
this.choices = choices;
self.l10n = l10n;
this.$solutionView = $('
', {
'class': 'h5p-sc-solution-view'
});
// Add header
this.$header = $('
', {
'class': 'h5p-sc-solution-view-header'
}).appendTo(this.$solutionView);
this.$title = $('
', {
'class': 'h5p-sc-solution-view-title',
'html': l10n.solutionViewTitle,
'tabindex': '-1'
});
this.$title = this.addAriaPunctuation(this.$title);
this.$header.append(this.$title);
// Close solution view button
$('
', {
'role': 'button',
'aria-label': l10n.closeButtonLabel + '.',
'class': 'h5p-joubelui-button h5p-sc-close-solution-view',
'click': function () {
self.hide();
}
}).appendTo(this.$header);
self.populate();
}
/**
* Will append the solution view to a container DOM
* @param {jQuery} $container The DOM object to append to
*/
SolutionView.prototype.appendTo = function ($container) {
this.$solutionView.appendTo($container);
};
/**
* Shows the solution view
*/
SolutionView.prototype.show = function () {
var self = this;
self.$solutionView.addClass('visible');
self.$title.focus();
$(document).on('keyup.solutionview', function (event) {
if (event.keyCode === 27) { // Escape
self.hide();
$(document).off('keyup.solutionview');
}
});
};
/**
* Hides the solution view
*/
SolutionView.prototype.hide = function () {
this.$solutionView.removeClass('visible');
this.trigger('hide', this);
};
/**
* Populates the solution view
*/
SolutionView.prototype.populate = function () {
var self = this;
self.$choices = $('', {
'class': 'h5p-sc-solution-choices',
'tabindex': -1,
});
this.choices.forEach(function (choice, index) {
if (choice.question && choice.answers && choice.answers.length !== 0) {
var $question = self.addAriaPunctuation($('', {
'class': 'h5p-sc-solution-question',
html: '' + self.l10n.solutionListQuestionNumber.replace(':num', index + 1) + ' ' + choice.question
}));
self.$choices.append($question);
var $answer = self.addAriaPunctuation($(' ', {
'class': 'h5p-sc-solution-answer',
html: choice.answers[0]
}));
self.$choices.append($answer);
}
});
self.$choices.appendTo(this.$solutionView);
};
/**
* If a jQuery elements text is missing punctuation, add an aria-label to the element
* containing the text, and adding an extra "period"-symbol at the end.
*
* @param {jQuery} $element A jQuery-element
* @returns {jQuery} The mutated jQuery-element
*/
SolutionView.prototype.addAriaPunctuation = function ($element) {
var text = $element.text().trim();
if (!this.hasPunctuation(text)) {
$element.attr('aria-label', text + '.');
}
return $element;
};
/**
* Checks if a string ends with punctuation
*
* @private
* @param {String} text Input string
*/
SolutionView.prototype.hasPunctuation = function (text) {
return /[,.?!]$/.test(text);
};
return SolutionView;
})(H5P.jQuery, H5P.EventDispatcher);
;
var H5P = H5P || {};
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
H5P.SingleChoiceSet.Alternative = (function ($, EventDispatcher) {
/**
* @constructor
*
* @param {object} options Options for the alternative
*/
function Alternative(options) {
EventDispatcher.call(this);
var self = this;
this.options = options;
var triggerAlternativeSelected = function (event) {
self.trigger('alternative-selected', {
correct: self.options.correct,
$element: self.$alternative,
answerIndex: self.options.answerIndex
});
event.preventDefault();
};
this.$alternative = $('', {
'class': 'h5p-sc-alternative h5p-sc-is-' + (this.options.correct ? 'correct' : 'wrong'),
'role': 'radio',
'tabindex': -1,
'on': {
'keydown': function (event) {
switch (event.which) {
case 13: // Enter
case 32: // Space
// Answer question
triggerAlternativeSelected(event);
break;
case 35: // End radio button
// Go to previous Option
self.trigger('lastOption', event);
event.preventDefault();
break;
case 36: // Home radio button
// Go to previous Option
self.trigger('firstOption', event);
event.preventDefault();
break;
case 37: // Left Arrow
case 38: // Up Arrow
// Go to previous Option
self.trigger('previousOption', event);
event.preventDefault();
break;
case 39: // Right Arrow
case 40: // Down Arrow
// Go to next Option
self.trigger('nextOption', event);
event.preventDefault();
break;
}
}
},
'focus': function (event) {
self.trigger('focus', event);
},
'click': triggerAlternativeSelected
});
this.$alternative.append($('', {
'class': 'h5p-sc-progressbar'
}));
this.$alternative.append($('
', {
'class': 'h5p-sc-label',
'html': this.options.text
}));
this.$alternative.append($('
', {
'class': 'h5p-sc-status'
}));
this.$alternative.append($('
', {
'class': 'h5p-sc-a11y',
'aria-hidden': 'true'
}));
}
Alternative.prototype = Object.create(EventDispatcher.prototype);
Alternative.prototype.constructor = Alternative;
/**
* Is this alternative the correct one?
*
* @return {boolean} Correct or not?
*/
Alternative.prototype.isCorrect = function () {
return this.options.correct;
};
/**
* Move focus to this option.
*/
Alternative.prototype.focus = function () {
this.$alternative.focus();
};
/**
* Makes it possible to tab your way to this option.
*/
Alternative.prototype.tabbable = function () {
this.$alternative.attr('tabindex', 0);
};
/**
* Make sure it's NOT possible to tab your way to this option.
*/
Alternative.prototype.notTabbable = function () {
this.$alternative.attr('tabindex', -1);
};
/**
* Append the alternative to a DOM container
*
* @param {jQuery} $container The Dom element to append to
* @return {jQuery} This dom element
*/
Alternative.prototype.appendTo = function ($container) {
$container.append(this.$alternative);
return this.$alternative;
};
return Alternative;
})(H5P.jQuery, H5P.EventDispatcher);
;
var H5P = H5P || {};
H5P.SingleChoiceSet = H5P.SingleChoiceSet || {};
H5P.SingleChoiceSet.SingleChoice = (function ($, EventDispatcher, Alternative) {
/**
* Constructor function.
*/
function SingleChoice(options, index, id, isAutoConfinue) {
EventDispatcher.call(this);
// Extend defaults with provided options
this.options = $.extend(true, {}, {
question: '',
answers: []
}, options);
this.isAutoConfinue = isAutoConfinue;
// Keep provided id.
this.index = index;
this.id = id;
this.answered = false;
for (var i = 0; i < this.options.answers.length; i++) {
this.options.answers[i] = {
text: this.options.answers[i],
correct: i === 0,
answerIndex: i
};
}
// Randomize alternatives
this.options.answers = H5P.shuffleArray(this.options.answers);
}
SingleChoice.prototype = Object.create(EventDispatcher.prototype);
SingleChoice.prototype.constructor = SingleChoice;
/**
* appendTo function invoked to append SingleChoice to container
*
* @param {jQuery} $container
* @param {boolean} isCurrent Current slide we are on
*/
SingleChoice.prototype.appendTo = function ($container, isCurrent) {
var self = this;
this.$container = $container;
// Index of the currently focused option.
var focusedOption;
this.$choice = $('
', {
'class': 'h5p-sc-slide h5p-sc' + (isCurrent ? ' h5p-sc-current-slide' : ''),
css: {'left': (self.index * 100) + '%'}
});
var questionId = 'single-choice-' + self.id + '-question-' + self.index;
this.$choice.append($('
', {
'id': questionId,
'class': 'h5p-sc-question',
'html': this.options.question
}));
var $alternatives = $('
', {
'class': 'h5p-sc-alternatives',
'role': 'radiogroup',
'aria-labelledby': questionId
});
/**
* List of Alternatives
*
* @type {Alternative[]}
*/
this.alternatives = self.options.answers.map(function (opts) {
return new Alternative(opts);
});
/**
* Handles click on an alternative
*/
var handleAlternativeSelected = function (event) {
var $element = event.data.$element;
var correct = event.data.correct;
var answerIndex = event.data.answerIndex;
if ($element.parent().hasClass('h5p-sc-selected')) {
return;
}
self.trigger('alternative-selected', {
correct: correct,
index: self.index,
answerIndex: answerIndex,
currentIndex: $element.index()
});
H5P.Transition.onTransitionEnd($element.find('.h5p-sc-progressbar'), function () {
$element.addClass('h5p-sc-drummed');
self.showResult(correct, answerIndex);
}, 700);
$element.addClass('h5p-sc-selected').parent().addClass('h5p-sc-selected');
// indicate that this question is anwered
this.setAnswered(true);
};
/**
* Handles focusing one of the options, making the rest non-tabbable.
* @private
*/
var handleFocus = function (answer, index) {
// Keep track of currently focused option
focusedOption = index;
// remove tabbable all alternatives
self.alternatives.forEach(function (alternative) {
alternative.notTabbable();
});
answer.tabbable();
};
/**
* Handles moving the focus from the current option to the previous option.
* @private
*/
var handlePreviousOption = function () {
if (focusedOption === 0) {
// wrap around to last
this.focusOnAlternative(self.alternatives.length - 1);
}
else {
this.focusOnAlternative(focusedOption - 1);
}
};
/**
* Handles moving the focus from the current option to the next option.
* @private
*/
var handleNextOption = function () {
if ((focusedOption === this.alternatives.length - 1)) {
// wrap around to first
this.focusOnAlternative(0);
}
else {
this.focusOnAlternative(focusedOption + 1);
}
};
/**
* Handles moving the focus to the first option
* @private
*/
var handleFirstOption = function () {
this.focusOnAlternative(0);
};
/**
* Handles moving the focus to the last option
* @private
*/
var handleLastOption = function () {
this.focusOnAlternative(self.alternatives.length - 1);
};
for (var i = 0; i < this.alternatives.length; i++) {
var alternative = this.alternatives[i];
if (i === 0) {
alternative.tabbable();
}
alternative.appendTo($alternatives);
alternative.on('focus', handleFocus.bind(this, alternative, i), this);
alternative.on('alternative-selected', handleAlternativeSelected, this);
alternative.on('previousOption', handlePreviousOption, this);
alternative.on('nextOption', handleNextOption, this);
alternative.on('firstOption', handleFirstOption, this);
alternative.on('lastOption', handleLastOption, this);
}
this.$choice.append($alternatives);
$container.append(this.$choice);
return this.$choice;
};
/**
* Focus on an alternative by index
*
* @param {Number} index The index of the alternative to focus on
*/
SingleChoice.prototype.focusOnAlternative = function (index) {
if (!this.answered || !this.isAutoConfinue) {
this.alternatives[index].focus();
}
};
/**
* Sets if the question was answered
*
* @param {Boolean} answered If this question was answered
*/
SingleChoice.prototype.setAnswered = function (answered) {
this.answered = answered;
};
/**
* Reveals the result for a question
*
* @param {boolean} correct True uf answer was correct, otherwise false
* @param {number} answerIndex Original index of answer
*/
SingleChoice.prototype.showResult = function (correct, answerIndex) {
var self = this;
var $correctAlternative = self.$choice.find('.h5p-sc-is-correct');
H5P.Transition.onTransitionEnd($correctAlternative, function () {
self.trigger('finished', {
correct: correct,
index: self.index,
answerIndex: answerIndex
});
self.setAriaAttributes();
}, 600);
// Reveal corrects and wrong
self.$choice.find('.h5p-sc-is-wrong').addClass('h5p-sc-reveal-wrong');
$correctAlternative.addClass('h5p-sc-reveal-correct');
};
/**
* Reset a11y text for selected options
*/
SingleChoice.prototype.resetA11yText = function () {
var self = this;
self.$choice.find('.h5p-sc-a11y').text('');
};
/**
* Make a11y text readable for screen reader
*/
SingleChoice.prototype.setA11yTextReadable = function () {
var self = this;
self.$choice.find('.h5p-sc-a11y').attr('aria-hidden', false);
};
/**
* Set aria attributes for choice
*/
SingleChoice.prototype.setAriaAttributes = function () {
var self = this;
// A11y mode is enabled
if (!self.isAutoConfinue) {
self.$choice.find('.h5p-sc-alternative.h5p-sc-selected').attr('aria-checked', true);
self.$choice.find('.h5p-sc-alternative').attr('aria-disabled', true);
}
}
/**
* Reset aria attributes
*/
SingleChoice.prototype.resetAriaAttributes = function () {
var self = this;
// A11y mode is enabled
if (!self.isAutoConfinue) {
const alternative = self.$choice.find('.h5p-sc-alternative');
alternative.removeAttr('aria-disabled');
alternative.removeAttr('aria-checked');
}
};
return SingleChoice;
})(H5P.jQuery, H5P.EventDispatcher, H5P.SingleChoiceSet.Alternative);
;
var H5P = H5P || {};
H5P.SingleChoiceSet = (function ($, UI, Question, SingleChoice, SolutionView, ResultSlide, SoundEffects, XApiEventBuilder, StopWatch) {
/**
* @constructor
* @extends Question
* @param {object} options Options for single choice set
* @param {string} contentId H5P instance id
* @param {Object} contentData H5P instance data
*/
function SingleChoiceSet(options, contentId, contentData) {
var self = this;
// Extend defaults with provided options
this.contentId = contentId;
this.contentData = contentData;
/**
* The users input on the questions. Uses the same index as this.options.choices
* @type {number[]}
*/
this.userResponses = [];
Question.call(this, 'single-choice-set');
this.options = $.extend(true, {}, {
choices: [],
overallFeedback: [],
behaviour: {
autoContinue: true,
timeoutCorrect: 2000,
timeoutWrong: 3000,
soundEffectsEnabled: true,
enableRetry: true,
enableSolutionsButton: true,
passPercentage: 100
}
}, options);
if (contentData && contentData.previousState !== undefined) {
this.currentIndex = contentData.previousState.progress;
this.results = contentData.previousState.answers;
this.userResponses = contentData.previousState.userResponses !== undefined
? contentData.previousState.userResponses
: [];
}
this.currentIndex = this.currentIndex || 0;
this.results = this.results || {
corrects: 0,
wrongs: 0
};
if (!this.options.behaviour.autoContinue) {
this.options.behaviour.timeoutCorrect = 0;
this.options.behaviour.timeoutWrong = 0;
}
/**
* @property {StopWatch[]} Stop watches for tracking duration of slides
*/
this.stopWatches = [];
this.startStopWatch(this.currentIndex);
this.muted = (this.options.behaviour.soundEffectsEnabled === false);
this.l10n = H5P.jQuery.extend({
correctText: 'Correct!',
incorrectText: 'Incorrect!',
shouldSelect: "Should have been selected",
shouldNotSelect: "Should not have been selected",
nextButtonLabel: 'Next question',
showSolutionButtonLabel: 'Show solution',
retryButtonLabel: 'Retry',
closeButtonLabel: 'Close',
solutionViewTitle: 'Solution',
slideOfTotal: 'Slide :num of :total',
muteButtonLabel: "Mute feedback sound",
scoreBarLabel: 'You got :num out of :total points',
solutionListQuestionNumber: 'Question :num',
a11yShowSolution: 'Show the solution. The task will be marked with its correct solution.',
a11yRetry: 'Retry the task. Reset all responses and start the task over again.',
}, options.l10n !== undefined ? options.l10n : {});
this.$container = $('', {
'class': 'h5p-sc-set-wrapper navigatable' + (!this.options.behaviour.autoContinue ? ' next-button-mode' : '')
});
this.$slides = [];
// An array containing the SingleChoice instances
this.choices = [];
/**
* Keeps track of buttons that will be hidden
* @type {Array}
*/
self.buttonsToBeHidden = [];
/**
* The solution dialog
* @type {SolutionView}
*/
this.solutionView = new SolutionView(contentId, this.options.choices, this.l10n);
this.$choices = $('
', {
'class': 'h5p-sc-set h5p-sc-animate'
});
// sometimes an empty object is in the choices
this.options.choices = this.options.choices.filter(function (choice) {
return choice !== undefined && !!choice.answers;
});
var numQuestions = this.options.choices.length;
// Create progressbar
self.progressbar = UI.createProgressbar(numQuestions + 1, {
progressText: this.l10n.slideOfTotal
});
self.progressbar.setProgress(this.currentIndex);
for (var i = 0; i < this.options.choices.length; i++) {
var choice = new SingleChoice(this.options.choices[i], i, this.contentId, this.options.behaviour.autoContinue);
choice.on('finished', this.handleQuestionFinished, this);
choice.on('alternative-selected', this.handleAlternativeSelected, this);
choice.appendTo(this.$choices, (i === this.currentIndex));
this.choices.push(choice);
this.$slides.push(choice.$choice);
}
this.resultSlide = new ResultSlide(this.options.choices.length);
this.resultSlide.appendTo(this.$choices);
this.resultSlide.on('retry', function() {
self.resetTask(true);
}, this);
this.resultSlide.on('view-solution', this.handleViewSolution, this);
this.$slides.push(this.resultSlide.$resultSlide);
this.on('resize', this.resize, this);
// Use the correct starting slide
this.recklessJump(this.currentIndex);
if (this.options.choices.length === this.currentIndex) {
// Make sure results slide is displayed
this.resultSlide.$resultSlide.addClass('h5p-sc-current-slide');
this.setScore(this.results.corrects, true);
}
if (!this.muted) {
setTimeout(function () {
SoundEffects.setup(self.getLibraryFilePath(''));
}, 1);
}
/**
* Override Question's hideButton function
* to be able to hide buttons after delay
*
* @override
* @param {string} id
*/
this.superHideButton = self.hideButton;
this.hideButton = (function () {
return function (id) {
if (!self.scoreTimeout) {
return self.superHideButton(id);
}
self.buttonsToBeHidden.push(id);
return this;
};
})();
}
SingleChoiceSet.prototype = Object.create(Question.prototype);
SingleChoiceSet.prototype.constructor = SingleChoiceSet;
/**
* Set if a element is tabbable or not
*
* @param {jQuery} $element The element
* @param {boolean} tabbable If element should be tabbable
* @returns {jQuery} The element
*/
SingleChoiceSet.prototype.setTabbable = function ($element, tabbable) {
if ($element) {
$element.attr('tabindex', tabbable ? 0 : -1);
}
};
/**
* Handle alternative selected, i.e play sound if sound effects are enabled
*
* @method handleAlternativeSelected
* @param {Object} event Event that was fired
*/
SingleChoiceSet.prototype.handleAlternativeSelected = function (event) {
var self = this;
this.lastAnswerIsCorrect = event.data.correct;
self.toggleNextButton(true);
// Keep track of num correct/wrong answers
this.results[this.lastAnswerIsCorrect ? 'corrects' : 'wrongs']++;
self.triggerXAPI('interacted');
// Read and set a11y friendly texts
self.readA11yFriendlyText(event.data.index, event.data.currentIndex)
if (!this.muted) {
// Can't play it after the transition end is received, since this is not
// accepted on iPad. Therefore we are playing it here with a delay instead
SoundEffects.play(this.lastAnswerIsCorrect ? 'positive-short' : 'negative-short', 700);
}
};
/**
* Handler invoked when question is done
*
* @param {object} event An object containing a single boolean property: "correct".
*/
SingleChoiceSet.prototype.handleQuestionFinished = function (event) {
var self = this;
var index = event.data.index;
// saves user response
var userResponse = self.userResponses[index] = event.data.answerIndex;
// trigger answered event
var duration = this.stopStopWatch(index);
var xapiEvent = self.createXApiAnsweredEvent(self.options.choices[index], userResponse, duration);
self.trigger(xapiEvent);
self.continue(index);
};
/**
* Setup auto continue
*/
SingleChoiceSet.prototype.continue = function (index) {
var self = this;
self.choices[index].setA11yTextReadable();
if (!self.options.behaviour.autoContinue) {
// Set focus to next button
self.$nextButton.focus();
return;
}
var timeout;
var letsMove = function () {
// Handle impatient users
self.$container.off('click.impatient keydown.impatient');
clearTimeout(timeout);
self.next();
};
timeout = setTimeout(function () {
letsMove();
}, self.lastAnswerIsCorrect ? self.options.behaviour.timeoutCorrect : self.options.behaviour.timeoutWrong);
self.onImpatientUser(letsMove);
};
/**
* Listen to impatience
* @param {Function} action Callback
*/
SingleChoiceSet.prototype.onImpatientUser = function (action) {
this.$container.off('click.impatient keydown.impatient');
this.$container.one('click.impatient', action);
this.$container.one('keydown.impatient', function (event) {
// If return, space or right arrow
if ([13,32,39].indexOf(event.which)) {
action();
}
});
};
/**
* Go to next slide
*/
SingleChoiceSet.prototype.next = function () {
this.move(this.currentIndex + 1);
};
/**
* Creates an xAPI answered event
*
* @param {object} question
* @param {number} userAnswer
* @param {number} duration
*
* @return {H5P.XAPIEvent}
*/
SingleChoiceSet.prototype.createXApiAnsweredEvent = function (question, userAnswer, duration) {
var self = this;
var types = XApiEventBuilder.interactionTypes;
// creates the definition object
var definition = XApiEventBuilder.createDefinition()
.interactionType(types.CHOICE)
.description(question.question)
.correctResponsesPattern(self.getXApiCorrectResponsePattern())
.optional( self.getXApiChoices(question.answers))
.build();
// create the result object
var result = XApiEventBuilder.createResult()
.response(userAnswer.toString())
.duration(duration)
.score((userAnswer === 0) ? 1 : 0, 1)
.completion(true)
.success(userAnswer === 0)
.build();
return XApiEventBuilder.create()
.verb(XApiEventBuilder.verbs.ANSWERED)
.objectDefinition(definition)
.context(self.contentId, self.subContentId)
.contentId(self.contentId, question.subContentId)
.result(result)
.build();
};
/**
* Returns the 'correct response pattern' for xApi
*
* @return {string[]}
*/
SingleChoiceSet.prototype.getXApiCorrectResponsePattern = function () {
return [XApiEventBuilder.createCorrectResponsePattern([(0).toString()])]; // is always '0' for SCS
};
/**
* Returns the choices array for xApi statements
*
* @param {String[]} answers
*
* @return {{ choices: []}}
*/
SingleChoiceSet.prototype.getXApiChoices = function (answers) {
var choices = answers.map(function (answer, index) {
return XApiEventBuilder.createChoice(index.toString(), answer);
});
return {
choices: choices
};
};
/**
* Handles buttons that are queued for hiding
*/
SingleChoiceSet.prototype.handleQueuedButtonChanges = function () {
var self = this;
if (self.buttonsToBeHidden.length) {
self.buttonsToBeHidden.forEach(function (id) {
self.superHideButton(id);
});
}
self.buttonsToBeHidden = [];
};
/**
* Set score and feedback
*
* @params {Number} score Number of correct answers
*/
SingleChoiceSet.prototype.setScore = function (score, noXAPI) {
var self = this;
if (!self.choices.length) {
return;
}
var feedbackText = determineOverallFeedback(self.options.overallFeedback , score / self.options.choices.length)
.replace(':numcorrect', score)
.replace(':maxscore', self.options.choices.length.toString());
self.setFeedback(feedbackText, score, self.options.choices.length, self.l10n.scoreBarLabel);
if (score === self.options.choices.length) {
self.hideButton('try-again');
self.hideButton('show-solution');
}
else {
self.showButton('try-again');
self.showButton('show-solution');
}
self.handleQueuedButtonChanges();
self.scoreTimeout = undefined;
if (!noXAPI) {
self.triggerXAPIScored(score, self.options.choices.length, 'completed', true, (100 * score / self.options.choices.length) >= self.options.behaviour.passPercentage);
}
self.trigger('resize');
};
/**
* Handler invoked when view solution is selected
*/
SingleChoiceSet.prototype.handleViewSolution = function () {
var self = this;
var $tryAgainButton = $('.h5p-question-try-again', self.$container);
var $showSolutionButton = $('.h5p-question-show-solution', self.$container);
var buttons = [self.$muteButton, $tryAgainButton, $showSolutionButton];
// remove tabbable for buttons in result view
buttons.forEach(function (button) {
self.setTabbable(button, false);
});
self.solutionView.on('hide', function () {
// re-add tabbable for buttons in result view
buttons.forEach(function (button) {
self.setTabbable(button, true);
});
self.toggleAriaVisibility(true);
// Focus on first button when closing solution view
self.focusButton();
});
self.solutionView.show();
self.toggleAriaVisibility(false);
};
/**
* Toggle elements visibility to Assistive Technologies
*
* @param {boolean} enable Make elements visible
*/
SingleChoiceSet.prototype.toggleAriaVisibility = function (enable) {
var self = this;
var ariaHidden = enable ? '' : 'true';
if (self.$muteButton) {
self.$muteButton.attr('aria-hidden', ariaHidden);
}
self.progressbar.$progressbar.attr('aria-hidden', ariaHidden);
self.$choices.attr('aria-hidden', ariaHidden);
};
/**
* Register DOM elements before they are attached.
* Called from H5P.Question.
*/
SingleChoiceSet.prototype.registerDomElements = function () {
// Register task content area.
this.setContent(this.createQuestion());
// Register buttons with question.
this.addButtons();
// Insert feedback and buttons section on the result slide
this.insertSectionAtElement('feedback', this.resultSlide.$feedbackContainer);
this.insertSectionAtElement('scorebar', this.resultSlide.$feedbackContainer);
this.insertSectionAtElement('buttons', this.resultSlide.$buttonContainer);
// Question is finished
if (this.options.choices.length === this.currentIndex) {
this.trigger('question-finished');
}
this.trigger('resize');
};
/**
* Add Buttons to question.
*/
SingleChoiceSet.prototype.addButtons = function () {
var self = this;
if (this.options.behaviour.enableRetry) {
this.addButton('try-again', this.l10n.retryButtonLabel, function () {
self.resetTask(true);
}, self.results.corrects !== self.options.choices.length, {
'aria-label': this.l10n.a11yRetry,
});
}
if (this.options.behaviour.enableSolutionsButton) {
this.addButton('show-solution', this.l10n.showSolutionButtonLabel, function () {
self.showSolutions();
}, self.results.corrects !== self.options.choices.length, {
'aria-label': this.l10n.a11yShowSolution,
});
}
};
/**
* Create main content
*/
SingleChoiceSet.prototype.createQuestion = function () {
var self = this;
self.progressbar.appendTo(self.$container);
self.$container.append(self.$choices);
function toggleMute(event) {
var $button = $(event.target);
event.preventDefault();
self.muted = !self.muted;
$button.attr('aria-pressed', self.muted);
}
// Keep this out of H5P.Question, since we are moving the button & feedback
// region to the last slide
if (!this.options.behaviour.autoContinue) {
var handleNextClick = function () {
if (self.$nextButton.attr('aria-disabled') !== 'true') {
self.next();
}
};
self.$nextButton = UI.createButton({
'class': 'h5p-ssc-next-button',
'aria-label': self.l10n.nextButtonLabel,
click: handleNextClick,
keydown: function (event) {
switch (event.which) {
case 13: // Enter
case 32: // Space
handleNextClick();
event.preventDefault();
}
},
appendTo: self.$container
});
self.toggleNextButton(false);
}
if (self.options.behaviour.soundEffectsEnabled) {
self.$muteButton = $('
', {
'class': 'h5p-sc-sound-control',
'tabindex': 0,
'role': 'button',
'aria-label': self.l10n.muteButtonLabel,
'aria-pressed': false,
'on': {
'keydown': function (event) {
switch (event.which) {
case 13: // Enter
case 32: // Space
toggleMute(event);
break;
}
}
},
'click': toggleMute,
prependTo: self.$container
});
}
// Append solution view - hidden by default:
self.solutionView.appendTo(self.$container);
self.resize();
// Hide all other slides than the current one:
self.$container.addClass('initialized');
return self.$container;
};
/**
* Resize if something outside resizes
*/
SingleChoiceSet.prototype.resize = function () {
var self = this;
var maxHeight = 0;
self.choices.forEach(function (choice) {
var choiceHeight = choice.$choice.outerHeight();
maxHeight = choiceHeight > maxHeight ? choiceHeight : maxHeight;
});
// Set minimum height for choices
self.$choices.css({minHeight: maxHeight + 'px'});
};
/**
* Disable/enable the next button
* @param {boolean} enable
*/
SingleChoiceSet.prototype.toggleNextButton = function (enable) {
if (this.$nextButton) {
this.$nextButton.attr('aria-disabled', !enable);
}
};
/**
* Will jump to the given slide without any though to animations,
* current slide etc.
*
* @public
*/
SingleChoiceSet.prototype.recklessJump = function (index) {
var tX = 'translateX(' + (-index * 100) + '%)';
this.$choices.css({
'-webkit-transform': tX,
'-moz-transform': tX,
'-ms-transform': tX,
'transform': tX
});
this.progressbar.setProgress(index + 1);
};
/**
* Move to slide n
* @param {number} index The slide number to move to
* @param {boolean} moveFocus True to set focus on first alternative
*/
SingleChoiceSet.prototype.move = function (index, moveFocus = true) {
var self = this;
if (index === this.currentIndex || index > self.$slides.length-1) {
return;
}
var $previousSlide = self.$slides[self.currentIndex];
var $currentChoice = self.choices[index];
var $currentSlide = self.$slides[index];
var isResultSlide = (index >= self.choices.length);
self.toggleNextButton(false);
H5P.Transition.onTransitionEnd(self.$choices, function () {
$previousSlide.removeClass('h5p-sc-current-slide');
// on slides with answers focus on first alternative
// if content is root and not on result slide - always move focus
if (!isResultSlide && (moveFocus || self.isRoot())) {
$currentChoice.focusOnAlternative(0);
}
// on last slide, focus on try again button
else {
self.resultSlide.focusScore();
}
}, 600);
// if should show result slide
if (isResultSlide) {
self.setScore(self.results.corrects);
}
self.$container.toggleClass('navigatable', !isResultSlide);
// start timing of new slide
this.startStopWatch(index);
// move to slide
$currentSlide.addClass('h5p-sc-current-slide');
self.recklessJump(index);
self.currentIndex = index;
};
/**
* Starts a stopwatch for indexed slide
*
* @param {number} index
*/
SingleChoiceSet.prototype.startStopWatch = function (index) {
this.stopWatches[index] = this.stopWatches[index] || new StopWatch();
this.stopWatches[index].start();
};
/**
* Stops a stopwatch for indexed slide
*
* @param {number} index
*/
SingleChoiceSet.prototype.stopStopWatch = function (index) {
if (this.stopWatches[index]) {
this.stopWatches[index].stop();
}
};
/**
* Returns the passed time in seconds of a stopwatch on an indexed slide,
* or 0 if not existing
*
* @param {number} index
* @return {number}
*/
SingleChoiceSet.prototype.timePassedInStopWatch = function (index) {
if (this.stopWatches[index] !== undefined) {
return this.stopWatches[index].passedTime();
}
else {
// if not created, return no passed time,
return 0;
}
};
/**
* Returns the time the user has spent on all questions so far
*
* @return {number}
*/
SingleChoiceSet.prototype.getTotalPassedTime = function () {
return this.stopWatches
.filter(function (watch) {
return watch != undefined;
})
.reduce(function (sum, watch) {
return sum + watch.passedTime();
}, 0);
};
/**
* The following functions implements the CP and IV - Contracts v 1.0 documented here:
* http://h5p.org/node/1009
*/
SingleChoiceSet.prototype.getScore = function () {
return this.results.corrects;
};
SingleChoiceSet.prototype.getMaxScore = function () {
return this.options.choices.length;
};
SingleChoiceSet.prototype.getAnswerGiven = function () {
return (this.results.corrects + this.results.wrongs) > 0;
};
SingleChoiceSet.prototype.getTitle = function () {
return H5P.createTitle((this.contentData && this.contentData.metadata && this.contentData.metadata.title) ? this.contentData.metadata.title : 'Single Choice Set');
};
/**
* Retrieves the xAPI data necessary for generating result reports.
*
* @return {object}
*/
SingleChoiceSet.prototype.getXAPIData = function () {
var self = this;
// create array with userAnswer
var children = self.options.choices.map(function (question, index) {
var userResponse = self.userResponses[index] >= 0 ? self.userResponses[index] : '';
var duration = self.timePassedInStopWatch(index);
var event = self.createXApiAnsweredEvent(question, userResponse, duration);
return {
statement: event.data.statement
};
});
var result = XApiEventBuilder.createResult()
.score(self.getScore(), self.getMaxScore())
.duration(self.getTotalPassedTime())
.build();
// creates the definition object
var definition = XApiEventBuilder.createDefinition()
.interactionType(XApiEventBuilder.interactionTypes.COMPOUND)
.build();
var xAPIEvent = XApiEventBuilder.create()
.verb(XApiEventBuilder.verbs.ANSWERED)
.contentId(self.contentId, self.subContentId)
.context(self.getParentAttribute('contentId'), self.getParentAttribute('subContentId'))
.objectDefinition(definition)
.result(result)
.build();
return {
statement: xAPIEvent.data.statement,
children: children
};
};
/**
* Returns an attribute from this.parent if it exists
*
* @param {string} attributeName
* @return {*|undefined}
*/
SingleChoiceSet.prototype.getParentAttribute = function (attributeName) {
var self = this;
if (self.parent !== undefined) {
return self.parent[attributeName];
}
};
SingleChoiceSet.prototype.showSolutions = function () {
this.handleViewSolution();
};
/**
* Reset all answers. This is equal to refreshing the quiz
* @param {boolean} moveFocus True to move the focus
* This prevents loss of focus if reset from within content
*/
SingleChoiceSet.prototype.resetTask = function (moveFocus = false) {
var self = this;
// Close solution view if visible:
this.solutionView.hide();
// Reset the user's answers
var classes = ['h5p-sc-reveal-wrong', 'h5p-sc-reveal-correct', 'h5p-sc-selected', 'h5p-sc-drummed', 'h5p-sc-correct-answer'];
for (var i = 0; i < classes.length; i++) {
this.$choices.find('.' + classes[i]).removeClass(classes[i]);
}
this.results = {
corrects: 0,
wrongs: 0
};
this.choices.forEach(function (choice) {
choice.setAnswered(false);
choice.resetA11yText();
choice.resetAriaAttributes();
});
this.stopWatches.forEach(function (stopWatch) {
if (stopWatch) {
stopWatch.reset();
}
});
this.move(0, moveFocus);
// Reset userResponses as well
this.userResponses = [];
// Wait for transition, then remove feedback.
H5P.Transition.onTransitionEnd(this.$choices, function () {
self.removeFeedback();
}, 600);
};
/**
* Clever comment.
*
* @public
* @returns {object}
*/
SingleChoiceSet.prototype.getCurrentState = function () {
return this.userResponses.length > 0
? {
progress: this.currentIndex,
answers: this.results,
userResponses: this.userResponses
}
: undefined;
};
/**
* Generate A11y friendly text
*
* @param {number} index
* @param {number} currentIndex
*/
SingleChoiceSet.prototype.readA11yFriendlyText = function (index, currentIndex) {
var self = this;
var correctAnswer = self.$choices.find('.h5p-sc-is-correct')[index].textContent.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
let selectedOptionText = this.lastAnswerIsCorrect ? self.l10n.correctText : self.l10n.incorrectText;
// Announce by ARIA label
if (!self.options.behaviour.autoContinue) {
// Set text for a11y
selectedOptionText = this.lastAnswerIsCorrect ? self.l10n.correctText + self.l10n.shouldSelect : self.l10n.incorrectText + self.l10n.shouldNotSelect;
self.$choices.find('.h5p-sc-current-slide .h5p-sc-is-correct .h5p-sc-a11y').text(self.l10n.shouldSelect);
self.$choices.find('.h5p-sc-current-slide .h5p-sc-is-wrong .h5p-sc-a11y').text(self.l10n.shouldNotSelect);
self.$choices.find('.h5p-sc-current-slide .h5p-sc-alternative').eq(currentIndex).find('.h5p-sc-a11y').text(selectedOptionText);
// Utilize same variable for the read text
selectedOptionText = this.lastAnswerIsCorrect ? self.l10n.correctText : self.l10n.incorrectText + correctAnswer + self.l10n.shouldSelect;
}
self.read(selectedOptionText);
};
/**
* Determine the overall feedback to display for the question.
* Returns empty string if no matching range is found.
*
* @param {Object[]} feedbacks
* @param {number} scoreRatio
* @return {string}
*/
var determineOverallFeedback = function (feedbacks, scoreRatio) {
scoreRatio = Math.floor(scoreRatio * 100);
for (var i = 0; i < feedbacks.length; i++) {
var feedback = feedbacks[i];
var hasFeedback = (feedback.feedback !== undefined && feedback.feedback.trim().length !== 0);
if (feedback.from <= scoreRatio && feedback.to >= scoreRatio && hasFeedback) {
return feedback.feedback;
}
}
return '';
};
return SingleChoiceSet;
})(H5P.jQuery, H5P.JoubelUI, H5P.Question, H5P.SingleChoiceSet.SingleChoice, H5P.SingleChoiceSet.SolutionView, H5P.SingleChoiceSet.ResultSlide, H5P.SingleChoiceSet.SoundEffects, H5P.SingleChoiceSet.XApiEventBuilder, H5P.SingleChoiceSet.StopWatch);
;
var H5P = H5P || {};
/**
* Constructor.
*
* @param {Object} params Options for this library.
* @param {Number} id Content identifier
* @returns {undefined}
*/
(function ($) {
H5P.Image = function (params, id, extras) {
H5P.EventDispatcher.call(this);
this.extras = extras;
if (params.file === undefined || !(params.file instanceof Object)) {
this.placeholder = true;
}
else {
this.source = H5P.getPath(params.file.path, id);
this.width = params.file.width;
this.height = params.file.height;
}
this.alt = (!params.decorative && params.alt !== undefined) ?
this.stripHTML(this.htmlDecode(params.alt)) :
'';
if (params.title !== undefined) {
this.title = this.stripHTML(this.htmlDecode(params.title));
}
};
H5P.Image.prototype = Object.create(H5P.EventDispatcher.prototype);
H5P.Image.prototype.constructor = H5P.Image;
/**
* Wipe out the content of the wrapper and put our HTML in it.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
H5P.Image.prototype.attach = function ($wrapper) {
var self = this;
var source = this.source;
if (self.$img === undefined) {
if(self.placeholder) {
self.$img = $('
', {
width: '100%',
height: '100%',
class: 'h5p-placeholder',
title: this.title === undefined ? '' : this.title,
on: {
load: function () {
self.trigger('loaded');
}
}
});
} else {
self.$img = $('
', {
width: '100%',
height: '100%',
src: source,
alt: this.alt,
title: this.title === undefined ? '' : this.title,
on: {
load: function () {
self.trigger('loaded');
}
}
});
}
}
$wrapper.addClass('h5p-image').html(self.$img);
};
/**
* Retrieve decoded HTML encoded string.
*
* @param {string} input HTML encoded string.
* @returns {string} Decoded string.
*/
H5P.Image.prototype.htmlDecode = function (input) {
const dparser = new DOMParser().parseFromString(input, 'text/html');
return dparser.documentElement.textContent;
};
/**
* Retrieve string without HTML tags.
*
* @param {string} input Input string.
* @returns {string} Output string.
*/
H5P.Image.prototype.stripHTML = function (html) {
const div = document.createElement('div');
div.innerHTML = html;
return div.textContent || div.innerText || '';
};
return H5P.Image;
}(H5P.jQuery));
;
/*
* flowplayer.js 3.2.12. The Flowplayer API
*
* Copyright 2009-2011 Flowplayer Oy
*
* This file is part of Flowplayer.
*
* Flowplayer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Flowplayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Flowplayer. If not, see
.
*
* Date: ${date}
* Revision: ${revision}
*/
!function(){function h(p){console.log("$f.fireEvent",[].slice.call(p))}function l(r){if(!r||typeof r!="object"){return r}var p=new r.constructor();for(var q in r){if(r.hasOwnProperty(q)){p[q]=l(r[q])}}return p}function n(u,r){if(!u){return}var p,q=0,s=u.length;if(s===undefined){for(p in u){if(r.call(u[p],p,u[p])===false){break}}}else{for(var t=u[0];q
1){var u=arguments[1],r=(arguments.length==3)?arguments[2]:{};if(typeof u=="string"){u={src:u}}u=j({bgcolor:"#000000",version:[10,1],expressInstall:"http://releases.flowplayer.org/swf/expressinstall.swf",cachebusting:false},u);if(typeof p=="string"){if(p.indexOf(".")!=-1){var t=[];n(o(p),function(){t.push(new b(this,l(u),l(r)))});return new d(t)}else{var s=c(p);return new b(s!==null?s:l(p),l(u),l(r))}}else{if(p){return new b(p,l(u),l(r))}}}return null};j(window.$f,{fireEvent:function(){var q=[].slice.call(arguments);var r=$f(q[0]);return r?r._fireEvent(q.slice(1)):null},addPlugin:function(p,q){b.prototype[p]=q;return $f},each:n,extend:j});if(typeof jQuery=="function"){jQuery.fn.flowplayer=function(r,q){if(!arguments.length||typeof arguments[0]=="number"){var p=[];this.each(function(){var s=$f(this);if(s){p.push(s)}});return arguments.length?p[arguments[0]]:new d(p)}return this.each(function(){$f(this,l(r),q?l(q):{})})}}}();!function(){var h=document.all,j="http://get.adobe.com/flashplayer",c=typeof jQuery=="function",e=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,b={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};if(window.attachEvent){window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}})}function i(m,l){if(l){for(var f in l){if(l.hasOwnProperty(f)){m[f]=l[f]}}}return m}function a(f,n){var m=[];for(var l in f){if(f.hasOwnProperty(l)){m[l]=n(f[l])}}return m}window.flashembed=function(f,m,l){if(typeof f=="string"){f=document.getElementById(f.replace("#",""))}if(!f){return}if(typeof m=="string"){m={src:m}}return new d(f,i(i({},b),m),l)};var g=i(window.flashembed,{conf:b,getVersion:function(){var m,f;try{f=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(o){try{m=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");f=m&&m.GetVariable("$version")}catch(n){try{m=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");f=m&&m.GetVariable("$version")}catch(l){}}}f=e.exec(f);return f?[1*f[1],1*f[(f[1]*1>9?2:3)]*1]:[0,0]},asString:function(l){if(l===null||l===undefined){return null}var f=typeof l;if(f=="object"&&l.push){f="array"}switch(f){case"string":l=l.replace(new RegExp('(["\\\\])',"g"),"\\$1");l=l.replace(/^\s?(\d+\.?\d*)%/,"$1pct");return'"'+l+'"';case"array":return"["+a(l,function(o){return g.asString(o)}).join(",")+"]";case"function":return'"function()"';case"object":var m=[];for(var n in l){if(l.hasOwnProperty(n)){m.push('"'+n+'":'+g.asString(l[n]))}}return"{"+m.join(",")+"}"}return String(l).replace(/\s/g," ").replace(/\'/g,'"')},getHTML:function(o,l){o=i({},o);var n='";if(o.w3c||h){n+=' '}o.width=o.height=o.id=o.w3c=o.src=null;o.onFail=o.version=o.expressInstall=null;for(var m in o){if(o[m]){n+=' '}}var p="";if(l){for(var f in l){if(l[f]){var q=l[f];p+=f+"="+(/function|object/.test(typeof q)?g.asString(q):q)+"&"}}p=p.slice(0,-1);n+=' "}n+=" ";return n},isSupported:function(f){return k[0]>f[0]||k[0]==f[0]&&k[1]>=f[1]}});var k=g.getVersion();function d(f,n,m){if(g.isSupported(n.version)){f.innerHTML=g.getHTML(n,m)}else{if(n.expressInstall&&g.isSupported([6,65])){f.innerHTML=g.getHTML(i(n,{src:n.expressInstall}),{MMredirectURL:encodeURIComponent(location.href),MMplayerType:"PlugIn",MMdoctitle:document.title})}else{if(!f.innerHTML.replace(/\s/g,"")){f.innerHTML="Flash version "+n.version+" or greater is required "+(k[0]>0?"Your version is "+k:"You have no flash plugin installed")+" "+(f.tagName=="A"?" Click here to download latest version
":"
Download latest version from here
");if(f.tagName=="A"||f.tagName=="DIV"){f.onclick=function(){location.href=j}}}if(n.onFail){var l=n.onFail.call(this);if(typeof l=="string"){f.innerHTML=l}}}}if(h){window[n.id]=document.getElementById(n.id)}i(this,{getRoot:function(){return f},getOptions:function(){return n},getConf:function(){return m},getApi:function(){return f.firstChild}})}if(c){jQuery.tools=jQuery.tools||{version:"3.2.12"};jQuery.tools.flashembed={conf:b};jQuery.fn.flashembed=function(l,f){return this.each(function(){$(this).data("flashembed",flashembed(this,l,f))})}}}();;
var H5P = H5P || {};
/**
* H5P audio module
*
* @external {jQuery} $ H5P.jQuery
*/
H5P.Audio = (function ($) {
/**
* @param {Object} params Options for this library.
* @param {Number} id Content identifier.
* @param {Object} extras Extras.
* @returns {undefined}
*/
function C(params, id, extras) {
H5P.EventDispatcher.call(this);
this.contentId = id;
this.params = params;
this.extras = extras;
this.toggleButtonEnabled = true;
// Retrieve previous state
if (extras && extras.previousState !== undefined) {
this.oldTime = extras.previousState.currentTime;
}
this.params = $.extend({}, {
playerMode: 'minimalistic',
fitToWrapper: false,
controls: true,
autoplay: false,
audioNotSupported: "Your browser does not support this audio",
playAudio: "Play audio",
pauseAudio: "Pause audio"
}, params);
this.on('resize', this.resize, this);
}
C.prototype = Object.create(H5P.EventDispatcher.prototype);
C.prototype.constructor = C;
/**
* Adds a minimalistic audio player with only "play" and "pause" functionality.
*
* @param {jQuery} $container Container for the player.
* @param {boolean} transparentMode true: the player is only visible when hovering over it; false: player's UI always visible
*/
C.prototype.addMinimalAudioPlayer = function ($container, transparentMode) {
var INNER_CONTAINER = 'h5p-audio-inner';
var AUDIO_BUTTON = 'h5p-audio-minimal-button';
var PLAY_BUTTON = 'h5p-audio-minimal-play';
var PLAY_BUTTON_PAUSED = 'h5p-audio-minimal-play-paused';
var PAUSE_BUTTON = 'h5p-audio-minimal-pause';
var self = this;
this.$container = $container;
self.$inner = $('
', {
'class': INNER_CONTAINER + (transparentMode ? ' h5p-audio-transparent' : '')
}).appendTo($container);
var audioButton = $('
', {
'class': AUDIO_BUTTON + " " + PLAY_BUTTON,
'aria-label': this.params.playAudio
}).appendTo(self.$inner)
.click( function () {
if (!self.isEnabledToggleButton()) {
return;
}
// Prevent ARIA from playing over audio on click
this.setAttribute('aria-hidden', 'true');
if (self.audio.paused) {
self.play();
}
else {
self.pause();
}
})
.on('focusout', function () {
// Restore ARIA, required when playing longer audio and tabbing out and back in
this.setAttribute('aria-hidden', 'false');
});
//Fit to wrapper
if (this.params.fitToWrapper) {
audioButton.css({
'width': '100%',
'height': '100%'
});
}
// cpAutoplay is passed from coursepresentation
if (this.params.autoplay) {
self.play();
}
//Event listeners that change the look of the player depending on events.
self.audio.addEventListener('ended', function () {
audioButton
.attr('aria-hidden', false)
.attr('aria-label', self.params.playAudio)
.removeClass(PAUSE_BUTTON)
.removeClass(PLAY_BUTTON_PAUSED)
.addClass(PLAY_BUTTON);
});
self.audio.addEventListener('play', function () {
audioButton
.attr('aria-label', self.params.pauseAudio)
.removeClass(PLAY_BUTTON)
.removeClass(PLAY_BUTTON_PAUSED)
.addClass(PAUSE_BUTTON);
});
self.audio.addEventListener('pause', function () {
audioButton
.attr('aria-hidden', false)
.attr('aria-label', self.params.playAudio)
.removeClass(PAUSE_BUTTON)
.addClass(PLAY_BUTTON_PAUSED);
});
this.$audioButton = audioButton;
//Scale icon to container
self.resize();
};
/**
* Resizes the audio player icon when the wrapper is resized.
*/
C.prototype.resize = function () {
// Find the smallest value of height and width, and use it to choose the font size.
if (this.params.fitToWrapper && this.$container && this.$container.width()) {
var w = this.$container.width();
var h = this.$container.height();
if (w < h) {
this.$audioButton.css({'font-size': w / 2 + 'px'});
}
else {
this.$audioButton.css({'font-size': h / 2 + 'px'});
}
}
};
return C;
})(H5P.jQuery);
/**
* Wipe out the content of the wrapper and put our HTML in it.
*
* @param {jQuery} $wrapper Our poor container.
*/
H5P.Audio.prototype.attach = function ($wrapper) {
$wrapper.addClass('h5p-audio-wrapper');
// Check if browser supports audio.
var audio = document.createElement('audio');
if (audio.canPlayType === undefined) {
// Try flash
this.attachFlash($wrapper);
return;
}
// Add supported source files.
if (this.params.files !== undefined && this.params.files instanceof Object) {
for (var i = 0; i < this.params.files.length; i++) {
var file = this.params.files[i];
if (audio.canPlayType(file.mime)) {
var source = document.createElement('source');
source.src = H5P.getPath(file.path, this.contentId);
source.type = file.mime;
audio.appendChild(source);
}
}
}
if (!audio.children.length) {
// Try flash
this.attachFlash($wrapper);
return;
}
if (this.endedCallback !== undefined) {
audio.addEventListener('ended', this.endedCallback, false);
}
audio.className = 'h5p-audio';
audio.controls = this.params.controls === undefined ? true : this.params.controls;
audio.preload = 'auto';
audio.style.display = 'block';
if (this.params.fitToWrapper === undefined || this.params.fitToWrapper) {
audio.style.width = '100%';
if (!this.isRoot()) {
// Only set height if this isn't a root
audio.style.height = '100%';
}
}
this.audio = audio;
if (this.params.playerMode === 'minimalistic') {
audio.controls = false;
this.addMinimalAudioPlayer($wrapper, false);
}
else if (this.params.playerMode === 'transparent') {
audio.controls = false;
this.addMinimalAudioPlayer($wrapper, true);
}
else {
audio.autoplay = this.params.autoplay === undefined ? false : this.params.autoplay;
$wrapper.html(audio);
}
// Set time to saved time from previous run
if (this.oldTime) {
this.seekTo(this.oldTime);
}
};
/**
* Attaches a flash audio player to the wrapper.
*
* @param {jQuery} $wrapper Our dear container.
*/
H5P.Audio.prototype.attachFlash = function ($wrapper) {
if (this.params.files !== undefined && this.params.files instanceof Object) {
for (var i = 0; i < this.params.files.length; i++) {
var file = this.params.files[i];
if (file.mime === 'audio/mpeg' || file.mime === 'audio/mp3') {
var audioSource = H5P.getPath(file.path, this.contentId);
break;
}
}
}
if (audioSource === undefined) {
$wrapper.addClass('h5p-audio-not-supported');
$wrapper.html(
'
' +
'
' +
'
' + this.params.audioNotSupported + ' ' +
'
'
);
if (this.endedCallback !== undefined) {
this.endedCallback();
}
return;
}
var options = {
buffering: true,
clip: {
url: window.location.protocol + '//' + window.location.host + audioSource,
autoPlay: this.params.autoplay === undefined ? false : this.params.autoplay,
scaling: 'fit'
},
plugins: {
controls: null
}
};
if (this.params.controls === undefined || this.params.controls) {
options.plugins.controls = {
fullscreen: false,
autoHide: false
};
}
if (this.endedCallback !== undefined) {
options.clip.onFinish = this.endedCallback;
options.clip.onError = this.endedCallback;
}
this.flowplayer = flowplayer($wrapper[0], {
src: "http://releases.flowplayer.org/swf/flowplayer-3.2.16.swf",
wmode: "opaque"
}, options);
};
/**
* Stop the audio. TODO: Rename to pause?
*
* @returns {undefined}
*/
H5P.Audio.prototype.stop = function () {
if (this.flowplayer !== undefined) {
this.flowplayer.stop().close().unload();
}
if (this.audio !== undefined) {
this.audio.pause();
}
};
/**
* Play
*/
H5P.Audio.prototype.play = function () {
if (this.flowplayer !== undefined) {
this.flowplayer.play();
}
if (this.audio !== undefined) {
this.audio.play();
}
};
/**
* @public
* Pauses the audio.
*/
H5P.Audio.prototype.pause = function () {
if (this.audio !== undefined) {
this.audio.pause();
}
};
/**
* @public
* Seek to audio position.
*
* @param {number} seekTo Time to seek to in seconds.
*/
H5P.Audio.prototype.seekTo = function (seekTo) {
if (this.audio !== undefined) {
this.audio.currentTime = seekTo;
}
};
/**
* @public
* Get current state for resetting it later.
*
* @returns {object} Current state.
*/
H5P.Audio.prototype.getCurrentState = function () {
if (this.audio !== undefined) {
const currentTime = this.audio.ended ? 0 : this.audio.currentTime;
return {
currentTime: currentTime
};
}
};
/**
* @public
* Disable button.
* Not using disabled attribute to block button activation, because it will
* implicitly set tabindex = -1 and confuse ChromeVox navigation. Clicks handled
* using "pointer-events: none" in CSS.
*/
H5P.Audio.prototype.disableToggleButton = function () {
this.toggleButtonEnabled = false;
if (this.$audioButton) {
this.$audioButton.addClass(H5P.Audio.BUTTON_DISABLED);
}
};
/**
* @public
* Enable button.
*/
H5P.Audio.prototype.enableToggleButton = function () {
this.toggleButtonEnabled = true;
if (this.$audioButton) {
this.$audioButton.removeClass(H5P.Audio.BUTTON_DISABLED);
}
};
/**
* @public
* Check if button is enabled.
* @return {boolean} True, if button is enabled. Else false.
*/
H5P.Audio.prototype.isEnabledToggleButton = function () {
return this.toggleButtonEnabled;
};
/** @constant {string} */
H5P.Audio.BUTTON_DISABLED = 'h5p-audio-disabled';
;
!function(e){var r={};function t(a){if(r[a])return r[a].exports;var n=r[a]={i:a,l:!1,exports:{}};return e[a].call(n.exports,n,n.exports,t),n.l=!0,n.exports}t.m=e,t.c=r,t.d=function(e,r,a){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:a})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var a=Object.create(null);if(t.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)t.d(a,n,function(r){return e[r]}.bind(null,n));return a},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=1)}([function(e,r,t){},function(e,r,t){"use strict";t.r(r);t(0);function a(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}function n(e,r){for(var t=0;t
4&&void 0!==arguments[4]?arguments[4]:{};return a(this,e),this.card=r,this.params=t||{},this.id=n,this.contentId=s,this.callbacks=o,this.$cardWrapper=i("",{class:"h5p-dialogcards-cardwrap",role:"group",tabindex:"-1"}),"repetition"!==this.params.mode&&this.$cardWrapper.attr("aria-labelledby","h5p-dialogcards-progress-"+H5P.Dialogcards.idCounter),this.$cardHolder=i("
",{class:"h5p-dialogcards-cardholder"}).appendTo(this.$cardWrapper),this.createCardContent(r).appendTo(this.$cardHolder),this}var r,t,s;return r=e,(t=[{key:"createCardContent",value:function(e){var r=i("
",{class:"h5p-dialogcards-card-content"});this.createCardImage(e).appendTo(r);var t=i("
",{class:"h5p-dialogcards-card-text-wrapper"}).appendTo(r),a=i("
",{class:"h5p-dialogcards-card-text-inner"}).appendTo(t),n=i("
",{class:"h5p-dialogcards-card-text-inner-content"}).appendTo(a);this.createCardAudio(e).appendTo(n);var s=i("
",{class:"h5p-dialogcards-card-text"}).appendTo(n);return this.$cardTextArea=i("
",{class:"h5p-dialogcards-card-text-area",tabindex:"-1",html:e.text}).appendTo(s),e.text&&e.text.length||s.addClass("hide"),this.createCardFooter().appendTo(t),r}},{key:"createCardImage",value:function(e){this.$image;var r=i("
",{class:"h5p-dialogcards-image-wrapper"});return void 0!==e.image?(this.image=e.image,this.$image=i('
'),e.imageAltText&&this.$image.attr("alt",e.imageAltText)):this.$image=i('
'),this.$image.appendTo(r),r}},{key:"createCardAudio",value:function(e){if(this.audio,this.$audioWrapper=i("
",{class:"h5p-dialogcards-audio-wrapper"}),void 0!==e.audio){var r={files:e.audio,audioNotSupported:this.params.audioNotSupported};this.audio=new H5P.Audio(r,this.contentId),this.audio.attach(this.$audioWrapper),this.audio.audio&&this.audio.audio.preload&&(this.audio.audio.preload="none")}else this.$audioWrapper.addClass("hide");return this.$audioWrapper}},{key:"createCardFooter",value:function(){var e=i("
",{class:"h5p-dialogcards-card-footer"}),r="h5p-dialogcards-button-hidden",t="-1";return"repetition"===this.params.mode&&(r="",this.params.behaviour.quickProgression&&(r="h5p-dialogcards-quick-progression",t="0")),this.$buttonTurn=H5P.JoubelUI.createButton({class:"h5p-dialogcards-turn",html:this.params.answer}).appendTo(e),this.$buttonShowSummary=H5P.JoubelUI.createButton({class:"h5p-dialogcards-show-summary h5p-dialogcards-button-gone",html:this.params.showSummary}).appendTo(e),this.$buttonIncorrect=H5P.JoubelUI.createButton({class:"h5p-dialogcards-answer-button",html:this.params.incorrectAnswer}).addClass("incorrect").addClass(r).attr("tabindex",t).appendTo(e),this.$buttonCorrect=H5P.JoubelUI.createButton({class:"h5p-dialogcards-answer-button",html:this.params.correctAnswer}).addClass("correct").addClass(r).attr("tabindex",t).appendTo(e),e}},{key:"createButtonListeners",value:function(){var e=this;this.$buttonIncorrect.unbind("click").click((function(r){r.target.classList.contains("h5p-dialogcards-quick-progression")&&e.callbacks.onNextCard({cardId:e.id,result:!1})})),this.$buttonTurn.unbind("click").click((function(){e.turnCard()})),this.$buttonCorrect.unbind("click").click((function(r){r.target.classList.contains("h5p-dialogcards-quick-progression")&&e.callbacks.onNextCard({cardId:e.id,result:!0})}))}},{key:"showSummaryButton",value:function(e){this.getDOM().find(".h5p-dialogcards-answer-button").addClass("h5p-dialogcards-button-hidden").attr("tabindex","-1"),this.$buttonTurn.addClass("h5p-dialogcards-button-gone"),this.$buttonShowSummary.click((function(){return e()})).removeClass("h5p-dialogcards-button-gone").focus()}},{key:"hideSummaryButton",value:function(){"normal"!==this.params.mode&&(this.getDOM().find(".h5p-dialogcards-answer-button").removeClass("h5p-dialogcards-button-hidden").attr("tabindex","0"),this.$buttonTurn.removeClass("h5p-dialogcards-button-gone"),this.$buttonShowSummary.addClass("h5p-dialogcards-button-gone"))}},{key:"turnCard",value:function(){var e=this,r=this.getDOM(),t=r.find(".h5p-dialogcards-card-content"),a=r.find(".h5p-dialogcards-cardholder").addClass("h5p-dialogcards-collapse");t.find(".joubel-tip-container").remove();var n=t.hasClass("h5p-dialogcards-turned");t.toggleClass("h5p-dialogcards-turned",!n),setTimeout((function(){if(a.removeClass("h5p-dialogcards-collapse"),e.changeText(n?e.getText():e.getAnswer()),n?a.find(".h5p-audio-inner").removeClass("hide"):e.removeAudio(a),"repetition"===e.params.mode&&!e.params.behaviour.quickProgression){var i=r.find(".h5p-dialogcards-answer-button");!1===i.hasClass("h5p-dialogcards-quick-progression")&&i.addClass("h5p-dialogcards-quick-progression").attr("tabindex",0)}setTimeout((function(){e.addTipToCard(t,n?"front":"back"),"function"==typeof e.callbacks.onCardTurned&&e.callbacks.onCardTurned(n)}),200),e.resizeOverflowingText(),e.$cardTextArea.focus()}),200)}},{key:"changeText",value:function(e){this.$cardTextArea.html(e),this.$cardTextArea.toggleClass("hide",!e||!e.length)}},{key:"setProgressText",value:function(e,r){if("repetition"===this.params.mode){var t=this.params.progressText.replace("@card",e.toString()).replace("@total",r.toString());this.$cardWrapper.attr("aria-label",t)}}},{key:"resizeOverflowingText",value:function(){if(this.params.behaviour.scaleTextNotCard){var e=this.getDOM().find(".h5p-dialogcards-card-text"),r=e.children();this.resizeTextToFitContainer(e,r)}}},{key:"resizeTextToFitContainer",value:function(r,t){t.css("font-size","");var a=r.get(0).getBoundingClientRect().height,n=t.get(0).getBoundingClientRect().height,i=parseFloat(r.css("font-size")),s=parseFloat(t.css("font-size")),o=this.getDOM().closest(".h5p-container"),d=parseFloat(o.css("font-size"));if(n>a)for(var c=!0;c;){if((s-=e.SCALEINTERVAL)
d){l=!1;break}t.css("font-size",s/i+"em"),(n=t.get(0).getBoundingClientRect().height)>=a&&(l=!1,s-=e.SCALEINTERVAL,t.css("font-size",s/i+"em"))}}},{key:"addTipToCard",value:function(e,r,t){"back"!==r&&(r="front"),void 0===t&&(t=this.id),e.find(".joubel-tip-container").remove();var a=this.card.tips;if(void 0!==a&&void 0!==a[r]){var n=a[r].trim();n.length&&e.find(".h5p-dialogcards-card-text-wrapper .h5p-dialogcards-card-text-inner").after(H5P.JoubelUI.createTip(n,{tipLabel:this.params.tipButtonLabel}))}}},{key:"setCardFocus",value:function(e){if(!0===e)this.$cardTextArea.focus();else{var r=this.getDOM();r.one("transitionend",(function(){r.focus()}))}}},{key:"stopAudio",value:function(){var e=this;this.audio&&this.audio.audio&&(this.audio.audio.duration>0&&(this.audio.audio.currentTime=this.audio.audio.duration),this.audio.audio.load&&setTimeout((function(){e.audio.audio.load()}),100))}},{key:"removeAudio",value:function(){this.stopAudio(),this.getDOM().find(".h5p-audio-inner").addClass("hide")}},{key:"getDOM",value:function(){return this.$cardWrapper}},{key:"getText",value:function(){return this.card.text}},{key:"getAnswer",value:function(){return this.card.answer}},{key:"getImage",value:function(){return this.$image}},{key:"getImageSize",value:function(){return this.image?{width:this.image.width,height:this.image.height}:this.image}},{key:"getAudio",value:function(){return this.$audioWrapper}},{key:"reset",value:function(){var e=this.getDOM();e.removeClass("h5p-dialogcards-previous"),e.removeClass("h5p-dialogcards-current"),this.changeText(this.getText());var r=e.find(".h5p-dialogcards-card-content");r.removeClass("h5p-dialogcards-turned"),this.addTipToCard(r,"front",this.id),this.params.behaviour.quickProgression||e.find(".h5p-dialogcards-answer-button").removeClass("h5p-dialogcards-quick-progression"),this.hideSummaryButton()}}])&&n(r.prototype,t),s&&n(r,s),e}();s.SCALEINTERVAL=.2,s.MAXSCALE=16,s.MINSCALE=4;var o=s;function d(e,r){for(var t=0;tthis.cards.length))return"number"==typeof this.cards[e]&&this.loadCard(e),this.cards[e]}},{key:"getCardIds",value:function(){return this.cards.map((function(e,r){return r}))}},{key:"loadCard",value:function(e){e<0||e>this.cards.length||"number"==typeof this.cards[e]&&(this.cards[e]=new o(this.params.dialogs[e],this.params,e,this.contentId,this.callbacks))}}])&&d(r.prototype,t),a&&d(r,a),e}();function l(e){return function(e){if(Array.isArray(e))return u(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,r){if(!e)return;if("string"==typeof e)return u(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);"Object"===t&&e.constructor&&(t=e.constructor.name);if("Map"===t||"Set"===t)return Array.from(e);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return u(e,r)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,a=new Array(r);t0&&void 0!==arguments[0]?arguments[0]:[];return h(this,e),this.cards=r.filter((function(e,t){return r.indexOf(e)>=t})),this}var r,t,a;return r=e,(t=[{key:"getCards",value:function(){return this.cards}},{key:"peek",value:function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return r=Math.max(0,r),"top"===e&&(e=0),"bottom"===e&&(e=this.cards.length-r),e<0||e>this.cards.length-1?[]:this.cards.slice(e,e+r)}},{key:"add",value:function(e){var r=this,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top";"number"==typeof e&&(e=[e]),e.forEach((function(a){var n;-1===r.cards.indexOf(a)&&("top"===t?t=0:"bottom"===t?t=r.cards.length:"random"===t&&(t=Math.floor(Math.random()*r.cards.length)),(n=r.cards).splice.apply(n,[t,0].concat(l(e))))}))}},{key:"push",value:function(e){this.add(e,"top")}},{key:"pull",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top";return e=Math.max(1,Math.min(e,this.cards.length)),"top"===r&&(r=0),"bottom"===r&&(r=-e),r=Math.max(0,Math.min(r,this.cards.length-1)),this.cards.splice(r,e)}},{key:"remove",value:function(e){var r=this;"number"==typeof e&&(e=[e]),e.forEach((function(e){var t=r.cards.indexOf(e);t>-1&&r.cards.splice(t,1)}))}},{key:"shuffle",value:function(){for(var e=this.cards.length-1;e>0;e--){var r=Math.floor(Math.random()*(e+1)),t=[this.cards[r],this.cards[e]];this.cards[e]=t[0],this.cards[r]=t[1]}return this.cards}},{key:"contains",value:function(e){return-1!==this.cards.indexOf(e)}},{key:"length",value:function(){return this.cards.length}}])&&p(r.prototype,t),a&&p(r,a),e}();function f(e){return function(e){if(Array.isArray(e))return m(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,r){if(!e)return;if("string"==typeof e)return m(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);"Object"===t&&e.constructor&&(t=e.constructor.name);if("Map"===t||"Set"===t)return Array.from(e);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return m(e,r)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function m(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,a=new Array(r);t0;t--){var a=Math.floor(Math.random()*(t+1)),n=[r[a],r[t]];r[t]=n[0],r[a]=n[1]}return r}},{key:"find",value:function(e){var r=-1;return this.cardPiles.forEach((function(t,a){if(-1!==r)return r;t.contains(e)&&(r=a)})),r}},{key:"reset",value:function(e){this.createPiles(e)}},{key:"getCard",value:function(e){return this.cardPool.getCard(e)}},{key:"getSize",value:function(){return this.cardPool.getCardIds().length}},{key:"getPiles",value:function(){return this.cardPiles}},{key:"getPileSizes",value:function(){return this.cardPiles.map((function(e){return e.length()}))}}])&&v(r.prototype,t),a&&v(r,a),e}();function y(e,r){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",t=document.createElement("div");t.classList.add("h5p-dialogcards-summary-container");var a=document.createElement("div");a.classList.add("h5p-dialogcards-summary-header"),a.innerHTML=e,t.appendChild(a);var n=document.createElement("div");n.classList.add("h5p-dialogcards-summary-subheader"),n.innerHTML=r,t.appendChild(n);var i=document.createElement("table");return i.classList.add("h5p-dialogcards-summary-table"),t.appendChild(i),t}},{key:"addTableRow",value:function(e,r){var t=e.getElementsByClassName("h5p-dialogcards-summary-table")[0],a=document.createElement("tr"),n=document.createElement("td");n.classList.add("h5p-dialogcards-summary-table-row-category"),n.innerHTML=r.category,a.appendChild(n);var i=document.createElement("td");i.classList.add("h5p-dialogcards-summary-table-row-symbol"),void 0!==r.symbol&&""!==r.symbol&&i.classList.add(r.symbol),a.appendChild(i);var s=document.createElement("td");return s.classList.add("h5p-dialogcards-summary-table-row-score"),a.appendChild(s),t.appendChild(a),s}},{key:"update",value:function(){var e=this,r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=r.done,a=void 0!==t&&t,n=r.round,i=void 0===n?void 0:n,s=r.message,o=void 0===s?void 0:s,d=r.results,c=void 0===d?[]:d;!0===a?(this.fields.buttonStartOver.classList.add("h5p-dialogcards-button-gone"),this.params.behaviour.enableRetry?(this.fields.button.classList.remove("h5p-dialogcards-button-next-round"),this.fields.button.classList.add("h5p-dialogcards-button-restart"),this.fields.button.innerHTML=this.params.retry,this.fields.button.title=this.params.retry,this.currentCallback=this.callbacks.retry):this.fields.button.classList.add("h5p-dialogcards-button-gone")):(this.fields.buttonStartOver.classList.remove("h5p-dialogcards-button-gone"),this.fields.button.classList.add("h5p-dialogcards-button-next-round"),this.fields.button.classList.remove("h5p-dialogcards-button-restart"),this.fields.button.innerHTML=this.params.nextRound,this.fields.button.title=this.params.nextRound,this.currentCallback=this.callbacks.nextRound),H5P.jQuery(this.fields.button).unbind("click").click(this.currentCallback),this.fields.round.innerHTML=this.params.round.replace("@round",i),a||void 0===i||(this.fields.button.innerHTML=this.params.nextRound.replace("@round",i+1),this.fields.button.title=this.params.nextRound.replace("@round",i+1)),a&&void 0!==o&&""!==o?(this.fields.message.classList.remove("h5p-dialogcards-gone"),this.fields.message.innerHTML=o):this.fields.message.classList.add("h5p-dialogcards-gone"),c.forEach((function(r){var t=void 0!==r.score.value?r.score.value:"";void 0!==r.score.max&&(t="".concat(t,' / ').concat(r.score.max)),e.fields[r.field].innerHTML=t}))}},{key:"show",value:function(){this.container.classList.remove("h5p-dialogcards-gone"),this.fields.button.focus()}},{key:"hide",value:function(){this.container.classList.add("h5p-dialogcards-gone")}},{key:"createConfirmationDialog",value:function(e,r){e=e||{};var t=new H5P.ConfirmationDialog({instance:e.instance,headerText:e.l10n.header,dialogText:e.l10n.body,cancelText:e.l10n.cancelLabel,confirmText:e.l10n.confirmLabel});return t.on("confirmed",(function(){r()})),t.appendTo(this.getContainer()),t}},{key:"getContainer",value:function(){var e=H5P.jQuery('[data-content-id="'+self.contentId+'"].h5p-content'),r=e.parents(".h5p-container");return(0!==r.length?r.last():0!==e.length?e:H5P.jQuery(document.body)).get(0)}}])&&y(r.prototype,t),a&&y(r,a),e}();function w(e){return(w="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function S(e,r){return(S=Object.setPrototypeOf||function(e,r){return e.__proto__=r,e})(e,r)}function x(e){var r=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}();return function(){var t,a=I(e);if(r){var n=I(this).constructor;t=Reflect.construct(a,arguments,n)}else t=a.apply(this,arguments);return T(this,t)}}function T(e,r){return!r||"object"!==w(r)&&"function"!=typeof r?k(e):r}function k(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function I(e){return(I=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}var $=H5P.jQuery,P=H5P.JoubelUI,A=function(e){!function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(r&&r.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),r&&S(e,r)}(t,H5P.EventDispatcher);var r=x(t);function t(e,a,n){var i;return function(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}(this,t),t.idCounter++,(i=r.call(this)).contentId=i.id=a,i.previousState=n.previousState||{},i.contentData=n||{},i.params=$.extend({title:"",mode:"normal",description:"Sit in pairs and make up sentences where you include the expressions below. Example: I should have said yes, HOWEVER I kept my mouth shut.",next:"Next",prev:"Previous",retry:"Retry",answer:"Turn",correctAnswer:"I got it right!",incorrectAnswer:"I got it wrong",round:"Round @round",cardsLeft:"Cards left: @number",nextRound:"Proceed to round @round",startOver:"Start over",showSummary:"Next",summary:"Summary",summaryCardsRight:"Cards you got right:",summaryCardsWrong:"Cards you got wrong:",summaryCardsNotShown:"Cards in pool not shown:",summaryOverallScore:"Overall Score",summaryCardsCompleted:"Cards you have completed learning:",summaryCompletedRounds:"Completed rounds:",summaryAllDone:"Well done! You got all @cards cards correct @max times in a row each!",progressText:"Card @card of @total",cardFrontLabel:"Card front",cardBackLabel:"Card back",tipButtonLabel:"Show tip",audioNotSupported:"Your browser does not support this audio",confirmStartingOver:{header:"Start over?",body:"All progress will be lost. Are you sure you want to start over?",cancelLabel:"Cancel",confirmLabel:"Start over"},dialogs:[{text:"Horse",answer:"Hest"},{text:"Cow",answer:"Ku"}],behaviour:{enableRetry:!0,disableBackwardsNavigation:!1,scaleTextNotCard:!1,randomCards:!1,maxProficiency:5,quickProgression:!1}},e),i.cards=[],i.currentCardId=0,i.round=0,i.results=i.previousState.results||[],i.attach=function(e){i.$inner=e.addClass("h5p-dialogcards"),i.params.behaviour.scaleTextNotCard&&e.addClass("h5p-text-scaling");var r={mode:i.params.mode,dialogs:i.params.dialogs,audioNotSupported:i.params.audioNotSupported,answer:i.params.answer,showSummary:i.params.showSummary,incorrectAnswer:i.params.incorrectAnswer,correctAnswer:i.params.correctAnswer,progressText:i.params.progressText,tipButtonLabel:i.params.tipButtonLabel,behaviour:{scaleTextNotCard:i.params.behaviour.scaleTextNotCard,maxProficiency:i.params.behaviour.maxProficiency,quickProgression:i.params.behaviour.quickProgression},cardPiles:i.previousState.cardPiles};i.cardManager=new b(r,i.id,{onCardTurned:i.handleCardTurned,onNextCard:i.nextCard}),i.createDOM(0===i.round),void 0!==i.previousState.currentCardId&&(i.gotoCard(i.previousState.currentCardId),"repetition"===i.params.mode&&i.results.length===i.cardIds.length&&i.showSummary(!0)),i.updateNavigation(),i.trigger("resize")},i.createDOM=function(e){if(i.cardIds=e&&i.previousState.cardIds?i.previousState.cardIds:i.cardManager.createSelection(),i.cardPoolSize=i.cardPoolSize||i.cardManager.getSize(),!0===e){var r=$(""+i.params.title+"
").text().trim();i.$header=$((r?'":"")+''+i.params.description+"
"),i.summaryScreen=new C(i.params,{nextRound:i.nextRound,retry:i.restartRepetition})}!0===e?i.$cardwrapperSet=i.initCards(i.cardIds):(i.$cardwrapperSet.detach(),i.$cardwrapperSet=i.initCards(i.cardIds),i.$cardSideAnnouncer.before(i.$cardwrapperSet)),i.$cardwrapperSet.prepend(i.summaryScreen.getDOM()),!0===e&&(i.$cardSideAnnouncer=$("",{html:i.params.cardFrontLabel,class:"h5p-dialogcards-card-side-announcer","aria-live":"polite","aria-hidden":"true"}),i.$footer=i.createFooter(),i.$mainContent=$("
").append(i.$header).append(i.$cardwrapperSet).append(i.$cardSideAnnouncer).append(i.$footer).appendTo(i.$inner),i.on("reset",(function(){this.reset()})),i.on("resize",i.resize),i.round=void 0!==i.previousState.round?i.previousState.round:1)},i.createFooter=function(){var e=$("
",{class:"h5p-dialogcards-footer",role:"navigation"});return"normal"===i.params.mode?(i.$prev=P.createButton({class:"h5p-dialogcards-footer-button h5p-dialogcards-prev truncated","aria-label":i.params.prev,title:i.params.prev}).click((function(){i.prevCard()})).appendTo(e),i.$next=P.createButton({class:"h5p-dialogcards-footer-button h5p-dialogcards-next truncated","aria-label":i.params.next,title:i.params.next}).click((function(){i.nextCard()})).appendTo(e),i.$retry=P.createButton({class:"h5p-dialogcards-footer-button h5p-dialogcards-retry h5p-dialogcards-disabled",title:i.params.retry,html:i.params.retry}).click((function(){i.trigger("reset")})).appendTo(e),i.$progress=$("",{id:"h5p-dialogcards-progress-"+t.idCounter,class:"h5p-dialogcards-progress","aria-live":"assertive"}).appendTo(e)):(i.$round=$("
",{class:"h5p-dialogcards-round"}).appendTo(e),i.$progress=$("
",{class:"h5p-dialogcards-cards-left","aria-live":"assertive"}).appendTo(e)),e},i.updateImageSize=function(){var e=0,r=i.cards[i.currentCardId].getDOM().find(".h5p-dialogcards-card-content");if(i.params.dialogs.forEach((function(t){if(t.image){var a=t.image.height/t.image.width*r.get(0).getBoundingClientRect().width;a>e&&(e=a)}})),e>0){var t=e/parseFloat(i.$inner.css("font-size"));t>15&&(t=15),i.cards.forEach((function(e){e.getImage().parent().css("height",t+"em")}))}},i.initCards=function(e){i.cards=[],i.currentCardId=0,i.params.behaviour.randomCards&&(e=H5P.shuffleArray(e));for(var r=$("
",{class:"h5p-dialogcards-cardwrap-set"}),t=0;t
=2);t++){var a=i.getCard(e[t]);a.setProgressText(t+1,e.length),i.cards.push(a);var n=a.getDOM();t===i.currentCardId&&(n.addClass("h5p-dialogcards-current"),i.$current=n),a.addTipToCard(n.find(".h5p-dialogcards-card-content"),"front",t),r.append(n)}return r},i.handleCardTurned=function(e){i.$cardSideAnnouncer.html(e?i.params.cardFrontLabel:i.params.cardBackLabel),i.params.behaviour.enableRetry&&i.currentCardId+1===i.cardIds.length&&i.$retry&&(i.$retry.removeClass("h5p-dialogcards-disabled"),i.truncateRetryButton())},i.updateNavigation=function(){if("normal"===i.params.mode)i.getCurrentSelectionIndex()0&&!i.params.behaviour.disableBackwardsNavigation?i.$prev.removeClass("h5p-dialogcards-disabled"):i.$prev.addClass("h5p-dialogcards-disabled"),i.$progress.text(i.params.progressText.replace("@card",i.getCurrentSelectionIndex()+1).replace("@total",i.cardIds.length)),i.cards[i.findCardPosition(i.cards[i.currentCardId].id)].resizeOverflowingText();else{i.$round.text(i.params.round.replace("@round",i.round));var e=i.getCurrentSelectionIndex();i.$progress.text(i.params.cardsLeft.replace("@number",i.cardIds.length-e))}i.trigger("resize")},i.showSummary=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],r=e?i.cardManager.getPileSizes():i.cardManager.updatePiles(i.results),t=i.results.filter((function(e){return!0===e.result})).length,a=i.results.length-t,n=i.cardPoolSize-t-a,s=r.slice(-1)[0],o=s===i.cardPoolSize,d={round:i.round,results:[{field:"h5p-dialogcards-round-cards-right",score:{value:t,max:a+t}},{field:"h5p-dialogcards-round-cards-wrong",score:{value:a,max:a+t}},{field:"h5p-dialogcards-round-cards-not-shown",score:{value:n}},{field:"h5p-dialogcards-overall-cards-completed",score:{value:s,max:i.cardPoolSize}},{field:"h5p-dialogcards-overall-completed-rounds",score:{value:i.round}}]};o&&(d.done=!0,d.message=i.params.summaryAllDone.replace("@cards",i.cardPoolSize).replace("@max",i.params.behaviour.maxProficiency-1)),i.summaryScreen.update(d),i.summaryScreen.show(),i.hideCards(),i.trigger("resize")},i.showCards=function(){i.$cardwrapperSet.find(".h5p-dialogcards-cardwrap").removeClass("h5p-dialogcards-gone"),i.$footer.removeClass("h5p-dialogcards-gone"),i.cardsShown=!0},i.hideCards=function(){i.$cardwrapperSet.find(".h5p-dialogcards-cardwrap").addClass("h5p-dialogcards-gone"),i.$footer.addClass("h5p-dialogcards-gone"),i.cardsShown=!1},i.nextCard=function(e){void 0!==e&&i.results.push(e),i.cards[i.currentCardId].stopAudio(),i.cardIds.length-i.getCurrentSelectionIndex()!=1?i.gotoCard(i.getCurrentSelectionIndex()+1):"repetition"===i.params.mode&&(i.$progress.text(i.params.cardsLeft.replace("@number",0)),i.cards[i.currentCardId].showSummaryButton(i.showSummary))},i.getCard=function(e){var r=i.cardManager.getCard(e);return r.createButtonListeners(),r},i.findCardPosition=function(e){var r;return i.cards.forEach((function(t,a){r||t.id!==e||(r=a)})),r},i.insertCardToDOM=function(e,r){var t=e.getDOM();void 0===r?t.appendTo(i.$cardwrapperSet):0===r?i.$cardwrapperSet.prepend(t):i.$cardwrapperSet.children().eq(r).after(t),e.addTipToCard(t.find(".h5p-dialogcards-card-content"),"front",r)},i.gotoCard=function(e){if(!(e<0||e>=i.cardIds.length)){var r=i.cards[i.currentCardId];r.stopAudio(),r.getDOM().removeClass("h5p-dialogcards-current");var t=[];e>0&&t.push(e-1),t.push(e),e+1e?r:e,!$(this).next(".h5p-dialogcards-cardwrap").length){var t=$(this).find(".h5p-dialogcards-cardholder").css("height","initial").outerHeight();e=t>e?t:e,$(this).find(".h5p-dialogcards-cardholder").css("height","inherit")}}));var r=e/parseFloat(i.$cardwrapperSet.css("font-size"));i.$cardwrapperSet.css("height",r+"em"),i.scaleToFitHeight(),i.truncateRetryButton(),i.cards[i.currentCardId].resizeOverflowingText()},i.determineCardSizes=function(){var e=k(i);void 0===i.cardSizeDetermined&&(i.cardSizeDetermined=[]),i.$cardwrapperSet.children(":visible").each((function(r){var t=e.cards[r].id;if(-1===e.cardSizeDetermined.indexOf(t)){e.cardSizeDetermined.push(t);var a=$(".h5p-dialogcards-card-content",this),n=$(".h5p-dialogcards-card-text-inner-content",a),i=n[0].getBoundingClientRect().height,s=e.cards[r];s.changeText(s.getAnswer());var o=n[0].getBoundingClientRect().height,d=i>o?i:o,c=parseFloat(n.parent().parent().css("minHeight"));dt.MAXSCALE){d=!1;break}var c=o/s;i.$inner.css("font-size",c+"em"),r<=(n=a())&&(d=!1,c=(o-t.SCALEINTERVAL)/s,i.$inner.css("font-size",c+"em"))}}else i.cards[i.currentCardId].resizeOverflowingText()},i.truncateRetryButton=function(){if(i.$retry){i.$retry.removeClass("truncated"),i.$retry.html(i.params.retry);(i.$retry.get(0).getBoundingClientRect().width+parseFloat(i.$retry.css("margin-left"))+parseFloat(i.$retry.css("margin-right")))/i.$retry.parent().get(0).getBoundingClientRect().width>.3&&(i.$retry.addClass("truncated"),i.$retry.html(""))}},i.getCurrentSelectionIndex=function(){return i.cardIds.indexOf(i.cards[i.currentCardId].id)},i.getTitle=function(){return H5P.createTitle(i.contentData&&i.contentData.metadata&&i.contentData.metadata.title?i.contentData.metadata.title:"Dialog Cards")},i.getCurrentState=function(){return{cardPiles:i.cardManager.getPiles(),cardIds:i.cardIds,round:i.round,currentCardId:i.getCurrentSelectionIndex(),results:i.results}},i}return t}();A.idCounter=0,A.SCALEINTERVAL=.2,A.MAXSCALE=16,A.MINSCALE=4;var O=A;H5P.Dialogcards=O}]);;
/** @namespace H5P */
H5P.VideoYouTube = (function ($) {
/**
* YouTube video player for H5P.
*
* @class
* @param {Array} sources Video files to use
* @param {Object} options Settings for the player
* @param {Object} l10n Localization strings
*/
function YouTube(sources, options, l10n) {
var self = this;
var player;
var playbackRate = 1;
var id = 'h5p-youtube-' + numInstances;
numInstances++;
var $wrapper = $('
');
var $placeholder = $('
', {
id: id,
text: l10n.loading
}).appendTo($wrapper);
// Optional placeholder
// var $placeholder = $('VIDEO ').appendTo($wrapper);
/**
* Use the YouTube API to create a new player
*
* @private
*/
var create = function () {
if (!$placeholder.is(':visible') || player !== undefined) {
return;
}
if (window.YT === undefined) {
// Load API first
loadAPI(create);
return;
}
if (YT.Player === undefined) {
return;
}
var width = $wrapper.width();
if (width < 200) {
width = 200;
}
var loadCaptionsModule = true;
var videoId = getId(sources[0].path);
player = new YT.Player(id, {
width: width,
height: width * (9/16),
videoId: videoId,
playerVars: {
origin: ORIGIN,
autoplay: options.autoplay ? 1 : 0,
controls: options.controls ? 1 : 0,
disablekb: options.controls ? 0 : 1,
fs: 0,
loop: options.loop ? 1 : 0,
playlist: options.loop ? videoId : undefined,
rel: 0,
showinfo: 0,
iv_load_policy: 3,
wmode: "opaque",
start: options.startAt,
playsinline: 1
},
events: {
onReady: function () {
self.trigger('ready');
self.trigger('loaded');
},
onApiChange: function () {
if (loadCaptionsModule) {
loadCaptionsModule = false;
// Always load captions
player.loadModule('captions');
}
var trackList;
try {
// Grab tracklist from player
trackList = player.getOption('captions', 'tracklist');
}
catch (err) {}
if (trackList && trackList.length) {
// Format track list into valid track options
var trackOptions = [];
for (var i = 0; i < trackList.length; i++) {
trackOptions.push(new H5P.Video.LabelValue(trackList[i].displayName, trackList[i].languageCode));
}
// Captions are ready for loading
self.trigger('captions', trackOptions);
}
},
onStateChange: function (state) {
if (state.data > -1 && state.data < 4) {
// Fix for keeping playback rate in IE11
if (H5P.Video.IE11_PLAYBACK_RATE_FIX && state.data === H5P.Video.PLAYING && playbackRate !== 1) {
// YT doesn't know that IE11 changed the rate so it must be reset before it's set to the correct value
player.setPlaybackRate(1);
player.setPlaybackRate(playbackRate);
}
// End IE11 fix
self.trigger('stateChange', state.data);
}
},
onPlaybackQualityChange: function (quality) {
self.trigger('qualityChange', quality.data);
},
onPlaybackRateChange: function (playbackRate) {
self.trigger('playbackRateChange', playbackRate.data);
},
onError: function (error) {
var message;
switch (error.data) {
case 2:
message = l10n.invalidYtId;
break;
case 100:
message = l10n.unknownYtId;
break;
case 101:
case 150:
message = l10n.restrictedYt;
break;
default:
message = l10n.unknownError + ' ' + error.data;
break;
}
self.trigger('error', message);
}
}
});
};
/**
* Indicates if the video must be clicked for it to start playing.
* For instance YouTube videos on iPad must be pressed to start playing.
*
* @public
*/
self.pressToPlay = navigator.userAgent.match(/iPad/i) ? true : false;
/**
* Appends the video player to the DOM.
*
* @public
* @param {jQuery} $container
*/
self.appendTo = function ($container) {
$container.addClass('h5p-youtube').append($wrapper);
create();
};
/**
* Get list of available qualities. Not available until after play.
*
* @public
* @returns {Array}
*/
self.getQualities = function () {
if (!player || !player.getAvailableQualityLevels) {
return;
}
var qualities = player.getAvailableQualityLevels();
if (!qualities.length) {
return; // No qualities
}
// Add labels
for (var i = 0; i < qualities.length; i++) {
var quality = qualities[i];
var label = (LABELS[quality] !== undefined ? LABELS[quality] : 'Unknown'); // TODO: l10n
qualities[i] = {
name: quality,
label: LABELS[quality]
};
}
return qualities;
};
/**
* Get current playback quality. Not available until after play.
*
* @public
* @returns {String}
*/
self.getQuality = function () {
if (!player || !player.getPlaybackQuality) {
return;
}
var quality = player.getPlaybackQuality();
return quality === 'unknown' ? undefined : quality;
};
/**
* Set current playback quality. Not available until after play.
* Listen to event "qualityChange" to check if successful.
*
* @public
* @params {String} [quality]
*/
self.setQuality = function (quality) {
if (!player || !player.setPlaybackQuality) {
return;
}
player.setPlaybackQuality(quality);
};
/**
* Start the video.
*
* @public
*/
self.play = function () {
if (!player || !player.playVideo) {
self.on('ready', self.play);
return;
}
player.playVideo();
};
/**
* Pause the video.
*
* @public
*/
self.pause = function () {
self.off('ready', self.play);
if (!player || !player.pauseVideo) {
return;
}
player.pauseVideo();
};
/**
* Seek video to given time.
*
* @public
* @param {Number} time
*/
self.seek = function (time) {
if (!player || !player.seekTo) {
return;
}
player.seekTo(time, true);
};
/**
* Get elapsed time since video beginning.
*
* @public
* @returns {Number}
*/
self.getCurrentTime = function () {
if (!player || !player.getCurrentTime) {
return;
}
return player.getCurrentTime();
};
/**
* Get total video duration time.
*
* @public
* @returns {Number}
*/
self.getDuration = function () {
if (!player || !player.getDuration) {
return;
}
return player.getDuration();
};
/**
* Get percentage of video that is buffered.
*
* @public
* @returns {Number} Between 0 and 100
*/
self.getBuffered = function () {
if (!player || !player.getVideoLoadedFraction) {
return;
}
return player.getVideoLoadedFraction() * 100;
};
/**
* Turn off video sound.
*
* @public
*/
self.mute = function () {
if (!player || !player.mute) {
return;
}
player.mute();
};
/**
* Turn on video sound.
*
* @public
*/
self.unMute = function () {
if (!player || !player.unMute) {
return;
}
player.unMute();
};
/**
* Check if video sound is turned on or off.
*
* @public
* @returns {Boolean}
*/
self.isMuted = function () {
if (!player || !player.isMuted) {
return;
}
return player.isMuted();
};
/**
* Return the video sound level.
*
* @public
* @returns {Number} Between 0 and 100.
*/
self.getVolume = function () {
if (!player || !player.getVolume) {
return;
}
return player.getVolume();
};
/**
* Set video sound level.
*
* @public
* @param {Number} level Between 0 and 100.
*/
self.setVolume = function (level) {
if (!player || !player.setVolume) {
return;
}
player.setVolume(level);
};
/**
* Get list of available playback rates.
*
* @public
* @returns {Array} available playback rates
*/
self.getPlaybackRates = function () {
if (!player || !player.getAvailablePlaybackRates) {
return;
}
var playbackRates = player.getAvailablePlaybackRates();
if (!playbackRates.length) {
return; // No rates, but the array should contain at least 1
}
return playbackRates;
};
/**
* Get current playback rate.
*
* @public
* @returns {Number} such as 0.25, 0.5, 1, 1.25, 1.5 and 2
*/
self.getPlaybackRate = function () {
if (!player || !player.getPlaybackRate) {
return;
}
return player.getPlaybackRate();
};
/**
* Set current playback rate.
* Listen to event "playbackRateChange" to check if successful.
*
* @public
* @params {Number} suggested rate that may be rounded to supported values
*/
self.setPlaybackRate = function (newPlaybackRate) {
if (!player || !player.setPlaybackRate) {
return;
}
playbackRate = Number(newPlaybackRate);
player.setPlaybackRate(playbackRate);
};
/**
* Set current captions track.
*
* @param {H5P.Video.LabelValue} Captions track to show during playback
*/
self.setCaptionsTrack = function (track) {
player.setOption('captions', 'track', track ? {languageCode: track.value} : {});
};
/**
* Figure out which captions track is currently used.
*
* @return {H5P.Video.LabelValue} Captions track
*/
self.getCaptionsTrack = function () {
var track = player.getOption('captions', 'track');
return (track.languageCode ? new H5P.Video.LabelValue(track.displayName, track.languageCode) : null);
};
// Respond to resize events by setting the YT player size.
self.on('resize', function () {
if (!$wrapper.is(':visible')) {
return;
}
if (!player) {
// Player isn't created yet. Try again.
create();
return;
}
// Use as much space as possible
$wrapper.css({
width: '100%',
height: '100%'
});
var width = $wrapper[0].clientWidth;
var height = options.fit ? $wrapper[0].clientHeight : (width * (9/16));
// Validate height before setting
if (height > 0) {
// Set size
$wrapper.css({
width: width + 'px',
height: height + 'px'
});
player.setSize(width, height);
}
});
}
/**
* Check to see if we can play any of the given sources.
*
* @public
* @static
* @param {Array} sources
* @returns {Boolean}
*/
YouTube.canPlay = function (sources) {
return getId(sources[0].path);
};
/**
* Find id of YouTube video from given URL.
*
* @private
* @param {String} url
* @returns {String} YouTube video identifier
*/
var getId = function (url) {
// Has some false positives, but should cover all regular URLs that people can find
var matches = url.match(/(?:(?:youtube.com\/(?:attribution_link\?(?:\S+))?(?:v\/|embed\/|watch\/|(?:user\/(?:\S+)\/)?watch(?:\S+)v\=))|(?:youtu.be\/|y2u.be\/))([A-Za-z0-9_-]{11})/i);
if (matches && matches[1]) {
return matches[1];
}
};
/**
* Load the IFrame Player API asynchronously.
*/
var loadAPI = function (loaded) {
if (window.onYouTubeIframeAPIReady !== undefined) {
// Someone else is loading, hook in
var original = window.onYouTubeIframeAPIReady;
window.onYouTubeIframeAPIReady = function (id) {
loaded(id);
original(id);
};
}
else {
// Load the API our self
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubeIframeAPIReady = loaded;
}
};
/** @constant {Object} */
var LABELS = {
highres: '2160p', // Old API support
hd2160: '2160p', // (New API)
hd1440: '1440p',
hd1080: '1080p',
hd720: '720p',
large: '480p',
medium: '360p',
small: '240p',
tiny: '144p',
auto: 'Auto'
};
/** @private */
var numInstances = 0;
// Extract the current origin (used for security)
var ORIGIN = window.location.href.match(/http[s]?:\/\/[^\/]+/);
ORIGIN = !ORIGIN || ORIGIN[0] === undefined ? undefined : ORIGIN[0];
// ORIGIN = undefined is needed to support fetching file from device local storage
return YouTube;
})(H5P.jQuery);
// Register video handler
H5P.videoHandlers = H5P.videoHandlers || [];
H5P.videoHandlers.push(H5P.VideoYouTube);
;
/** @namespace H5P */
H5P.VideoPanopto = (function ($) {
/**
* Panopto video player for H5P.
*
* @class
* @param {Array} sources Video files to use
* @param {Object} options Settings for the player
* @param {Object} l10n Localization strings
*/
function Panopto(sources, options, l10n) {
var self = this;
var player;
var playbackRate = 1;
var id = 'h5p-panopto-' + numInstances;
numInstances++;
var $wrapper = $('
');
var $placeholder = $('
', {
id: id,
html: '' + l10n.loading + '
'
}).appendTo($wrapper);
/**
* Use the Panopto API to create a new player
*
* @private
*/
var create = function () {
if (!$placeholder.is(':visible') || player !== undefined) {
return;
}
if (window.EmbedApi === undefined) {
// Load API first
loadAPI(create);
return;
}
var width = $wrapper.width();
if (width < 200) {
width = 200;
}
const videoId = getId(sources[0].path);
player = new EmbedApi(id, {
width: width,
height: width * (9/16),
serverName: videoId[0],
sessionId: videoId[1],
videoParams: { // Optional
interactivity: 'none',
showtitle: false,
autohide: true,
offerviewer: false,
autoplay: !!options.autoplay,
showbrand: false,
start: 0,
hideoverlay: !options.controls,
},
events: {
onIframeReady: function () {
$placeholder.children(0).text('');
player.loadVideo();
},
onReady: function () {
self.trigger('loaded');
if (player.hasCaptions()) {
const captions = [];
const captionTracks = player.getCaptionTracks();
for (trackIndex in captionTracks) {
captions.push(new H5P.Video.LabelValue(captionTracks[trackIndex], trackIndex));
}
// Select active track
currentTrack = player.getSelectedCaptionTrack();
currentTrack = captions[currentTrack] ? captions[currentTrack] : null;
self.trigger('captions', captions);
}
self.pause();
},
onStateChange: function (state) {
// TODO: Playback rate fix for IE11?
if (state > -1 && state < 4) {
self.trigger('stateChange', state);
}
},
onPlaybackRateChange: function () {
self.trigger('playbackRateChange', self.getPlaybackRate());
},
onError: function () {
self.trigger('error', l10n.unknownError);
},
onLoginShown: function () {
$placeholder.children().first().remove(); // Remove loading message
self.trigger('loaded'); // Resize parent
}
}
});
};
/**
* Indicates if the video must be clicked for it to start playing.
* This is always true for Panopto since all videos auto play.
*
* @public
*/
self.pressToPlay = true;
/**
* Appends the video player to the DOM.
*
* @public
* @param {jQuery} $container
*/
self.appendTo = function ($container) {
$container.addClass('h5p-panopto').append($wrapper);
create();
};
/**
* Get list of available qualities. Not available until after play.
*
* @public
* @returns {Array}
*/
self.getQualities = function () {
// Not available for Panopto
};
/**
* Get current playback quality. Not available until after play.
*
* @public
* @returns {String}
*/
self.getQuality = function () {
// Not available for Panopto
};
/**
* Set current playback quality. Not available until after play.
* Listen to event "qualityChange" to check if successful.
*
* @public
* @params {String} [quality]
*/
self.setQuality = function (quality) {
// Not available for Panopto
};
/**
* Start the video.
*
* @public
*/
self.play = function () {
if (!player || !player.playVideo) {
return;
}
player.playVideo();
};
/**
* Pause the video.
*
* @public
*/
self.pause = function () {
if (!player || !player.pauseVideo) {
return;
}
try {
player.pauseVideo();
}
catch (err) {
// Swallow Panopto throwing an error. This has been seen in the authoring
// tool if Panopto has been used inside Iv inside CP
}
};
/**
* Seek video to given time.
*
* @public
* @param {Number} time
*/
self.seek = function (time) {
if (!player || !player.seekTo) {
return;
}
player.seekTo(time);
};
/**
* Get elapsed time since video beginning.
*
* @public
* @returns {Number}
*/
self.getCurrentTime = function () {
if (!player || !player.getCurrentTime) {
return;
}
return player.getCurrentTime();
};
/**
* Get total video duration time.
*
* @public
* @returns {Number}
*/
self.getDuration = function () {
if (!player || !player.getDuration) {
return;
}
return player.getDuration();
};
/**
* Get percentage of video that is buffered.
*
* @public
* @returns {Number} Between 0 and 100
*/
self.getBuffered = function () {
// Not available for Panopto
};
/**
* Turn off video sound.
*
* @public
*/
self.mute = function () {
if (!player || !player.muteVideo) {
return;
}
player.muteVideo();
};
/**
* Turn on video sound.
*
* @public
*/
self.unMute = function () {
if (!player || !player.unmuteVideo) {
return;
}
player.unmuteVideo();
};
/**
* Check if video sound is turned on or off.
*
* @public
* @returns {Boolean}
*/
self.isMuted = function () {
if (!player || !player.isMuted) {
return;
}
return player.isMuted();
};
/**
* Return the video sound level.
*
* @public
* @returns {Number} Between 0 and 100.
*/
self.getVolume = function () {
if (!player || !player.getVolume) {
return;
}
return player.getVolume() * 100;
};
/**
* Set video sound level.
*
* @public
* @param {Number} level Between 0 and 100.
*/
self.setVolume = function (level) {
if (!player || !player.setVolume) {
return;
}
player.setVolume(level/100);
};
/**
* Get list of available playback rates.
*
* @public
* @returns {Array} available playback rates
*/
self.getPlaybackRates = function () {
return [0.25, 0.5, 1, 1.25, 1.5, 2];
};
/**
* Get current playback rate.
*
* @public
* @returns {Number} such as 0.25, 0.5, 1, 1.25, 1.5 and 2
*/
self.getPlaybackRate = function () {
if (!player || !player.getPlaybackRate) {
return;
}
return player.getPlaybackRate();
};
/**
* Set current playback rate.
* Listen to event "playbackRateChange" to check if successful.
*
* @public
* @params {Number} suggested rate that may be rounded to supported values
*/
self.setPlaybackRate = function (newPlaybackRate) {
if (!player || !player.setPlaybackRate) {
return;
}
player.setPlaybackRate(newPlaybackRate);
};
/**
* Set current captions track.
*
* @param {H5P.Video.LabelValue} Captions track to show during playback
*/
self.setCaptionsTrack = function (track) {
if (!track) {
console.log('Disable captions');
player.disableCaptions();
currentTrack = null;
}
else {
console.log('Set captions', track.value);
player.enableCaptions(track.value + '');
currentTrack = track;
}
};
/**
* Figure out which captions track is currently used.
*
* @return {H5P.Video.LabelValue} Captions track
*/
self.getCaptionsTrack = function () {
return currentTrack; // No function for getting active caption track?
};
// Respond to resize events by setting the player size.
self.on('resize', function () {
if (!$wrapper.is(':visible')) {
return;
}
if (!player) {
// Player isn't created yet. Try again.
create();
return;
}
// Use as much space as possible
$wrapper.css({
width: '100%',
height: '100%'
});
var width = $wrapper[0].clientWidth;
var height = options.fit ? $wrapper[0].clientHeight : (width * (9/16));
// Set size
$wrapper.css({
width: width + 'px',
height: height + 'px'
});
const $iframe = $placeholder.children('iframe');
if ($iframe.length) {
$iframe.attr('width', width);
$iframe.attr('height', height);
}
});
let currentTrack;
}
/**
* Check to see if we can play any of the given sources.
*
* @public
* @static
* @param {Array} sources
* @returns {Boolean}
*/
Panopto.canPlay = function (sources) {
return getId(sources[0].path);
};
/**
* Find id of YouTube video from given URL.
*
* @private
* @param {String} url
* @returns {String} Panopto video identifier
*/
var getId = function (url) {
const matches = url.match(/^[^\/]+:\/\/([^\/]*panopto\.[^\/]+)\/Panopto\/.+\?id=(.+)$/);
if (matches && matches.length === 3) {
return [matches[1], matches[2]];
}
};
/**
* Load the IFrame Player API asynchronously.
*/
var loadAPI = function (loaded) {
if (window.onPanoptoEmbedApiReady !== undefined) {
// Someone else is loading, hook in
var original = window.onPanoptoEmbedApiReady;
window.onPanoptoEmbedApiReady = function (id) {
loaded(id);
original(id);
};
}
else {
// Load the API our self
var tag = document.createElement('script');
tag.src = 'https://developers.panopto.com/scripts/embedapi.min.js';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onPanoptoEmbedApiReady = loaded;
}
};
/** @private */
var numInstances = 0;
return Panopto;
})(H5P.jQuery);
// Register video handler
H5P.videoHandlers = H5P.videoHandlers || [];
H5P.videoHandlers.push(H5P.VideoPanopto);
;
/** @namespace H5P */
H5P.VideoHtml5 = (function ($) {
/**
* HTML5 video player for H5P.
*
* @class
* @param {Array} sources Video files to use
* @param {Object} options Settings for the player
* @param {Object} l10n Localization strings
*/
function Html5(sources, options, l10n) {
var self = this;
/**
* Small helper to ensure all video sources get the same cache buster.
*
* @private
* @param {Object} source
* @return {string}
*/
const getCrossOriginPath = function (source) {
let path = H5P.getPath(source.path, self.contentId);
if (video.crossOrigin !== null && H5P.addQueryParameter && H5PIntegration.crossoriginCacheBuster) {
path = H5P.addQueryParameter(path, H5PIntegration.crossoriginCacheBuster);
}
return path
};
/**
* Register track to video
*
* @param {Object} trackData Track object
* @param {string} trackData.kind Kind of track
* @param {Object} trackData.track Source path
* @param {string} [trackData.label] Label of track
* @param {string} [trackData.srcLang] Language code
*/
const addTrack = function (trackData) {
// Skip invalid tracks
if (!trackData.kind || !trackData.track.path) {
return;
}
var track = document.createElement('track');
track.kind = trackData.kind;
track.src = getCrossOriginPath(trackData.track); // Uses same crossOrigin as parent. You cannot mix.
if (trackData.label) {
track.label = trackData.label;
}
if (trackData.srcLang) {
track.srcLang = trackData.srcLang;
}
return track;
};
/**
* Small helper to set the inital video source.
* Useful if some of the loading happens asynchronously.
* NOTE: Setting the crossOrigin must happen before any of the
* sources(poster, tracks etc.) are loaded
*
* @private
*/
const setInitialSource = function () {
if (qualities[currentQuality] === undefined) {
return;
}
if (H5P.setSource !== undefined) {
H5P.setSource(video, qualities[currentQuality].source, self.contentId)
}
else {
// Backwards compatibility (H5P < v1.22)
const srcPath = H5P.getPath(qualities[currentQuality].source.path, self.contentId);
if (H5P.getCrossOrigin !== undefined) {
var crossOrigin = H5P.getCrossOrigin(srcPath);
video.setAttribute('crossorigin', crossOrigin !== null ? crossOrigin : 'anonymous');
}
video.src = srcPath;
}
// Add poster if provided
if (options.poster) {
video.poster = getCrossOriginPath(options.poster); // Uses same crossOrigin as parent. You cannot mix.
}
// Register tracks
options.tracks.forEach(function (track, i) {
var trackElement = addTrack(track);
if (i === 0) {
trackElement.default = true;
}
if (trackElement) {
video.appendChild(trackElement);
}
});
};
/**
* Displayed when the video is buffering
* @private
*/
var $throbber = $('
', {
'class': 'h5p-video-loading'
});
/**
* Used to display error messages
* @private
*/
var $error = $('
', {
'class': 'h5p-video-error'
});
/**
* Keep track of current state when changing quality.
* @private
*/
var stateBeforeChangingQuality;
var currentTimeBeforeChangingQuality;
/**
* Avoids firing the same event twice.
* @private
*/
var lastState;
/**
* Keeps track whether or not the video has been loaded.
* @private
*/
var isLoaded = false;
/**
*
* @private
*/
var playbackRate = 1;
var skipRateChange = false;
// Create player
var video = document.createElement('video');
// Sort sources into qualities
var qualities = getQualities(sources, video);
var currentQuality;
numQualities = 0;
for (let quality in qualities) {
numQualities++;
}
if (numQualities > 1 && H5P.VideoHtml5.getExternalQuality !== undefined) {
H5P.VideoHtml5.getExternalQuality(sources, function (chosenQuality) {
if (qualities[chosenQuality] !== undefined) {
currentQuality = chosenQuality;
}
setInitialSource();
});
}
else {
// Select quality and source
currentQuality = getPreferredQuality();
if (currentQuality === undefined || qualities[currentQuality] === undefined) {
// No preferred quality, pick the first.
for (currentQuality in qualities) {
if (qualities.hasOwnProperty(currentQuality)) {
break;
}
}
}
setInitialSource();
}
// Setting webkit-playsinline, which makes iOS 10 beeing able to play video
// inside browser.
video.setAttribute('webkit-playsinline', '');
video.setAttribute('playsinline', '');
video.setAttribute('preload', 'metadata');
// Remove buttons in Chrome's video player:
let controlsList = 'nodownload';
if (options.disableFullscreen) {
controlsList += ' nofullscreen';
}
if (options.disableRemotePlayback) {
controlsList += ' noremoteplayback';
}
video.setAttribute('controlsList', controlsList);
// Remove picture in picture as it interfers with other video players
video.disablePictureInPicture = true;
// Set options
video.disableRemotePlayback = (options.disableRemotePlayback ? true : false);
video.controls = (options.controls ? true : false);
video.autoplay = (options.autoplay ? true : false);
video.loop = (options.loop ? true : false);
video.className = 'h5p-video';
video.style.display = 'block';
if (options.fit) {
// Style is used since attributes with relative sizes aren't supported by IE9.
video.style.width = '100%';
video.style.height = '100%';
}
/**
* Helps registering events.
*
* @private
* @param {String} native Event name
* @param {String} h5p Event name
* @param {String} [arg] Optional argument
*/
var mapEvent = function (native, h5p, arg) {
video.addEventListener(native, function () {
switch (h5p) {
case 'stateChange':
if (lastState === arg) {
return; // Avoid firing event twice.
}
var validStartTime = options.startAt && options.startAt > 0;
if (arg === H5P.Video.PLAYING && validStartTime) {
video.currentTime = options.startAt;
delete options.startAt;
}
break;
case 'loaded':
isLoaded = true;
if (stateBeforeChangingQuality !== undefined) {
return; // Avoid loaded event when changing quality.
}
// Remove any errors
if ($error.is(':visible')) {
$error.remove();
}
if (OLD_ANDROID_FIX) {
var andLoaded = function () {
video.removeEventListener('durationchange', andLoaded, false);
// On Android seeking isn't ready until after play.
self.trigger(h5p);
};
video.addEventListener('durationchange', andLoaded, false);
return;
}
break;
case 'error':
// Handle error and get message.
arg = error(arguments[0], arguments[1]);
break;
case 'playbackRateChange':
// Fix for keeping playback rate in IE11
if (skipRateChange) {
skipRateChange = false;
return; // Avoid firing event when changing back
}
if (H5P.Video.IE11_PLAYBACK_RATE_FIX && playbackRate != video.playbackRate) { // Intentional
// Prevent change in playback rate not triggered by the user
video.playbackRate = playbackRate;
skipRateChange = true;
return;
}
// End IE11 fix
arg = self.getPlaybackRate();
break;
}
self.trigger(h5p, arg);
}, false);
};
/**
* Handle errors from the video player.
*
* @private
* @param {Object} code Error
* @param {String} [message]
* @returns {String} Human readable error message.
*/
var error = function (code, message) {
if (code instanceof Event) {
// No error code
if (!code.target.error) {
return '';
}
switch (code.target.error.code) {
case MediaError.MEDIA_ERR_ABORTED:
message = l10n.aborted;
break;
case MediaError.MEDIA_ERR_NETWORK:
message = l10n.networkFailure;
break;
case MediaError.MEDIA_ERR_DECODE:
message = l10n.cannotDecode;
break;
case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
message = l10n.formatNotSupported;
break;
case MediaError.MEDIA_ERR_ENCRYPTED:
message = l10n.mediaEncrypted;
break;
}
}
if (!message) {
message = l10n.unknownError;
}
// Hide throbber
$throbber.remove();
// Display error message to user
$error.text(message).insertAfter(video);
// Pass message to our error event
return message;
};
/**
* Appends the video player to the DOM.
*
* @public
* @param {jQuery} $container
*/
self.appendTo = function ($container) {
$container.append(video);
};
/**
* Get list of available qualities. Not available until after play.
*
* @public
* @returns {Array}
*/
self.getQualities = function () {
// Create reverse list
var options = [];
for (var q in qualities) {
if (qualities.hasOwnProperty(q)) {
options.splice(0, 0, {
name: q,
label: qualities[q].label
});
}
}
if (options.length < 2) {
// Do not return if only one quality.
return;
}
return options;
};
/**
* Get current playback quality. Not available until after play.
*
* @public
* @returns {String}
*/
self.getQuality = function () {
return currentQuality;
};
/**
* Set current playback quality. Not available until after play.
* Listen to event "qualityChange" to check if successful.
*
* @public
* @params {String} [quality]
*/
self.setQuality = function (quality) {
if (qualities[quality] === undefined || quality === currentQuality) {
return; // Invalid quality
}
// Keep track of last choice
setPreferredQuality(quality);
// Avoid multiple loaded events if changing quality multiple times.
if (!stateBeforeChangingQuality) {
// Keep track of last state
stateBeforeChangingQuality = lastState;
// Keep track of current time
currentTimeBeforeChangingQuality = video.currentTime;
// Seek and start video again after loading.
var loaded = function () {
video.removeEventListener('loadedmetadata', loaded, false);
if (OLD_ANDROID_FIX) {
var andLoaded = function () {
video.removeEventListener('durationchange', andLoaded, false);
// On Android seeking isn't ready until after play.
self.seek(currentTimeBeforeChangingQuality);
};
video.addEventListener('durationchange', andLoaded, false);
}
else {
// Seek to current time.
self.seek(currentTimeBeforeChangingQuality);
}
// Always play to get image.
video.play();
if (stateBeforeChangingQuality !== H5P.Video.PLAYING) {
// Do not resume playing
video.pause();
}
// Done changing quality
stateBeforeChangingQuality = undefined;
// Remove any errors
if ($error.is(':visible')) {
$error.remove();
}
};
video.addEventListener('loadedmetadata', loaded, false);
}
// Keep track of current quality
currentQuality = quality;
self.trigger('qualityChange', currentQuality);
// Display throbber
self.trigger('stateChange', H5P.Video.BUFFERING);
// Change source
video.src = getCrossOriginPath(qualities[quality].source); // (iPad does not support #t=).
// Note: Optional tracks use same crossOrigin as the original. You cannot mix.
// Remove poster so it will not show during quality change
video.removeAttribute('poster');
};
/**
* Starts the video.
*
* @public
* @return {Promise|undefined} May return a Promise that resolves when
* play has been processed.
*/
self.play = function () {
if ($error.is(':visible')) {
return;
}
if (!isLoaded) {
// Make sure video is loaded before playing
video.load();
}
return video.play();
};
/**
* Pauses the video.
*
* @public
*/
self.pause = function () {
video.pause();
};
/**
* Seek video to given time.
*
* @public
* @param {Number} time
*/
self.seek = function (time) {
if (lastState === undefined) {
// Make sure we always play before we seek to get an image.
// If not iOS devices will reset currentTime when pressing play.
video.play();
video.pause();
}
video.currentTime = time;
};
/**
* Get elapsed time since video beginning.
*
* @public
* @returns {Number}
*/
self.getCurrentTime = function () {
return video.currentTime;
};
/**
* Get total video duration time.
*
* @public
* @returns {Number}
*/
self.getDuration = function () {
if (isNaN(video.duration)) {
return;
}
return video.duration;
};
/**
* Get percentage of video that is buffered.
*
* @public
* @returns {Number} Between 0 and 100
*/
self.getBuffered = function () {
// Find buffer currently playing from
var buffered = 0;
for (var i = 0; i < video.buffered.length; i++) {
var from = video.buffered.start(i);
var to = video.buffered.end(i);
if (video.currentTime > from && video.currentTime < to) {
buffered = to;
break;
}
}
// To percentage
return buffered ? (buffered / video.duration) * 100 : 0;
};
/**
* Turn off video sound.
*
* @public
*/
self.mute = function () {
video.muted = true;
};
/**
* Turn on video sound.
*
* @public
*/
self.unMute = function () {
video.muted = false;
};
/**
* Check if video sound is turned on or off.
*
* @public
* @returns {Boolean}
*/
self.isMuted = function () {
return video.muted;
};
/**
* Returns the video sound level.
*
* @public
* @returns {Number} Between 0 and 100.
*/
self.getVolume = function () {
return video.volume * 100;
};
/**
* Set video sound level.
*
* @public
* @param {Number} level Between 0 and 100.
*/
self.setVolume = function (level) {
video.volume = level / 100;
};
/**
* Get list of available playback rates.
*
* @public
* @returns {Array} available playback rates
*/
self.getPlaybackRates = function () {
/*
* not sure if there's a common rule about determining good speeds
* using Google's standard options via a constant for setting
*/
var playbackRates = PLAYBACK_RATES;
return playbackRates;
};
/**
* Get current playback rate.
*
* @public
* @returns {Number} such as 0.25, 0.5, 1, 1.25, 1.5 and 2
*/
self.getPlaybackRate = function () {
return video.playbackRate;
};
/**
* Set current playback rate.
* Listen to event "playbackRateChange" to check if successful.
*
* @public
* @params {Number} suggested rate that may be rounded to supported values
*/
self.setPlaybackRate = function (newPlaybackRate) {
playbackRate = newPlaybackRate;
video.playbackRate = newPlaybackRate;
};
/**
* Set current captions track.
*
* @param {H5P.Video.LabelValue} Captions track to show during playback
*/
self.setCaptionsTrack = function (track) {
for (var i = 0; i < video.textTracks.length; i++) {
video.textTracks[i].mode = (track && track.value === i ? 'showing' : 'disabled');
}
};
/**
* Figure out which captions track is currently used.
*
* @return {H5P.Video.LabelValue} Captions track
*/
self.getCaptionsTrack = function () {
for (var i = 0; i < video.textTracks.length; i++) {
if (video.textTracks[i].mode === 'showing') {
return new H5P.Video.LabelValue(video.textTracks[i].label, i);
}
}
return null;
};
// Register event listeners
mapEvent('ended', 'stateChange', H5P.Video.ENDED);
mapEvent('playing', 'stateChange', H5P.Video.PLAYING);
mapEvent('pause', 'stateChange', H5P.Video.PAUSED);
mapEvent('waiting', 'stateChange', H5P.Video.BUFFERING);
mapEvent('loadedmetadata', 'loaded');
mapEvent('canplay', 'canplay');
mapEvent('error', 'error');
mapEvent('ratechange', 'playbackRateChange');
if (!video.controls) {
// Disable context menu(right click) to prevent controls.
video.addEventListener('contextmenu', function (event) {
event.preventDefault();
}, false);
}
// Display throbber when buffering/loading video.
self.on('stateChange', function (event) {
var state = event.data;
lastState = state;
if (state === H5P.Video.BUFFERING) {
$throbber.insertAfter(video);
}
else {
$throbber.remove();
}
});
// Load captions after the video is loaded
self.on('loaded', function () {
nextTick(function () {
var textTracks = [];
for (var i = 0; i < video.textTracks.length; i++) {
textTracks.push(new H5P.Video.LabelValue(video.textTracks[i].label, i));
}
if (textTracks.length) {
self.trigger('captions', textTracks);
}
});
});
// Alternative to 'canplay' event
/*self.on('resize', function () {
if (video.offsetParent === null) {
return;
}
video.style.width = '100%';
video.style.height = '100%';
var width = video.clientWidth;
var height = options.fit ? video.clientHeight : (width * (video.videoHeight / video.videoWidth));
video.style.width = width + 'px';
video.style.height = height + 'px';
});*/
// Video controls are ready
nextTick(function () {
self.trigger('ready');
});
}
/**
* Check to see if we can play any of the given sources.
*
* @public
* @static
* @param {Array} sources
* @returns {Boolean}
*/
Html5.canPlay = function (sources) {
var video = document.createElement('video');
if (video.canPlayType === undefined) {
return false; // Not supported
}
// Cycle through sources
for (var i = 0; i < sources.length; i++) {
var type = getType(sources[i]);
if (type && video.canPlayType(type) !== '') {
// We should be able to play this
return true;
}
}
return false;
};
/**
* Find source type.
*
* @private
* @param {Object} source
* @returns {String}
*/
var getType = function (source) {
var type = source.mime;
if (!type) {
// Try to get type from URL
var matches = source.path.match(/\.(\w+)$/);
if (matches && matches[1]) {
type = 'video/' + matches[1];
}
}
if (type && source.codecs) {
// Add codecs
type += '; codecs="' + source.codecs + '"';
}
return type;
};
/**
* Sort sources into qualities.
*
* @private
* @static
* @param {Array} sources
* @param {Object} video
* @returns {Object} Quality mapping
*/
var getQualities = function (sources, video) {
var qualities = {};
var qualityIndex = 1;
var lastQuality;
// Cycle through sources
for (var i = 0; i < sources.length; i++) {
var source = sources[i];
// Find and update type.
var type = source.type = getType(source);
// Check if we support this type
var isPlayable = type && (type === 'video/unknown' || video.canPlayType(type) !== '');
if (!isPlayable) {
continue; // We cannot play this source
}
if (source.quality === undefined) {
/**
* No quality metadata. Create a quality tag to separate multiple sources of the same type,
* e.g. if two mp4 files with different quality has been uploaded
*/
if (lastQuality === undefined || qualities[lastQuality].source.type === type) {
// Create a new quality tag
source.quality = {
name: 'q' + qualityIndex,
label: (source.metadata && source.metadata.qualityName) ? source.metadata.qualityName : 'Quality ' + qualityIndex // TODO: l10n
};
qualityIndex++;
}
else {
/**
* Assumes quality already exists in a different format.
* Uses existing label for this quality.
*/
source.quality = qualities[lastQuality].source.quality;
}
}
// Log last quality
lastQuality = source.quality.name;
// Look to see if quality exists
var quality = qualities[lastQuality];
if (quality) {
// We have a source with this quality. Check if we have a better format.
if (source.mime.split('/')[1] === PREFERRED_FORMAT) {
quality.source = source;
}
}
else {
// Add new source with quality.
qualities[source.quality.name] = {
label: source.quality.label,
source: source
};
}
}
return qualities;
};
/**
* Set preferred video quality.
*
* @private
* @static
* @param {String} quality Index of preferred quality
*/
var setPreferredQuality = function (quality) {
try {
localStorage.setItem('h5pVideoQuality', quality);
}
catch (err) {
console.warn('Unable to set preferred video quality, localStorage is not available.');
}
};
/**
* Get preferred video quality.
*
* @private
* @static
* @returns {String} Index of preferred quality
*/
var getPreferredQuality = function () {
// First check localStorage
let quality;
try {
quality = localStorage.getItem('h5pVideoQuality');
}
catch (err) {
console.warn('Unable to retrieve preferred video quality from localStorage.');
}
if (!quality) {
try {
// The fallback to old cookie solution
var settings = document.cookie.split(';');
for (var i = 0; i < settings.length; i++) {
var setting = settings[i].split('=');
if (setting[0] === 'H5PVideoQuality') {
quality = setting[1];
break;
}
}
}
catch (err) {
console.warn('Unable to retrieve preferred video quality from cookie.');
}
}
return quality;
};
/**
* Helps schedule a task for the next tick.
* @param {function} task
*/
var nextTick = function (task) {
setTimeout(task, 0);
};
/** @constant {Boolean} */
var OLD_ANDROID_FIX = false;
/** @constant {Boolean} */
var PREFERRED_FORMAT = 'mp4';
/** @constant {Object} */
var PLAYBACK_RATES = [0.25, 0.5, 1, 1.25, 1.5, 2];
if (navigator.userAgent.indexOf('Android') !== -1) {
// We have Android, check version.
var version = navigator.userAgent.match(/AppleWebKit\/(\d+\.?\d*)/);
if (version && version[1] && Number(version[1]) <= 534.30) {
// Include fix for devices running the native Android browser.
// (We don't know when video was fixed, so the number is just the lastest
// native android browser we found.)
OLD_ANDROID_FIX = true;
}
}
else {
if (navigator.userAgent.indexOf('Chrome') !== -1) {
// If we're using chrome on a device that isn't Android, prefer the webm
// format. This is because Chrome has trouble with some mp4 codecs.
PREFERRED_FORMAT = 'webm';
}
}
return Html5;
})(H5P.jQuery);
// Register video handler
H5P.videoHandlers = H5P.videoHandlers || [];
H5P.videoHandlers.push(H5P.VideoHtml5);
;
/** @namespace H5P */
H5P.VideoFlash = (function ($) {
/**
* Flash video player for H5P.
*
* @class
* @param {Array} sources Video files to use
* @param {Object} options Settings for the player
*/
function Flash(sources, options) {
var self = this;
// Player wrapper
var $wrapper = $('
', {
'class': 'h5p-video-flash',
css: {
width: '100%',
height: '100%'
}
});
/**
* Used to display error messages
* @private
*/
var $error = $('
', {
'class': 'h5p-video-error'
});
/**
* Keep track of current state when changing quality.
* @private
*/
var stateBeforeChangingQuality;
var currentTimeBeforeChangingQuality;
// Sort sources into qualities
//var qualities = getQualities(sources);
var currentQuality;
// Create player options
var playerOptions = {
buffering: true,
clip: {
url: sources[0].path, // getPreferredQuality(),
autoPlay: options.autoplay,
autoBuffering: true,
scaling: 'fit',
onSeek: function () {
if (stateBeforeChangingQuality) {
// ????
}
},
onMetaData: function () {
setTimeout(function () {
if (stateBeforeChangingQuality !== undefined) {
fp.seek(currentTimeBeforeChangingQuality);
if (stateBeforeChangingQuality === H5P.Video.PLAYING) {
// Resume play
fp.play();
}
// Done changing quality
stateBeforeChangingQuality = undefined;
// Remove any errors
if ($error.is(':visible')) {
$error.remove();
}
}
else {
self.trigger('ready');
self.trigger('loaded');
}
}, 0); // Run on next tick
},
onBegin: function () {
self.trigger('stateChange', H5P.Video.PLAYING);
},
onResume: function () {
self.trigger('stateChange', H5P.Video.PLAYING);
},
onPause: function () {
self.trigger('stateChange', H5P.Video.PAUSED);
},
onFinish: function () {
self.trigger('stateChange', H5P.Video.ENDED);
},
onError: function (code, message) {
console.log('ERROR', code, message); // TODO
self.trigger('error', message);
}
},
plugins: {
controls: null
},
play: null, // Disable overlay controls
onPlaylistReplace: function () {
that.playlistReplaced();
}
};
if (options.controls) {
playerOptions.plugins.controls = {};
delete playerOptions.play;
}
var fp = flowplayer($wrapper[0], {
src: "http://releases.flowplayer.org/swf/flowplayer-3.2.16.swf",
wmode: "opaque"
}, playerOptions);
/**
* Appends the video player to the DOM.
*
* @public
* @param {jQuery} $container
*/
self.appendTo = function ($container) {
$wrapper.appendTo($container);
};
/**
* Get list of available qualities. Not available until after play.
*
* @public
* @returns {Array}
*/
self.getQualities = function () {
return;
};
/**
* Get current playback quality. Not available until after play.
*
* @public
* @returns {String}
*/
self.getQuality = function () {
return currentQuality;
};
/**
* Set current playback quality. Not available until after play.
* Listen to event "qualityChange" to check if successful.
*
* @public
* @params {String} [quality]
*/
self.setQuality = function (quality) {
if (qualities[quality] === undefined || quality === currentQuality) {
return; // Invalid quality
}
// Keep track of last choice
setPreferredQuality(quality);
// Avoid multiple loaded events if changing quality multiple times.
if (!stateBeforeChangingQuality) {
// Keep track of last state
stateBeforeChangingQuality = lastState;
// Keep track of current time
currentTimeBeforeChangingQuality = video.currentTime;
}
// Keep track of current quality
currentQuality = quality;
self.trigger('qualityChange', currentQuality);
// Display throbber
self.trigger('stateChange', H5P.Video.BUFFERING);
// Change source
fp.setClip(qualities[quality].source.path);
fp.startBuffering();
};
/**
* Starts the video.
*
* @public
*/
self.play = function () {
if ($error.is(':visible')) {
return;
}
fp.play();
};
/**
* Pauses the video.
*
* @public
*/
self.pause = function () {
fp.pause();
};
/**
* Seek video to given time.
*
* @public
* @param {Number} time
*/
self.seek = function (time) {
fp.seek(time);
};
/**
* Get elapsed time since video beginning.
*
* @public
* @returns {Number}
*/
self.getCurrentTime = function () {
return fp.getTime();
};
/**
* Get total video duration time.
*
* @public
* @returns {Number}
*/
self.getDuration = function () {
return fp.getClip().metaData.duration;
};
/**
* Get percentage of video that is buffered.
*
* @public
* @returns {Number} Between 0 and 100
*/
self.getBuffered = function () {
return fp.getClip().buffer;
};
/**
* Turn off video sound.
*
* @public
*/
self.mute = function () {
fp.mute();
};
/**
* Turn on video sound.
*
* @public
*/
self.unMute = function () {
fp.unmute();
};
/**
* Check if video sound is turned on or off.
*
* @public
* @returns {Boolean}
*/
self.isMuted = function () {
return fp.muted;
};
/**
* Returns the video sound level.
*
* @public
* @returns {Number} Between 0 and 100.
*/
self.getVolume = function () {
return fp.volumeLevel * 100;
};
/**
* Set video sound level.
*
* @public
* @param {Number} volume Between 0 and 100.
*/
self.setVolume = function (level) {
fp.volume(level / 100);
};
// Handle resize events
self.on('resize', function () {
var $object = H5P.jQuery(fp.getParent()).children('object');
var clip = fp.getClip();
if (clip !== undefined) {
$object.css('height', $object.width() * (clip.metaData.height / clip.metaData.width));
}
});
}
/**
* Check to see if we can play any of the given sources.
*
* @public
* @static
* @param {Array} sources
* @returns {Boolean}
*/
Flash.canPlay = function (sources) {
// Cycle through sources
for (var i = 0; i < sources.length; i++) {
if (sources[i].mime === 'video/mp4' || /\.mp4$/.test(sources[i].mime)) {
return true; // We only play mp4
}
}
};
return Flash;
})(H5P.jQuery);
// Register video handler
H5P.videoHandlers = H5P.videoHandlers || [];
H5P.videoHandlers.push(H5P.VideoFlash);
;
/** @namespace H5P */
H5P.Video = (function ($, ContentCopyrights, MediaCopyright, handlers) {
/**
* The ultimate H5P video player!
*
* @class
* @param {Object} parameters Options for this library.
* @param {Object} parameters.visuals Visual options
* @param {Object} parameters.playback Playback options
* @param {Object} parameters.a11y Accessibility options
* @param {Boolean} [parameters.startAt] Start time of video
* @param {Number} id Content identifier
*/
function Video(parameters, id) {
var self = this;
self.contentId = id;
// Ref youtube.js - ipad & youtube - issue
self.pressToPlay = false;
// Reference to the handler
var handlerName = '';
// Initialize event inheritance
H5P.EventDispatcher.call(self);
// Default language localization
parameters = $.extend(true, parameters, {
l10n: {
name: 'Video',
loading: 'Video player loading...',
noPlayers: 'Found no video players that supports the given video format.',
noSources: 'Video source is missing.',
aborted: 'Media playback has been aborted.',
networkFailure: 'Network failure.',
cannotDecode: 'Unable to decode media.',
formatNotSupported: 'Video format not supported.',
mediaEncrypted: 'Media encrypted.',
unknownError: 'Unknown error.',
invalidYtId: 'Invalid YouTube ID.',
unknownYtId: 'Unable to find video with the given YouTube ID.',
restrictedYt: 'The owner of this video does not allow it to be embedded.'
}
});
parameters.a11y = parameters.a11y || [];
parameters.playback = parameters.playback || {};
parameters.visuals = $.extend(true, parameters.visuals, {
disableFullscreen: false
});
/** @private */
var sources = [];
if (parameters.sources) {
for (var i = 0; i < parameters.sources.length; i++) {
// Clone to avoid changing of parameters.
var source = $.extend(true, {}, parameters.sources[i]);
// Create working URL without html entities.
source.path = $cleaner.html(source.path).text();
sources.push(source);
}
}
/** @private */
var tracks = [];
parameters.a11y.forEach(function (track) {
// Clone to avoid changing of parameters.
var clone = $.extend(true, {}, track);
// Create working URL without html entities
if (clone.track && clone.track.path) {
clone.track.path = $cleaner.html(clone.track.path).text();
tracks.push(clone);
}
});
/**
* Attaches the video handler to the given container.
* Inserts text if no handler is found.
*
* @public
* @param {jQuery} $container
*/
self.attach = function ($container) {
$container.addClass('h5p-video').html('');
if (self.appendTo !== undefined) {
self.appendTo($container);
}
else {
if (sources.length) {
$container.text(parameters.l10n.noPlayers);
}
else {
$container.text(parameters.l10n.noSources);
}
}
};
/**
* Get name of the video handler
*
* @public
* @returns {string}
*/
self.getHandlerName = function() {
return handlerName;
};
// Resize the video when we know its aspect ratio
self.on('loaded', function () {
self.trigger('resize');
});
// Find player for video sources
if (sources.length) {
const options = {
controls: parameters.visuals.controls,
autoplay: parameters.playback.autoplay,
loop: parameters.playback.loop,
fit: parameters.visuals.fit,
poster: parameters.visuals.poster === undefined ? undefined : parameters.visuals.poster,
startAt: parameters.startAt || 0,
tracks: tracks,
disableRemotePlayback: parameters.visuals.disableRemotePlayback === true,
disableFullscreen: parameters.visuals.disableFullscreen === true
}
var html5Handler;
for (var i = 0; i < handlers.length; i++) {
var handler = handlers[i];
if (handler.canPlay !== undefined && handler.canPlay(sources)) {
handler.call(self, sources, options, parameters.l10n);
handlerName = handler.name;
return;
}
if (handler === H5P.VideoHtml5) {
html5Handler = handler;
handlerName = handler.name;
}
}
// Fallback to trying HTML5 player
if (html5Handler) {
html5Handler.call(self, sources, options, parameters.l10n);
}
}
}
// Extends the event dispatcher
Video.prototype = Object.create(H5P.EventDispatcher.prototype);
Video.prototype.constructor = Video;
// Player states
/** @constant {Number} */
Video.ENDED = 0;
/** @constant {Number} */
Video.PLAYING = 1;
/** @constant {Number} */
Video.PAUSED = 2;
/** @constant {Number} */
Video.BUFFERING = 3;
/**
* When video is queued to start
* @constant {Number}
*/
Video.VIDEO_CUED = 5;
// Used to convert between html and text, since URLs have html entities.
var $cleaner = H5P.jQuery('
');
/**
* Help keep track of key value pairs used by the UI.
*
* @class
* @param {string} label
* @param {string} value
*/
Video.LabelValue = function (label, value) {
this.label = label;
this.value = value;
};
/** @constant {Boolean} */
Video.IE11_PLAYBACK_RATE_FIX = (navigator.userAgent.match(/Trident.*rv[ :]*11\./) ? true : false);
return Video;
})(H5P.jQuery, H5P.ContentCopyrights, H5P.MediaCopyright, H5P.videoHandlers || []);
;
!function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,i){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:i})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=6)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.jQuery=H5P.jQuery,t.EventDispatcher=H5P.EventDispatcher,t.JoubelUI=H5P.JoubelUI},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.stripHTML=t.addClickAndKeyboardListeners=t.keyCode=t.defaultValue=t.contains=t.isIOS=t.isIPad=t.kebabCase=t.isFunction=t.flattenArray=void 0;var i=n(0),r=(t.flattenArray=function(e){return e.concat.apply([],e)},t.isFunction=function(e){return"function"==typeof e},t.kebabCase=function(e){return e.replace(/[\W]/g,"-")},t.isIPad=null!==navigator.userAgent.match(/iPad/i),t.isIOS=null!==navigator.userAgent.match(/iPad|iPod|iPhone/i),t.contains=function(e,t){return-1!==e.indexOf(t)}),s=(t.defaultValue=function(e,t){return void 0!==e?e:t},t.keyCode={ENTER:13,ESC:27,SPACE:32}),o=(t.addClickAndKeyboardListeners=function(e,t,n){e.click(function(e){t.call(n||this,e)}),e.keydown(function(e){r([s.ENTER,s.SPACE],e.which)&&(e.preventDefault(),t.call(n||this,e))})},(0,i.jQuery)(""));t.stripHTML=function(e){return o.html(e).text().trim()}},function(e,t,n){"use strict";function i(e,t){var n=this;s.call(n),n.children=[];var i=function(e){for(var t=e;t
=t?e.apply(null,i):function(){var e=Array.prototype.slice.call(arguments,0);return n.apply(null,i.concat(e))}}},r=(t.compose=function(){for(var e=arguments.length,t=Array(e),n=0;n
';e.attr("role","application").addClass("h5p-course-presentation").html(i),this.$container=e,this.$slideAnnouncer=e.find(".h5p-current-slide-announcer"),this.$fullscreenAnnouncer=e.find(".h5p-fullscreen-announcer"),this.$slideTop=this.$slideAnnouncer.next(),this.$wrapper=e.children(".h5p-wrapper").focus(function(){n.initKeyEvents()}).blur(function(){void 0!==n.keydown&&(H5P.jQuery("body").unbind("keydown",n.keydown),delete n.keydown)}).click(function(e){var t=H5P.jQuery(e.target),i=n.belongsToTagName(e.target,["input","textarea","a","button"],e.currentTarget),r=-1!==e.target.tabIndex,s=t.closest(".h5p-popup-container"),o=0!==s.length;if(!i&&!r&&!n.editor)if(o){var a=t.closest("[tabindex]");1===a.closest(".h5p-popup-container").length?a.focus():s.find(".h5p-close-popup").focus()}else n.$wrapper.focus();n.presentation.keywordListEnabled&&!n.presentation.keywordListAlwaysShow&&n.presentation.keywordListAutoHide&&!t.is("textarea, .h5p-icon-pencil, span")&&n.hideKeywords()}),this.on("exitFullScreen",function(){t.$footer.removeClass("footer-full-screen"),t.$fullScreenButton.attr("title",t.l10n.fullscreen),t.$fullscreenAnnouncer.html(t.l10n.accessibilityExitedFullscreen)}),this.on("enterFullScreen",function(){t.$fullscreenAnnouncer.html(t.l10n.accessibilityEnteredFullscreen)});var r=parseInt(this.$wrapper.css("width"));this.width=0!==r?r:640;var s=parseInt(this.$wrapper.css("height"));this.height=0!==s?s:400,this.ratio=16/9,this.fontSize=16,this.$boxWrapper=this.$wrapper.children(".h5p-box-wrapper");var o=this.$boxWrapper.children(".h5p-presentation-wrapper");this.$slidesWrapper=o.children(".h5p-slides-wrapper"),this.$keywordsWrapper=o.children(".h5p-keywords-wrapper"),this.$progressbar=this.$wrapper.find(".h5p-progressbar"),this.$footer=this.$wrapper.children(".h5p-footer"),this.initKeywords=void 0===this.presentation.keywordListEnabled||!0===this.presentation.keywordListEnabled||void 0!==this.editor,this.activeSurface&&void 0===this.editor&&(this.initKeywords=!1,this.$boxWrapper.css("height","100%")),this.isSolutionMode=!1,this.createSlides(),this.elementsAttached[this.currentSlideIndex]=!0;var a;if(this.showSummarySlide=!1,this.hideSummarySlide?this.showSummarySlide=!this.hideSummarySlide:this.slidesWithSolutions.forEach(function(e){n.showSummarySlide=e.length}),void 0===this.editor&&(this.showSummarySlide||this.hasAnswerElements)){var l={elements:[],keywords:[]};this.slides.push(l),a=H5P.jQuery(g.default.createHTML(l)).appendTo(this.$slidesWrapper),a.addClass("h5p-summary-slide"),this.isCurrentSlide(this.slides.length-1)&&(this.$current=a)}var c=this.getKeywordMenuConfig();c.length>0||this.isEditor()?(this.keywordMenu.init(c),this.keywordMenu.on("select",function(e){return t.keywordClick(e.data.index)}),this.keywordMenu.on("close",function(){return t.hideKeywords()}),this.keywordMenu.on("select",function(){t.$currentKeyword=t.$keywords.children(".h5p-current")}),this.$keywords=(0,m.jQuery)(this.keywordMenu.getElement()).appendTo(this.$keywordsWrapper),this.$currentKeyword=this.$keywords.children(".h5p-current"),this.setKeywordsOpacity(void 0===this.presentation.keywordListOpacity?90:this.presentation.keywordListOpacity),this.presentation.keywordListAlwaysShow&&this.showKeywords()):(this.$keywordsWrapper.remove(),this.initKeywords=!1),void 0===this.editor&&this.activeSurface?(this.$progressbar.add(this.$footer).remove(),H5P.fullscreenSupported&&(this.$fullScreenButton=H5P.jQuery("
",{class:"h5p-toggle-full-screen",title:this.l10n.fullscreen,role:"button",tabindex:0,appendTo:this.$wrapper}),(0,y.addClickAndKeyboardListeners)(this.$fullScreenButton,function(){return n.toggleFullScreen()}))):(this.initTouchEvents(),this.navigationLine=new u.default(this),this.previousState&&this.previousState.progress||this.setSlideNumberAnnouncer(0,!1),this.summarySlideObject=new d.default(this,a)),new h.default(this),this.previousState&&this.previousState.progress&&this.jumpToSlide(this.previousState.progress)},S.prototype.belongsToTagName=function(e,t,n){if(!e)return!1;n=n||document.body,"string"==typeof t&&(t=[t]),t=t.map(function(e){return e.toLowerCase()});var i=e.tagName.toLowerCase();return-1!==t.indexOf(i)||n!==e&&this.belongsToTagName(e.parentNode,t,n)},S.prototype.updateKeywordMenuFromSlides=function(){this.keywordMenu.removeAllMenuItemElements();var e=this.getKeywordMenuConfig();return(0,m.jQuery)(this.keywordMenu.init(e))},S.prototype.getKeywordMenuConfig=function(){var e=this;return this.slides.map(function(t,n){return{title:e.createSlideTitle(t),subtitle:e.l10n.slide+" "+(n+1),index:n}}).filter(function(e){return null!==e.title})},S.prototype.createSlideTitle=function(e){var t=this.isEditor()?this.l10n.noTitle:null;return this.hasKeywords(e)?e.keywords[0].main:t},S.prototype.isEditor=function(){return void 0!==this.editor},S.prototype.hasKeywords=function(e){return void 0!==e.keywords&&e.keywords.length>0},S.prototype.createSlides=function(){for(var e=this,t=0;t=e.maxScore;n.addClass(i?"h5p-is-correct":"h5p-is-wrong"),t.navigationLine.updateSlideTitle(e.slide-1)}}):this.progressbarParts.forEach(function(e){e.find(".h5p-progressbar-part-has-task").removeClass("h5p-is-correct").removeClass("h5p-is-wrong")})},S.prototype.toggleKeywords=function(){this[this.$keywordsWrapper.hasClass("h5p-open")?"hideKeywords":"showKeywords"]()},S.prototype.hideKeywords=function(){this.$keywordsWrapper.hasClass("h5p-open")&&(void 0!==this.$keywordsButton&&(this.$keywordsButton.attr("title",this.l10n.showKeywords),this.$keywordsButton.attr("aria-label",this.l10n.showKeywords),this.$keywordsButton.attr("aria-expanded","false"),this.$keywordsButton.focus()),this.$keywordsWrapper.removeClass("h5p-open"))},S.prototype.showKeywords=function(){this.$keywordsWrapper.hasClass("h5p-open")||(void 0!==this.$keywordsButton&&(this.$keywordsButton.attr("title",this.l10n.hideKeywords),this.$keywordsButton.attr("aria-label",this.l10n.hideKeywords),this.$keywordsButton.attr("aria-expanded","true")),this.$keywordsWrapper.addClass("h5p-open"),this.presentation.keywordListAlwaysShow||this.$keywordsWrapper.find('li[tabindex="0"]').focus())},S.prototype.setKeywordsOpacity=function(e){var t=this.$keywordsWrapper.css("background-color").split(/\(|\)|,/g),n=r(t,3),i=n[0],s=n[1],o=n[2];this.$keywordsWrapper.css("background-color","rgba("+i+", "+s+", "+o+", "+e/100+")")},S.prototype.fitCT=function(){void 0===this.editor&&this.$current.find(".h5p-ct").each(function(){for(var e=100,t=H5P.jQuery(this),n=t.parent().height();t.outerHeight()>n&&(e--,t.css({fontSize:e+"%",lineHeight:e+65+"%"}),!(e<0)););})},S.prototype.resize=function(){var e=this.$container.hasClass("h5p-fullscreen")||this.$container.hasClass("h5p-semi-fullscreen");if(!this.ignoreResize){this.$wrapper.css("width","auto");var t=this.$container.width(),n={};if(e){var i=this.$container.height();t/i>this.ratio&&(t=i*this.ratio,n.width=t+"px")}var r=t/this.width;n.height=t/this.ratio+"px",n.fontSize=this.fontSize*r+"px",void 0!==this.editor&&this.editor.setContainerEm(this.fontSize*r*.75),this.$wrapper.css(n),this.swipeThreshold=100*r;var s=this.elementInstances[this.$current.index()];if(void 0!==s)for(var o=this.slides[this.$current.index()].elements,a=0;a",{class:o}).css({left:e.x+"%",top:e.y+"%",width:e.width+"%",height:e.height+"%"}).appendTo(n),l=void 0===e.backgroundOpacity||0===e.backgroundOpacity;if(a.toggleClass("h5p-transparent",l),r){this.createInteractionButton(e,t).appendTo(a)}else{var d=e.action&&e.action.library,c=d?this.getLibraryTypePmz(e.action.library):"other",u=H5P.jQuery("",{class:"h5p-element-outer "+c+"-outer-element"}).css({background:"rgba(255,255,255,"+(void 0===e.backgroundOpacity?0:e.backgroundOpacity/100)+")"}).appendTo(a),p=H5P.jQuery("
",{class:"h5p-element-inner"}).appendTo(u);if(t.on("set-size",function(e){for(var t in e.data)a.get(0).style[t]=e.data[t]}),t.attach(p),void 0!==e.action&&"H5P.InteractiveVideo"===e.action.library.substr(0,20)){var h=function(){t.$container.addClass("h5p-fullscreen"),t.controls.$fullscreen&&t.controls.$fullscreen.remove(),t.hasFullScreen=!0,t.controls.$play.hasClass("h5p-pause")?t.$controls.addClass("h5p-autohide"):t.enableAutoHide()};void 0!==t.controls?h():t.on("controls",h)}0==i&&this.slidesWithSolutions.indexOf(i)<0&&p.attr("tabindex","0"),this.setOverflowTabIndex()}return void 0!==this.editor?this.editor.processElement(e,a,i,t):(e.solution&&this.addElementSolutionButton(e,t,a),this.hasAnswerElements=this.hasAnswerElements||void 0!==t.exportAnswers),a},S.prototype.disableTabIndexes=function(){var e=this.$container.find(".h5p-popup-container");this.$tabbables=this.$container.find("a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]").filter(function(){var t=(0,m.jQuery)(this),n=m.jQuery.contains(e.get(0),t.get(0));if(t.data("tabindex"))return!0;if(!n){var i=t.attr("tabindex");return t.data("tabindex",i),t.attr("tabindex","-1"),!0}return!1})},S.prototype.restoreTabIndexes=function(){this.$tabbables&&this.$tabbables.each(function(){var e=(0,m.jQuery)(this),t=e.data("tabindex");e.hasClass("ui-slider-handle")?(e.attr("tabindex",0),e.removeData("tabindex")):void 0!==t?(e.attr("tabindex",t),e.removeData("tabindex")):e.removeAttr("tabindex")})},S.prototype.createInteractionButton=function(e,t){var n=this,i=e.action.params&&e.action.params.cpAutoplay,r=e.action.metadata?e.action.metadata.title:"";""===r&&(r=e.action.params&&e.action.params.contentName||e.action.library.split(" ")[0].split(".")[1]);var s=this.getLibraryTypePmz(e.action.library),o=function(e){return function(){return e.attr("aria-expanded","false")}},a=(0,m.jQuery)("
",{role:"button",tabindex:0,"aria-label":r,"aria-popup":!0,"aria-expanded":!1,class:"h5p-element-button h5p-element-button-"+e.buttonSize+" "+s+"-button"}),l=(0,m.jQuery)('
');t.attach(l);var d="h5p-advancedtext"===s?{x:e.x,y:e.y}:null;return(0,y.addClickAndKeyboardListeners)(a,function(){a.attr("aria-expanded","true"),n.showInteractionPopup(t,a,l,s,i,o(a),d),n.disableTabIndexes()}),void 0!==e.action&&"H5P.InteractiveVideo"===e.action.library.substr(0,20)&&t.on("controls",function(){t.controls.$fullscreen&&t.controls.$fullscreen.remove()}),a},S.prototype.showInteractionPopup=function(e,t,n,i,r,s){var o=this,a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,l=function(){e.trigger("resize")};if(!this.isEditor()){this.on("exitFullScreen",l),this.showPopup(n,t,a,function(){o.pauseMedia(e),n.detach(),o.off("exitFullScreen",l),s()},i),H5P.trigger(e,"resize"),"h5p-image"===i&&this.resizePopupImage(n);n.closest(".h5p-popup-container");setTimeout(function(){var e=n.find(":input").add(n.find("[tabindex]"));e.length?e[0].focus():(n.attr("tabindex",0),n.focus())},200),(0,y.isFunction)(e.setActivityStarted)&&(0,y.isFunction)(e.getScore)&&e.setActivityStarted(),r&&(0,y.isFunction)(e.play)&&e.play()}},S.prototype.getLibraryTypePmz=function(e){return(0,y.kebabCase)(e.split(" ")[0]).toLowerCase()},S.prototype.resizePopupImage=function(e){var t=Number(e.css("fontSize").replace("px","")),n=e.find("img"),i=function(n,i){if(!(i/t<18.5)){var r=n/i;i=18.5*t,e.css({width:i*r,height:i})}};n.height()?i(n.width(),n.height()):n.one("load",function(){i(this.width,this.height)})},S.prototype.addElementSolutionButton=function(e,t,n){var i=this;t.showCPComments=function(){if(0===n.children(".h5p-element-solution").length&&(0,y.stripHTML)(e.solution).length>0){var t=(0,m.jQuery)("
",{role:"button",tabindex:0,title:i.l10n.solutionsButtonTitle,"aria-popup":!0,"aria-expanded":!1,class:"h5p-element-solution"}).append('').appendTo(n),r={x:e.x,y:e.y};e.displayAsButton||(r.x+=e.width-4,r.y+=e.height-12),(0,y.addClickAndKeyboardListeners)(t,function(){return i.showPopup(e.solution,t,r)})}},void 0!==e.alwaysDisplayComments&&e.alwaysDisplayComments&&t.showCPComments()},S.prototype.showPopup=function(e,t){var n,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,r=this,s=arguments[3],o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"h5p-popup-comment-field",a=this,l=function(e){if(n)return void(n=!1);void 0!==s&&setTimeout(function(){s(),a.restoreTabIndexes()},100),e.preventDefault(),d.addClass("h5p-animate"),d.find(".h5p-popup-container").addClass("h5p-animate"),setTimeout(function(){d.remove()},100),t.focus()},d=(0,m.jQuery)(''),c=d.find(".h5p-popup-wrapper");e instanceof H5P.jQuery?c.append(e):c.html(e);var u=d.find(".h5p-popup-container");return function(e,t,n){if(n){t.css({visibility:"hidden"}),e.prependTo(r.$wrapper);var i=t.height(),s=t.width(),o=e.height(),a=e.width(),l=s*(100/a),d=i*(100/o);if(l>50&&d>50)return void e.detach();l>d&&d<45&&(l=Math.sqrt(l*d),t.css({width:l+"%"}));var c=100-l-7.5,u=n.x;n.x>c?u=c:n.x<7.5&&(u=7.5),d=t.height()*(100/o);var p=100-d-10,h=n.y;n.y>p?h=p:n.y<10&&(h=10),e.detach(),t.css({left:u+"%",top:h+"%"})}}(d,u,i),d.addClass("h5p-animate"),u.css({visibility:""}).addClass("h5p-animate"),d.prependTo(this.$wrapper).focus().removeClass("h5p-animate").click(l).find(".h5p-popup-container").removeClass("h5p-animate").click(function(){n=!0}).keydown(function(e){e.which===y.keyCode.ESC&&l(e)}).end(),(0,y.addClickAndKeyboardListeners)(d.find(".h5p-close-popup"),function(e){return l(e)}),d},S.prototype.checkForSolutions=function(e){return void 0!==e.showSolutions||void 0!==e.showCPComments},S.prototype.initKeyEvents=function(){if(void 0===this.keydown&&!this.activeSurface){var e=this,t=!1;this.keydown=function(n){t||(37!==n.keyCode&&33!==n.keyCode||!e.previousSlide()?39!==n.keyCode&&34!==n.keyCode||!e.nextSlide()||(n.preventDefault(),t=!0):(n.preventDefault(),t=!0),t&&setTimeout(function(){t=!1},300))},H5P.jQuery("body").keydown(this.keydown)}},S.prototype.initTouchEvents=function(){var e,t,n,i,r,s,o=this,a=!1,l=!1,d=function(e){return{"-webkit-transform":e,"-moz-transform":e,"-ms-transform":e,transform:e}},c=d("");this.$slidesWrapper.bind("touchstart",function(d){l=!1,n=e=d.originalEvent.touches[0].pageX,t=d.originalEvent.touches[0].pageY;var c=o.$slidesWrapper.width();i=0===o.currentSlideIndex?0:-c,r=o.currentSlideIndex+1>=o.slides.length?0:c,s=null,a=!0}).bind("touchmove",function(c){var u=c.originalEvent.touches;a&&(o.$current.prev().addClass("h5p-touch-move"),o.$current.next().addClass("h5p-touch-move"),a=!1),n=u[0].pageX;var p=e-n;null===s&&(s=Math.abs(t-c.originalEvent.touches[0].pageY)>Math.abs(p)),1!==u.length||s||(c.preventDefault(),l||(p<0?o.$current.prev().css(d("translateX("+(i-p)+"px")):o.$current.next().css(d("translateX("+(r-p)+"px)")),o.$current.css(d("translateX("+-p+"px)"))))}).bind("touchend",function(){if(!s){var t=e-n;if(t>o.swipeThreshold&&o.nextSlide()||t<-o.swipeThreshold&&o.previousSlide())return}o.$slidesWrapper.children().css(c).removeClass("h5p-touch-move")})},S.prototype.updateTouchPopup=function(e,t,n,i){if(arguments.length<=0)return void(void 0!==this.touchPopup&&this.touchPopup.remove());var r="";if(void 0!==this.$keywords&&void 0!==this.$keywords.children(":eq("+t+")").find("span").html())r+=this.$keywords.children(":eq("+t+")").find("span").html();else{var s=t+1;r+=this.l10n.slide+" "+s}void 0===this.editor&&t>=this.slides.length-1&&(r=this.l10n.showSolutions),void 0===this.touchPopup?this.touchPopup=H5P.jQuery("
",{class:"h5p-touch-popup"}).insertAfter(e):this.touchPopup.insertAfter(e),i-.15*e.parent().height()<0?i=0:i-=.15*e.parent().height(),this.touchPopup.css({"max-width":e.width()-n,left:n,top:i}),this.touchPopup.html(r)},S.prototype.previousSlide=function(e){var t=this.$current.prev();return!!t.length&&this.jumpToSlide(t.index(),e,!1)},S.prototype.nextSlide=function(e){var t=this.$current.next();return!!t.length&&this.jumpToSlide(t.index(),e,!1)},S.prototype.isCurrentSlide=function(e){return this.currentSlideIndex===e},S.prototype.getCurrentSlideIndex=function(){return this.currentSlideIndex},S.prototype.attachAllElements=function(){for(var e=this.$slidesWrapper.children(),t=0;t
1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=this;if(void 0===this.editor&&this.contentId){var r=this.createXAPIEventTemplate("progressed");r.data.statement.object.definition.extensions["http://id.tincanapi.com/extension/ending-point"]=e+1,this.trigger(r)}if(!this.$current.hasClass("h5p-animate")){var s=this.$current.addClass("h5p-animate"),o=i.$slidesWrapper.children(),a=o.filter(":lt("+e+")");this.$current=o.eq(e).addClass("h5p-animate");var l=this.currentSlideIndex;this.currentSlideIndex=e,this.attachElements(this.$current,e);var d=this.$current.next();d.length&&this.attachElements(d,e+1),this.setOverflowTabIndex();var c=this.elementInstances[l];if(void 0!==c)for(var u=0;un&&e.attr("tabindex",0)})},S.prototype.setSlideNumberAnnouncer=function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n="";if(!this.navigationLine)return n;var i=this.slides[e];i.keywords&&i.keywords.length>0&&!this.navigationLine.isSummarySlide(e)&&(n+=this.l10n.slide+" "+(e+1)+": "),n+=this.navigationLine.createSlideTitle(e),this.$slideAnnouncer.html(n),t&&this.$slideTop.focus()},S.prototype.resetTask=function(){this.summarySlideObject.toggleSolutionMode(!1);for(var e=0;e=this.cp.slides.length-1,s=!this.cp.showSummarySlide&&this.cp.hasAnswerElements;if(r){n.cp.presentation.keywordListEnabled&&n.cp.presentation.keywordListAlwaysShow&&n.cp.hideKeywords(),this.$summarySlide.children().remove();var o=n.cp.getSlideScores(t),a=n.outputScoreStats(o);if((0,i.jQuery)(a).appendTo(n.$summarySlide),!s){var l=n.totalScores(o);if(!isNaN(l.totalPercentage)){var d=i.JoubelUI.createScoreBar(l.totalMaxScore,"","","");d.setScore(l.totalScore);var c=(0,i.jQuery)(".h5p-summary-total-score",n.$summarySlide);d.appendTo(c),setTimeout(function(){c.append((0,i.jQuery)("
",{"aria-live":"polite",class:"hidden-but-read",html:n.cp.l10n.summary+". "+n.cp.l10n.accessibilityTotalScore.replace("@score",l.totalScore).replace("@maxScore",l.totalMaxScore)}))},100)}if(1==n.cp.enableTwitterShare){var u=(0,i.jQuery)(".h5p-summary-twitter-message",n.$summarySlide);this.addTwitterScoreLinkTo(u,l)}if(1==n.cp.enableFacebookShare){var p=(0,i.jQuery)(".h5p-summary-facebook-message",n.$summarySlide);this.addFacebookScoreLinkTo(p,l)}if(1==n.cp.enableGoogleShare){var h=(0,i.jQuery)(".h5p-summary-google-message",n.$summarySlide);this.addGoogleScoreLinkTo(h)}n.$summarySlide.find(".h5p-td > .h5p-slide-link").each(function(){var e=(0,i.jQuery)(this);e.click(function(t){n.cp.jumpToSlide(parseInt(e.data("slide"),10)-1),t.preventDefault()})})}var f=(0,i.jQuery)(".h5p-summary-footer",n.$summarySlide);this.cp.showSummarySlideSolutionButton&&i.JoubelUI.createButton({class:"h5p-show-solutions",html:n.cp.l10n.showSolutions,on:{click:function(){n.toggleSolutionMode(!0)}},appendTo:f}),this.cp.showSummarySlideRetryButton&&i.JoubelUI.createButton({class:"h5p-cp-retry-button",html:n.cp.l10n.retry,on:{click:function(){n.cp.resetTask()}},appendTo:f}),n.cp.hasAnswerElements&&i.JoubelUI.createButton({class:"h5p-eta-export",html:n.cp.l10n.exportAnswers,on:{click:function(){H5P.ExportableTextArea.Exporter.run(n.cp.slides,n.cp.elementInstances)}},appendTo:f})}},e.prototype.outputScoreStats=function(e){var t=this;if(void 0===e)return this.$summarySlide.addClass("h5p-summary-only-export"),'';var n,i=this,r=0,s=0,o="",a=0,l="";for(n=0;n]+)>)/gi,"")+" "+a+'%" data-slide="'+e[n].slide+'">'+i.cp.l10n.slide+" "+e[n].slide+": "+l.replace(/(<([^>]+)>)/gi,"")+' '+a+"%
"+e[n].score+"/ "+e[n].maxScore+"
",r+=e[n].score,s+=e[n].maxScore;i.cp.triggerXAPICompleted(r,s);var d=i.cp.enableTwitterShare||i.cp.enableFacebookShare||i.cp.enableGoogleShare?''+i.cp.l10n.shareResult+" ":"",c=1==i.cp.enableTwitterShare?'':"",u=1==i.cp.enableFacebookShare?' ':"",p=1==i.cp.enableGoogleShare?' ':"";return''},e.prototype.getSlideDescription=function(e){var t,n,i=this,r=i.cp.slides[e.slide-1].elements;if(e.indexes.length>1)t=i.cp.l10n.summaryMultipleTaskText;else if(void 0!==r[e.indexes[0]]&&r[0])if(n=r[e.indexes[0]].action,"function"==typeof i.cp.elementInstances[e.slide-1][e.indexes[0]].getTitle)t=i.cp.elementInstances[e.slide-1][e.indexes[0]].getTitle();else if(void 0!==n.library&&n.library){var s=n.library.split(" ")[0].split(".")[1].split(/(?=[A-Z])/),o="";s.forEach(function(e,t){0!==t&&(e=e.toLowerCase()),o+=e,t<=s.length-1&&(o+=" ")}),t=o}return t},e.prototype.addTwitterScoreLinkTo=function(e,t){var n=this,i=n.cp.twitterShareStatement||"",s=n.cp.twitterShareHashtags||"",o=n.cp.twitterShareUrl||"";o=o.replace("@currentpageurl",window.location.href),i=i.replace("@score",t.totalScore).replace("@maxScore",t.totalMaxScore).replace("@percentage",t.totalPercentage+"%").replace("@currentpageurl",window.location.href),s=s.trim().replace(" ",""),i=encodeURIComponent(i),s=encodeURIComponent(s),o=encodeURIComponent(o);var a="https://twitter.com/intent/tweet?";a+=i.length>0?"text="+i+"&":"",a+=o.length>0?"url="+o+"&":"",a+=s.length>0?"hashtags="+s:"";var l=window.innerWidth/2,d=window.innerHeight/2;e.attr("tabindex","0").attr("role","button"),(0,r.addClickAndKeyboardListeners)(e,function(){return window.open(a,n.cp.l10n.shareTwitter,"width=800,height=300,left="+l+",top="+d),!1})},e.prototype.addFacebookScoreLinkTo=function(e,t){var n=this,i=n.cp.facebookShareUrl||"",s=n.cp.facebookShareQuote||"";i=i.replace("@currentpageurl",window.location.href),s=s.replace("@currentpageurl",window.location.href).replace("@percentage",t.totalPercentage+"%").replace("@score",t.totalScore).replace("@maxScore",t.totalMaxScore),i=encodeURIComponent(i),s=encodeURIComponent(s);var o="https://www.facebook.com/sharer/sharer.php?";o+=i.length>0?"u="+i+"&":"",o+=s.length>0?"quote="+s:"";var a=window.innerWidth/2,l=window.innerHeight/2;e.attr("tabindex","0").attr("role","button"),(0,r.addClickAndKeyboardListeners)(e,function(){return window.open(o,n.cp.l10n.shareFacebook,"width=800,height=300,left="+a+",top="+l),!1})},e.prototype.addGoogleScoreLinkTo=function(e){var t=this,n=t.cp.googleShareUrl||"";n=n.replace("@currentpageurl",window.location.href),n=encodeURIComponent(n);var i="https://plus.google.com/share?";i+=n.length>0?"url="+n:"";var s=window.innerWidth/2,o=window.innerHeight/2;e.attr("tabindex","0").attr("role","button"),(0,r.addClickAndKeyboardListeners)(e,function(){return window.open(i,t.cp.l10n.shareGoogle,"width=401,height=437,left="+s+",top="+o),!1})},e.prototype.totalScores=function(e){if(void 0===e)return{totalScore:0,totalMaxScore:0,totalPercentage:0};var t,n=0,i=0;for(t=0;t",{class:"h5p-progressbar-part"}).appendTo(i.cp.$progressbar),h=e("",{href:"#",html:''+d+" ",tabindex:"-1"}).data("slideNumber",o).click(s).appendTo(p);if(this.progresbarKeyboardControls.addElement(h.get(0)),u.isIOS||function(){var t=e("
",{class:"h5p-progressbar-popup",html:d,"aria-hidden":"true"}).appendTo(p);p.mouseenter(function(){return n.ensurePopupVisible(t)})}(),this.isSummarySlide(o)&&p.addClass("progressbar-part-summary-slide"),0===o&&p.addClass("h5p-progressbar-part-show"),o===r&&p.addClass("h5p-progressbar-part-selected"),i.cp.progressbarParts.push(p),this.updateSlideTitle(o),this.cp.slides.length<=60&&a.elements&&a.elements.length>0){var f=t[o]&&t[o].length>0,v=!!(i.cp.previousState&&i.cp.previousState.answered&&i.cp.previousState.answered[o]);f&&(e("",{class:"h5p-progressbar-part-has-task"}).appendTo(h),this.setTaskAnswered(o,v))}}},t.prototype.ensurePopupVisible=function(e){var t=this.cp.$container.width(),n=e.outerWidth(),i=e.offset().left;i<0?(e.css("left",0),e.css("transform","translateX(0)")):i+n>t&&(e.css("left","auto"),e.css("right",0),e.css("transform","translateX(0)"))},t.prototype.displaySlide=function(e){var t=this.cp.getCurrentSlideIndex();this.updateSlideTitle(e,{isCurrent:!0}),this.updateSlideTitle(t,{isCurrent:!1}),this.cp.jumpToSlide(e),this.toggleNextAndPreviousButtonDisabled(e)},t.prototype.createSlideTitle=function(e){var t=this.cp.slides[e];return t.keywords&&t.keywords.length>0?t.keywords[0].main:this.isSummarySlide(e)?this.cp.l10n.summary:this.cp.l10n.slide+" "+(e+1)},t.prototype.isSummarySlide=function(e){return!(void 0!==this.cp.editor||e!==this.cp.slides.length-1||!this.cp.showSummarySlide)},t.prototype.initFooter=function(){var t=this,n=this,i=this.cp.$footer,r=e("
",{class:"h5p-footer-left-adjusted"}).appendTo(i),s=e("
",{class:"h5p-footer-center-adjusted"}).appendTo(i),a=e("
",{role:"toolbar",class:"h5p-footer-right-adjusted"}).appendTo(i);this.cp.$keywordsButton=e("
",{class:"h5p-footer-button h5p-footer-toggle-keywords","aria-expanded":"false","aria-label":this.cp.l10n.showKeywords,title:this.cp.l10n.showKeywords,role:"button",tabindex:"0",html:'
'}).appendTo(r),(0,u.addClickAndKeyboardListeners)(this.cp.$keywordsButton,function(e){n.cp.presentation.keywordListAlwaysShow||(n.cp.toggleKeywords(),e.stopPropagation())}),!this.cp.presentation.keywordListAlwaysShow&&this.cp.initKeywords||this.cp.$keywordsButton.hide(),this.cp.presentation.keywordListEnabled||this.cp.$keywordsWrapper.add(this.$keywordsButton).hide(),this.updateFooterKeyword(0),this.cp.$prevSlideButton=e("
",{class:"h5p-footer-button h5p-footer-previous-slide","aria-label":this.cp.l10n.prevSlide,title:this.cp.l10n.prevSlide,role:"button",tabindex:"-1","aria-disabled":"true"}).appendTo(s),(0,u.addClickAndKeyboardListeners)(this.cp.$prevSlideButton,function(){return t.cp.previousSlide()});var l=e("
",{class:"h5p-footer-slide-count"}).appendTo(s);this.cp.$footerCurrentSlide=e("
",{html:"1",class:"h5p-footer-slide-count-current",title:this.cp.l10n.currentSlide,"aria-hidden":"true"}).appendTo(l),this.cp.$footerCounter=e("
",{class:"hidden-but-read",html:this.cp.l10n.slideCount.replace("@index","1").replace("@total",this.cp.slides.length.toString())}).appendTo(s),e("
",{html:"/",class:"h5p-footer-slide-count-delimiter","aria-hidden":"true"}).appendTo(l),this.cp.$footerMaxSlide=e("
",{html:this.cp.slides.length,class:"h5p-footer-slide-count-max",title:this.cp.l10n.lastSlide,"aria-hidden":"true"}).appendTo(l),this.cp.$nextSlideButton=e("
",{class:"h5p-footer-button h5p-footer-next-slide","aria-label":this.cp.l10n.nextSlide,title:this.cp.l10n.nextSlide,role:"button",tabindex:"0"}).appendTo(s),(0,u.addClickAndKeyboardListeners)(this.cp.$nextSlideButton,function(){return t.cp.nextSlide()}),void 0===this.cp.editor&&(this.cp.$exitSolutionModeButton=e("
",{role:"button",class:"h5p-footer-exit-solution-mode","aria-label":this.cp.l10n.solutionModeTitle,title:this.cp.l10n.solutionModeTitle,tabindex:"0"}).appendTo(a),(0,u.addClickAndKeyboardListeners)(this.cp.$exitSolutionModeButton,function(){return n.cp.jumpToSlide(n.cp.slides.length-1)}),this.cp.enablePrintButton&&o.default.supported()&&(this.cp.$printButton=e("
",{class:"h5p-footer-button h5p-footer-print","aria-label":this.cp.l10n.printTitle,title:this.cp.l10n.printTitle,role:"button",tabindex:"0"}).appendTo(a),(0,u.addClickAndKeyboardListeners)(this.cp.$printButton,function(){return n.openPrintDialog()})),H5P.fullscreenSupported&&(this.cp.$fullScreenButton=e("
",{class:"h5p-footer-button h5p-footer-toggle-full-screen","aria-label":this.cp.l10n.fullscreen,title:this.cp.l10n.fullscreen,role:"button",tabindex:"0"}),(0,u.addClickAndKeyboardListeners)(this.cp.$fullScreenButton,function(){return n.cp.toggleFullScreen()}),this.cp.$fullScreenButton.appendTo(a))),this.cp.$exitSolutionModeText=e("
",{html:"",class:"h5p-footer-exit-solution-mode-text"}).appendTo(this.cp.$exitSolutionModeButton)},t.prototype.openPrintDialog=function(){var t=this,n=e(".h5p-wrapper");o.default.showDialog(this.cp.l10n,n,function(e){o.default.print(t.cp,n,e)}).children('[role="dialog"]').focus()},t.prototype.updateProgressBar=function(e,t,n){var i,r=this;for(i=0;i
i?r.cp.progressbarParts[i].addClass("h5p-progressbar-part-show"):r.cp.progressbarParts[i].removeClass("h5p-progressbar-part-show");if(r.progresbarKeyboardControls.setTabbableByIndex(e),r.cp.progressbarParts[e].addClass("h5p-progressbar-part-selected").siblings().removeClass("h5p-progressbar-part-selected"),void 0===t)return void r.cp.progressbarParts.forEach(function(e,t){r.setTaskAnswered(t,!1)});n||r.cp.editor},t.prototype.setTaskAnswered=function(e,t){this.cp.progressbarParts[e].find(".h5p-progressbar-part-has-task").toggleClass("h5p-answered",t),this.updateSlideTitle(e,{state:t?p.ANSWERED:p.NOT_ANSWERED})},t.prototype.updateSlideTitle=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.state,i=t.isCurrent;this.setSlideTitle(e,{state:(0,u.defaultValue)(n,this.getAnsweredState(e)),isCurrent:(0,u.defaultValue)(i,this.cp.isCurrentSlide(e))})},t.prototype.setSlideTitle=function(e,t){var n=t.state,i=void 0===n?p.NO_INTERACTIONS:n,r=t.isCurrent,s=void 0!==r&&r,o=this.cp.slides.length,a=this.cp.progressbarParts[e],l=a.find(".h5p-progressbar-part-title"),d=this.cp.l10n.slideCount.replace("@index",e+1).replace("@total",o),c=this.answeredLabels[i].replace("@slideName",this.createSlideTitle(e)),u=s?this.cp.l10n.currentSlide:"";l.html(d+": "+c+". "+u)},t.prototype.getAnsweredState=function(e){var t=this.cp.progressbarParts[e],n=this.slideHasInteraction(e),i=this.cp.slideHasAnsweredTask(e);return n?t.find(".h5p-is-correct").length>0?p.CORRECT:t.find(".h5p-is-wrong").length>0?p.INCORRECT:i?p.ANSWERED:p.NOT_ANSWERED:p.NO_INTERACTIONS},t.prototype.slideHasInteraction=function(e){return this.cp.progressbarParts[e].find(".h5p-progressbar-part-has-task").length>0},t.prototype.updateFooter=function(e){this.cp.$footerCurrentSlide.html(e+1),this.cp.$footerMaxSlide.html(this.cp.slides.length),this.cp.$footerCounter.html(this.cp.l10n.slideCount.replace("@index",(e+1).toString()).replace("@total",this.cp.slides.length.toString())),this.cp.isSolutionMode&&e===this.cp.slides.length-1?this.cp.$footer.addClass("summary-slide"):this.cp.$footer.removeClass("summary-slide"),this.toggleNextAndPreviousButtonDisabled(e),this.updateFooterKeyword(e)},t.prototype.toggleNextAndPreviousButtonDisabled=function(e){var t=this.cp.slides.length-1;this.cp.$prevSlideButton.attr("aria-disabled",(0===e).toString()),this.cp.$nextSlideButton.attr("aria-disabled",(e===t).toString()),this.cp.$prevSlideButton.attr("tabindex",0===e?"-1":"0"),this.cp.$nextSlideButton.attr("tabindex",e===t?"-1":"0")},t.prototype.updateFooterKeyword=function(e){var t=this.cp.slides[e],n="";t&&t.keywords&&t.keywords[0]&&(n=t.keywords[0].main),!this.cp.isEditor()&&this.cp.showSummarySlide&&e>=this.cp.slides.length-1&&(n=this.cp.l10n.summary),this.cp.$keywordsButton.children(".current-slide-title").html((0,u.defaultValue)(n,""))},t}(H5P.jQuery);t.default=h},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=n(1),r=function(e){function t(){}var n=0;return t.supported=function(){return"function"==typeof window.print},t.print=function(t,n,i){t.trigger("printing",{finished:!1,allSlides:i});var r=e(".h5p-slide.h5p-current"),s=r.height(),o=r.width(),a=o/670,l=e(".h5p-slide");l.css({height:s/a+"px",width:"670px",fontSize:Math.floor(100/a)+"%"});var d=n.height();n.css("height","auto"),l.toggleClass("doprint",!0===i),r.addClass("doprint"),setTimeout(function(){window.print(),l.css({height:"",width:"",fontSize:""}),n.css("height",d+"px"),t.trigger("printing",{finished:!0})},500)},t.showDialog=function(t,r,s){var o=this,a=n++,l="h5p-cp-print-dialog-"+a+"-title",d="h5p-cp-print-dialog-"+a+"-ingress",c=e('"},t.default=r},function(e,t,n){"use strict";function i(e){var t=this;if(void 0===e.action)t.instance=new s.default(e,{l10n:t.parent.parent.l10n,currentIndex:t.parent.index}),t.parent.parent.isEditor()||t.instance.on("navigate",function(e){var n=e.data;t.parent.parent.jumpToSlide(n)});else{var n;n=t.parent.parent.isEditor()?H5P.jQuery.extend(!0,{},e.action,t.parent.parent.elementsOverride):H5P.jQuery.extend(!0,e.action,t.parent.parent.elementsOverride),n.params.autoplay?(n.params.autoplay=!1,n.params.cpAutoplay=!0):n.params.playback&&n.params.playback.autoplay?(n.params.playback.autoplay=!1,n.params.cpAutoplay=!0):n.params.media&&n.params.media.params&&n.params.media.params.playback&&n.params.media.params.playback.autoplay?(n.params.media.params.playback.autoplay=!1,n.params.cpAutoplay=!0):n.params.media&&n.params.media.params&&n.params.media.params.autoplay?(n.params.media.params.autoplay=!1,n.params.cpAutoplay=!0):n.params.override&&n.params.override.autoplay&&(n.params.override.autoplay=!1,n.params.cpAutoplay=!0);var i=t.parent.parent.elementInstances[t.parent.index]?t.parent.parent.elementInstances[t.parent.index].length:0;t.parent.parent.previousState&&t.parent.parent.previousState.answers&&t.parent.parent.previousState.answers[t.parent.index]&&t.parent.parent.previousState.answers[t.parent.index][i]&&(n.userDatas={state:t.parent.parent.previousState.answers[t.parent.index][i]}),n.params=n.params||{},t.instance=H5P.newRunnable(n,t.parent.parent.contentId,void 0,!0,{parent:t.parent.parent}),void 0!==t.instance.preventResize&&(t.instance.preventResize=!0)}void 0===t.parent.parent.elementInstances[t.parent.index]?t.parent.parent.elementInstances[t.parent.index]=[t.instance]:t.parent.parent.elementInstances[t.parent.index].push(t.instance),(void 0!==t.instance.showCPComments||t.instance.isTask||void 0===t.instance.isTask&&void 0!==t.instance.showSolutions)&&(t.instance.coursePresentationIndexOnSlide=t.parent.parent.elementInstances[t.parent.index].length-1,void 0===t.parent.parent.slidesWithSolutions[t.parent.index]&&(t.parent.parent.slidesWithSolutions[t.parent.index]=[]),t.parent.parent.slidesWithSolutions[t.parent.index].push(t.instance)),void 0!==t.instance.exportAnswers&&t.instance.exportAnswers&&(t.parent.parent.hasAnswerElements=!0),t.parent.parent.isTask||t.parent.parent.hideSummarySlide||(t.instance.isTask||void 0===t.instance.isTask&&void 0!==t.instance.showSolutions)&&(t.parent.parent.isTask=!0)}Object.defineProperty(t,"__esModule",{value:!0});var r=n(25),s=function(e){return e&&e.__esModule?e:{default:e}}(r);t.default=i},function(e,t,n){"use strict";function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n",{href:"#",class:m,tabindex:y,title:l}),(0,s.addClickAndKeyboardListeners)(this.$element,function(e){r.eventDispatcher.trigger("navigate",b),e.preventDefault()})}return r(e,[{key:"attach",value:function(e){e.html("").addClass("h5p-go-to-slide").append(this.$element)}},{key:"on",value:function(e,t){this.eventDispatcher.on(e,t)}}]),e}();t.default=l}]);;