=this.text.length&&this.selectionEnd>=this.text.length)return;this.abortCursorAnimation(),this._currentCursorOpacity=1,e.shiftKey?this.moveCursorRightWithShift(e):this.moveCursorRightWithoutShift(e),this.initDelayedCursor()},moveCursorRightWithShift:function(e){this._selectionDirection==="left"&&this.selectionStart!==this.selectionEnd?this._moveRight(e,"selectionStart"):(this._selectionDirection="right",this._moveRight(e,"selectionEnd"),this.text.charAt(this.selectionEnd-1)==="\n"&&this.selectionEnd++,this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length)),this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},moveCursorRightWithoutShift:function(e){this._selectionDirection="right",this.selectionStart===this.selectionEnd?(this._moveRight(e,"selectionStart"),this.selectionEnd=this.selectionStart):(this.selectionEnd+=this.getNumNewLinesInSelectedText(),this.selectionEnd>this.text.length&&(this.selectionEnd=this.text.length),this.selectionStart=this.selectionEnd),this.fire("selection:changed"),this.canvas&&this.canvas.fire("text:selection:changed",{target:this})},removeChars:function(e){this.selectionStart===this.selectionEnd?this._removeCharsNearCursor(e):this._removeCharsFromTo(this.selectionStart,this.selectionEnd),this.selectionEnd=this.selectionStart,this._removeExtraneousStyles(),this.canvas&&this.canvas.renderAll().renderAll(),this.setCoords(),this.fire("changed"),this.canvas&&this.canvas.fire("text:changed",{target:this})},_removeCharsNearCursor:function(e){if(this.selectionStart!==0)if(e.metaKey){var t=this.findLineBoundaryLeft(this.selectionStart);this._removeCharsFromTo(t,this.selectionStart),this.selectionStart=t}else if(e.altKey){var n=this.findWordBoundaryLeft(this.selectionStart);this._removeCharsFromTo(n,this.selectionStart),this.selectionStart=n}else{var r=this.text.slice(this.selectionStart-1,this.selectionStart)==="\n";this.removeStyleObject(r),this.selectionStart--,this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionStart+1)}}}),fabric.util.object.extend(fabric.IText.prototype,{_setSVGTextLineText:function(e,t,n,r,i,s){this.styles[t]?this._setSVGTextLineChars(e,t,n,r,i,s):this.callSuper("_setSVGTextLineText",e,t,n,r,i)},_setSVGTextLineChars:function(e,t,n,r,i,s){var o=t===0||this.useNative?"y":"dy",u=e.split(""),a=0,f=this._getSVGLineLeftOffset(t),l=this._getSVGLineTopOffset(t),c=this._getHeightOfLine(this.ctx,t);for(var h=0,p=u.length;h'].join("")},_createTextCharSpan:function(e,t,n,r,i,s){var o=this.getSvgStyles.call(fabric.util.object.extend({visible:!0,fill:this.fill,stroke:this.stroke,type:"text"},t));return['',fabric.util.string.escapeXml(e),""].join("")}}),function(){function request(e,t,n){var r=URL.parse(e);r.port||(r.port=r.protocol.indexOf("https:")===0?443:80);var i=r.port===443?HTTPS:HTTP,s=i.request({hostname:r.hostname,port:r.port,path:r.path,method:"GET"},function(e){var r="";t&&e.setEncoding(t),e.on("end",function(){n(r)}),e.on("data",function(t){e.statusCode===200&&(r+=t)})});s.on("error",function(e){e.errno===process.ECONNREFUSED?fabric.log("ECONNREFUSED: connection refused to "+r.hostname+":"+r.port):fabric.log(e.message)}),s.end()}function requestFs(e,t){var n=require("fs");n.readFile(e,function(e,n){if(e)throw fabric.log(e),e;t(n)})}if(typeof document!="undefined"&&typeof window!="undefined")return;var DOMParser=require("xmldom").DOMParser,URL=require("url"),HTTP=require("http"),HTTPS=require("https"),Canvas=require("canvas"),Image=require("canvas").Image;fabric.util.loadImage=function(e,t,n){function r(r){i.src=new Buffer(r,"binary"),i._src=e,t&&t.call(n,i)}var i=new Image;e&&(e instanceof Buffer||e.indexOf("data")===0)?(i.src=i._src=e,t&&t.call(n,i)):e&&e.indexOf("http")!==0?requestFs(e,r):e?request(e,"binary",r):t&&t.call(n,e)},fabric.loadSVGFromURL=function(e,t,n){e=e.replace(/^\n\s*/,"").replace(/\?.*$/,"").trim(),e.indexOf("http")!==0?requestFs(e,function(
e){fabric.loadSVGFromString(e.toString(),t,n)}):request(e,"",function(e){fabric.loadSVGFromString(e,t,n)})},fabric.loadSVGFromString=function(e,t,n){var r=(new DOMParser).parseFromString(e);fabric.parseSVGDocument(r.documentElement,function(e,n){t&&t(e,n)},n)},fabric.util.getScript=function(url,callback){request(url,"",function(body){eval(body),callback&&callback()})},fabric.Image.fromObject=function(e,t){fabric.util.loadImage(e.src,function(n){var r=new fabric.Image(n);r._initConfig(e),r._initFilters(e,function(e){r.filters=e||[],t&&t(r)})})},fabric.createCanvasForNode=function(e,t,n,r){r=r||n;var i=fabric.document.createElement("canvas"),s=new Canvas(e||600,t||600,r);i.style={},i.width=s.width,i.height=s.height;var o=fabric.Canvas||fabric.StaticCanvas,u=new o(i,n);return u.contextContainer=s.getContext("2d"),u.nodeCanvas=s,u.Font=Canvas.Font,u},fabric.StaticCanvas.prototype.createPNGStream=function(){return this.nodeCanvas.createPNGStream()},fabric.StaticCanvas.prototype.createJPEGStream=function(e){return this.nodeCanvas.createJPEGStream(e)};var origSetWidth=fabric.StaticCanvas.prototype.setWidth;fabric.StaticCanvas.prototype.setWidth=function(e,t){return origSetWidth.call(this,e,t),this.nodeCanvas.width=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setWidth=fabric.StaticCanvas.prototype.setWidth);var origSetHeight=fabric.StaticCanvas.prototype.setHeight;fabric.StaticCanvas.prototype.setHeight=function(e,t){return origSetHeight.call(this,e,t),this.nodeCanvas.height=e,this},fabric.Canvas&&(fabric.Canvas.prototype.setHeight=fabric.StaticCanvas.prototype.setHeight)}();PK m|Kvgh gh libs/darkroom.jsnu W+A !function(){"use strict";var element=document.createElement("div");element.id="darkroom-icons",element.style.height=0,element.style.width=0,element.style.position="absolute",element.style.visibility="hidden",element.innerHTML='',document.body.appendChild(element)}(),function(){"use strict";function Darkroom(element,options,plugins){return this.constructor(element,options,plugins)}window.Darkroom=Darkroom,Darkroom.plugins=[],Darkroom.prototype={containerElement:null,canvas:null,image:null,sourceCanvas:null,sourceImage:null,originalImageElement:null,transformations:[],defaults:{minWidth:null,minHeight:null,maxWidth:null,maxHeight:null,ratio:null,backgroundColor:"#fff",plugins:{},initialize:function(){}},plugins:{},options:{},constructor:function(element,options,plugins){if(this.options=Darkroom.Utils.extend(options,this.defaults),"string"==typeof element&&(element=document.querySelector(element)),null!==element){var image=new Image;image.onload=function(){this._initializeDOM(element),this._initializeImage(),this._initializePlugins(Darkroom.plugins),this.refresh(function(){this.options.initialize.bind(this).call()}.bind(this))}.bind(this),image.src=element.src}},selfDestroy:function(){var container=this.containerElement,image=new Image;image.onload=function(){container.parentNode.replaceChild(image,container)},image.src=this.sourceImage.toDataURL()},addEventListener:function(eventName,callback){var el=this.canvas.getElement();el.addEventListener?el.addEventListener(eventName,callback):el.attachEvent&&el.attachEvent("on"+eventName,callback)},dispatchEvent:function(eventName){var event=document.createEvent("Event");event.initEvent(eventName,!0,!0),this.canvas.getElement().dispatchEvent(event)},refresh:function(next){var clone=new Image;clone.onload=function(){this._replaceCurrentImage(new fabric.Image(clone)),next&&next()}.bind(this),clone.src=this.sourceImage.toDataURL()},_replaceCurrentImage:function(newImage){this.image&&this.image.remove(),this.image=newImage,this.image.selectable=!1;var viewport=Darkroom.Utils.computeImageViewPort(this.image),canvasWidth=viewport.width,canvasHeight=viewport.height;if(null!==this.options.ratio){var canvasRatio=+this.options.ratio,currentRatio=canvasWidth/canvasHeight;currentRatio>canvasRatio?canvasHeight=canvasWidth/canvasRatio:canvasRatio>currentRatio&&(canvasWidth=canvasHeight*canvasRatio)}var scaleMin=1,scaleMax=1,scaleX=1,scaleY=1;null!==this.options.maxWidth&&this.options.maxWidthcanvasWidth&&(scaleX=this.options.minWidth/canvasWidth),null!==this.options.minHeight&&this.options.minHeight>canvasHeight&&(scaleY=this.options.minHeight/canvasHeight),scaleMax=Math.max(scaleX,scaleY);var scale=scaleMax*scaleMin;canvasWidth*=scale,canvasHeight*=scale,this.image.setScaleX(1*scale),this.image.setScaleY(1*scale),this.canvas.add(this.image),canvasWidth-=2,canvasHeight-=2,this.canvas.setWidth(canvasWidth),this.canvas.setHeight(canvasHeight),this.canvas.centerObject(this.image),this.image.setCoords()},applyTransformation:function(transformation){this.transformations.push(transformation),transformation.applyTransformation(this.sourceCanvas,this.sourceImage,this._postTransformation.bind(this))},_postTransformation:function(newImage){newImage&&(this.sourceImage=newImage),this.refresh(function(){this.dispatchEvent("core:transformation")}.bind(this))},reinitializeImage:function(){this.sourceImage.remove(),this._initializeImage(),this._popTransformation(this.transformations.slice())},_popTransformation:function(transformations){if(0===transformations.length)return this.dispatchEvent("core:reinitialized"),void this.refresh();var transformation=transformations.shift(),next=function(newImage){newImage&&(this.sourceImage=newImage),this._popTransformation(transformations)};transformation.applyTransformation(this.sourceCanvas,this.sourceImage,next.bind(this))},_initializeDOM:function(imageElement){var mainContainerElement=document.createElement("div");mainContainerElement.className="darkroom-container";var toolbarElement=document.createElement("div");toolbarElement.className="darkroom-toolbar",mainContainerElement.appendChild(toolbarElement);var canvasContainerElement=document.createElement("div");canvasContainerElement.className="darkroom-image-container";var canvasElement=document.createElement("canvas");canvasContainerElement.appendChild(canvasElement),mainContainerElement.appendChild(canvasContainerElement);var sourceCanvasContainerElement=document.createElement("div");sourceCanvasContainerElement.className="darkroom-source-container",sourceCanvasContainerElement.style.display="none";var sourceCanvasElement=document.createElement("canvas");sourceCanvasContainerElement.appendChild(sourceCanvasElement),mainContainerElement.appendChild(sourceCanvasContainerElement),imageElement.parentNode.replaceChild(mainContainerElement,imageElement),imageElement.style.display="none",mainContainerElement.appendChild(imageElement),this.containerElement=mainContainerElement,this.originalImageElement=imageElement,this.toolbar=new Darkroom.UI.Toolbar(toolbarElement),this.canvas=new fabric.Canvas(canvasElement,{selection:!1,backgroundColor:this.options.backgroundColor}),this.sourceCanvas=new fabric.Canvas(sourceCanvasElement,{selection:!1,backgroundColor:this.options.backgroundColor})},_initializeImage:function(){this.sourceImage=new fabric.Image(this.originalImageElement,{selectable:!1,evented:!1,lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0,hasControls:!1,hasBorders:!1}),this.sourceCanvas.add(this.sourceImage);var viewport=Darkroom.Utils.computeImageViewPort(this.sourceImage),canvasWidth=viewport.width,canvasHeight=viewport.height;this.sourceCanvas.setWidth(canvasWidth),this.sourceCanvas.setHeight(canvasHeight),this.sourceCanvas.centerObject(this.sourceImage),this.sourceImage.setCoords()},_initializePlugins:function(plugins){for(var name in plugins){var plugin=plugins[name],options=this.options.plugins[name];options!==!1&&plugins.hasOwnProperty(name)&&(this.plugins[name]=new plugin(this,options))}}}}(),function(){"use strict";function Plugin(darkroom,options){this.darkroom=darkroom,this.options=Darkroom.Utils.extend(options,this.defaults),this.initialize()}Darkroom.Plugin=Plugin,Plugin.prototype={defaults:{},initialize:function(){}},Plugin.extend=function(protoProps){var child,parent=this;child=protoProps&&protoProps.hasOwnProperty("constructor")?protoProps.constructor:function(){return parent.apply(this,arguments)},Darkroom.Utils.extend(child,parent);var Surrogate=function(){this.constructor=child};return Surrogate.prototype=parent.prototype,child.prototype=new Surrogate,protoProps&&Darkroom.Utils.extend(child.prototype,protoProps),child.__super__=parent.prototype,child}}(),function(){"use strict";function Transformation(options){this.options=options}Darkroom.Transformation=Transformation,Transformation.prototype={applyTransformation:function(image){}},Transformation.extend=function(protoProps){var child,parent=this;child=protoProps&&protoProps.hasOwnProperty("constructor")?protoProps.constructor:function(){return parent.apply(this,arguments)},Darkroom.Utils.extend(child,parent);var Surrogate=function(){this.constructor=child};return Surrogate.prototype=parent.prototype,child.prototype=new Surrogate,protoProps&&Darkroom.Utils.extend(child.prototype,protoProps),child.__super__=parent.prototype,child}}(),function(){"use strict";function Toolbar(element){this.element=element}function ButtonGroup(element){this.element=element}function Button(element){this.element=element}Darkroom.UI={Toolbar:Toolbar,ButtonGroup:ButtonGroup,Button:Button},Toolbar.prototype={createButtonGroup:function(options){var buttonGroup=document.createElement("div");return buttonGroup.className="darkroom-button-group",this.element.appendChild(buttonGroup),new ButtonGroup(buttonGroup)}},ButtonGroup.prototype={createButton:function(options){var defaults={image:"help",type:"default",group:"default",hide:!1,disabled:!1};options=Darkroom.Utils.extend(options,defaults);var buttonElement=document.createElement("button");buttonElement.type="button",buttonElement.className="darkroom-button darkroom-button-"+options.type,buttonElement.innerHTML='',this.element.appendChild(buttonElement);var button=new Button(buttonElement);return button.hide(options.hide),button.disable(options.disabled),button}},Button.prototype={addEventListener:function(eventName,listener){this.element.addEventListener?this.element.addEventListener(eventName,listener):this.element.attachEvent&&this.element.attachEvent("on"+eventName,listener)},removeEventListener:function(eventName,listener){this.element.removeEventListener&&this.element.removeEventListener(eventName,listener)},active:function(value){value?this.element.classList.add("darkroom-button-active"):this.element.classList.remove("darkroom-button-active")},hide:function(value){value?this.element.classList.add("darkroom-button-hidden"):this.element.classList.remove("darkroom-button-hidden")},disable:function(value){this.element.disabled=!!value}}}(),function(){"use strict";function extend(b,a){var prop;if(void 0===b)return a;for(prop in a)a.hasOwnProperty(prop)&&b.hasOwnProperty(prop)===!1&&(b[prop]=a[prop]);return b}function computeImageViewPort(image){return{height:Math.abs(image.getWidth()*Math.sin(image.getAngle()*Math.PI/180))+Math.abs(image.getHeight()*Math.cos(image.getAngle()*Math.PI/180)),width:Math.abs(image.getHeight()*Math.sin(image.getAngle()*Math.PI/180))+Math.abs(image.getWidth()*Math.cos(image.getAngle()*Math.PI/180))}}Darkroom.Utils={extend:extend,computeImageViewPort:computeImageViewPort}}(),function(window,document,Darkroom,fabric){"use strict";Darkroom.plugins.history=Darkroom.Plugin.extend({undoTransformations:[],initialize:function(){this._initButtons(),this.darkroom.addEventListener("core:transformation",this._onTranformationApplied.bind(this))},undo:function(){if(0!==this.darkroom.transformations.length){var lastTransformation=this.darkroom.transformations.pop();this.undoTransformations.unshift(lastTransformation),this.darkroom.reinitializeImage(),this._updateButtons()}},redo:function(){if(0!==this.undoTransformations.length){var cancelTransformation=this.undoTransformations.shift();this.darkroom.transformations.push(cancelTransformation),this.darkroom.reinitializeImage(),this._updateButtons()}},_initButtons:function(){var buttonGroup=this.darkroom.toolbar.createButtonGroup();return this.backButton=buttonGroup.createButton({image:"undo",disabled:!0}),this.forwardButton=buttonGroup.createButton({image:"redo",disabled:!0}),this.backButton.addEventListener("click",this.undo.bind(this)),this.forwardButton.addEventListener("click",this.redo.bind(this)),this},_updateButtons:function(){this.backButton.disable(0===this.darkroom.transformations.length),this.forwardButton.disable(0===this.undoTransformations.length)},_onTranformationApplied:function(){this.undoTransformations=[],this._updateButtons()}})}(window,document,Darkroom,fabric),function(){"use strict";var Rotation=Darkroom.Transformation.extend({applyTransformation:function(canvas,image,next){var angle=(image.getAngle()+this.options.angle)%360;image.rotate(angle);var width,height;height=Math.abs(image.getWidth()*Math.sin(angle*Math.PI/180))+Math.abs(image.getHeight()*Math.cos(angle*Math.PI/180)),width=Math.abs(image.getHeight()*Math.sin(angle*Math.PI/180))+Math.abs(image.getWidth()*Math.cos(angle*Math.PI/180)),canvas.setWidth(width),canvas.setHeight(height),canvas.centerObject(image),image.setCoords(),canvas.renderAll(),next()}});Darkroom.plugins.rotate=Darkroom.Plugin.extend({initialize:function(){var buttonGroup=this.darkroom.toolbar.createButtonGroup(),leftButton=buttonGroup.createButton({image:"rotate-left"}),rightButton=buttonGroup.createButton({image:"rotate-right"});leftButton.addEventListener("click",this.rotateLeft.bind(this)),rightButton.addEventListener("click",this.rotateRight.bind(this))},rotateLeft:function(){this.rotate(-90)},rotateRight:function(){this.rotate(90)},rotate:function(angle){this.darkroom.applyTransformation(new Rotation({angle:angle}))}})}(),function(){"use strict";var Crop=Darkroom.Transformation.extend({applyTransformation:function(canvas,image,next){var snapshot=new Image;snapshot.onload=function(){if(!(1>height||1>width)){var imgInstance=new fabric.Image(this,{selectable:!1,evented:!1,lockMovementX:!0,lockMovementY:!0,lockRotation:!0,lockScalingX:!0,lockScalingY:!0,lockUniScaling:!0,hasControls:!1,hasBorders:!1}),width=this.width,height=this.height;canvas.setWidth(width),canvas.setHeight(height),image.remove(),canvas.add(imgInstance),next(imgInstance)}};var viewport=Darkroom.Utils.computeImageViewPort(image),imageWidth=viewport.width,imageHeight=viewport.height,left=this.options.left*imageWidth,top=this.options.top*imageHeight,width=Math.min(this.options.width*imageWidth,imageWidth-left),height=Math.min(this.options.height*imageHeight,imageHeight-top);snapshot.src=canvas.toDataURL({left:left,top:top,width:width,height:height})}}),CropZone=fabric.util.createClass(fabric.Rect,{_render:function(ctx){this.callSuper("_render",ctx);var dashWidth=(ctx.canvas,7),flipX=this.flipX?-1:1,flipY=this.flipY?-1:1,scaleX=flipX/this.scaleX,scaleY=flipY/this.scaleY;ctx.scale(scaleX,scaleY),ctx.fillStyle="rgba(0, 0, 0, 0.5)",this._renderOverlay(ctx),void 0!==ctx.setLineDash?ctx.setLineDash([dashWidth,dashWidth]):void 0!==ctx.mozDash&&(ctx.mozDash=[dashWidth,dashWidth]),ctx.strokeStyle="rgba(0, 0, 0, 0.2)",this._renderBorders(ctx),this._renderGrid(ctx),ctx.lineDashOffset=dashWidth,ctx.strokeStyle="rgba(255, 255, 255, 0.4)",this._renderBorders(ctx),this._renderGrid(ctx),ctx.scale(1/scaleX,1/scaleY)},_renderOverlay:function(ctx){var canvas=ctx.canvas,x0=Math.ceil(-this.getWidth()/2-this.getLeft()),x1=Math.ceil(-this.getWidth()/2),x2=Math.ceil(this.getWidth()/2),x3=Math.ceil(this.getWidth()/2+(canvas.width-this.getWidth()-this.getLeft())),y0=Math.ceil(-this.getHeight()/2-this.getTop()),y1=Math.ceil(-this.getHeight()/2),y2=Math.ceil(this.getHeight()/2),y3=Math.ceil(this.getHeight()/2+(canvas.height-this.getHeight()-this.getTop()));ctx.beginPath(),ctx.moveTo(x0-1,y0-1),ctx.lineTo(x3+1,y0-1),ctx.lineTo(x3+1,y3+1),ctx.lineTo(x0-1,y3-1),ctx.lineTo(x0-1,y0-1),ctx.closePath(),ctx.moveTo(x1,y1),ctx.lineTo(x1,y2),ctx.lineTo(x2,y2),ctx.lineTo(x2,y1),ctx.lineTo(x1,y1),ctx.closePath(),ctx.fill()},_renderBorders:function(ctx){ctx.beginPath(),ctx.moveTo(-this.getWidth()/2,-this.getHeight()/2),ctx.lineTo(this.getWidth()/2,-this.getHeight()/2),ctx.lineTo(this.getWidth()/2,this.getHeight()/2),ctx.lineTo(-this.getWidth()/2,this.getHeight()/2),ctx.lineTo(-this.getWidth()/2,-this.getHeight()/2),ctx.stroke()},_renderGrid:function(ctx){ctx.beginPath(),ctx.moveTo(-this.getWidth()/2+1/3*this.getWidth(),-this.getHeight()/2),ctx.lineTo(-this.getWidth()/2+1/3*this.getWidth(),this.getHeight()/2),ctx.stroke(),ctx.beginPath(),ctx.moveTo(-this.getWidth()/2+2/3*this.getWidth(),-this.getHeight()/2),ctx.lineTo(-this.getWidth()/2+2/3*this.getWidth(),this.getHeight()/2),ctx.stroke(),ctx.beginPath(),ctx.moveTo(-this.getWidth()/2,-this.getHeight()/2+1/3*this.getHeight()),ctx.lineTo(this.getWidth()/2,-this.getHeight()/2+1/3*this.getHeight()),ctx.stroke(),ctx.beginPath(),ctx.moveTo(-this.getWidth()/2,-this.getHeight()/2+2/3*this.getHeight()),ctx.lineTo(this.getWidth()/2,-this.getHeight()/2+2/3*this.getHeight()),ctx.stroke()}});Darkroom.plugins.crop=Darkroom.Plugin.extend({startX:null,startY:null,isKeyCroping:!1,isKeyLeft:!1,isKeyUp:!1,defaults:{minHeight:1,minWidth:1,ratio:null,quickCropKey:!1},initialize:function(){var buttonGroup=this.darkroom.toolbar.createButtonGroup();this.cropButton=buttonGroup.createButton({image:"crop"}),this.okButton=buttonGroup.createButton({image:"done",type:"success",hide:!0}),this.cancelButton=buttonGroup.createButton({image:"close",type:"danger",hide:!0}),this.cropButton.addEventListener("click",this.toggleCrop.bind(this)),this.okButton.addEventListener("click",this.cropCurrentZone.bind(this)),this.cancelButton.addEventListener("click",this.releaseFocus.bind(this)),this.darkroom.canvas.on("mouse:down",this.onMouseDown.bind(this)),this.darkroom.canvas.on("mouse:move",this.onMouseMove.bind(this)),this.darkroom.canvas.on("mouse:up",this.onMouseUp.bind(this)),this.darkroom.canvas.on("object:moving",this.onObjectMoving.bind(this)),this.darkroom.canvas.on("object:scaling",this.onObjectScaling.bind(this)),fabric.util.addListener(fabric.document,"keydown",this.onKeyDown.bind(this)),fabric.util.addListener(fabric.document,"keyup",this.onKeyUp.bind(this)),this.darkroom.addEventListener("core:transformation",this.releaseFocus.bind(this))},onObjectMoving:function(event){if(this.hasFocus()){var currentObject=event.target;if(currentObject===this.cropZone){var canvas=this.darkroom.canvas,x=currentObject.getLeft(),y=currentObject.getTop(),w=currentObject.getWidth(),h=currentObject.getHeight(),maxX=canvas.getWidth()-w,maxY=canvas.getHeight()-h;0>x&¤tObject.set("left",0),0>y&¤tObject.set("top",0),x>maxX&¤tObject.set("left",maxX),y>maxY&¤tObject.set("top",maxY),this.darkroom.dispatchEvent("crop:update")}}},onObjectScaling:function(event){if(this.hasFocus()){var preventScaling=!1,currentObject=event.target;if(currentObject===this.cropZone){var canvas=this.darkroom.canvas,pointer=canvas.getPointer(event.e),minX=(pointer.x,pointer.y,currentObject.getLeft()),minY=currentObject.getTop(),maxX=currentObject.getLeft()+currentObject.getWidth(),maxY=currentObject.getTop()+currentObject.getHeight();if(null!==this.options.ratio&&(0>minX||maxX>canvas.getWidth()||0>minY||maxY>canvas.getHeight())&&(preventScaling=!0),0>minX||maxX>canvas.getWidth()||preventScaling){var lastScaleX=this.lastScaleX||1;currentObject.setScaleX(lastScaleX)}if(0>minX&¤tObject.setLeft(0),0>minY||maxY>canvas.getHeight()||preventScaling){var lastScaleY=this.lastScaleY||1;currentObject.setScaleY(lastScaleY)}0>minY&¤tObject.setTop(0),currentObject.getWidth()top&&(height+=top,top=0),0>left&&(width+=left,left=0),this.darkroom.applyTransformation(new Crop({top:top/image.getHeight(),left:left/image.getWidth(),width:width/image.getWidth(),height:height/image.getHeight()}))}},hasFocus:function(){return void 0!==this.cropZone},requireFocus:function(){this.cropZone=new CropZone({fill:"transparent",hasBorders:!1,originX:"left",originY:"top",cornerColor:"#444",cornerSize:8,transparentCorners:!1,lockRotation:!0,hasRotatingPoint:!1}),null!==this.options.ratio&&this.cropZone.set("lockUniScaling",!0),this.darkroom.canvas.add(this.cropZone),this.darkroom.canvas.defaultCursor="crosshair",this.cropButton.active(!0),this.okButton.hide(!1),this.cancelButton.hide(!1)},releaseFocus:function(){void 0!==this.cropZone&&(this.cropZone.remove(),this.cropZone=void 0,this.cropButton.active(!1),this.okButton.hide(!0),this.cancelButton.hide(!0),this.darkroom.canvas.defaultCursor="default",this.darkroom.dispatchEvent("crop:update"))},_renderCropZone:function(fromX,fromY,toX,toY){var canvas=this.darkroom.canvas,isRight=toX>fromX,isLeft=!isRight,isDown=toY>fromY,isUp=!isDown,minWidth=Math.min(+this.options.minWidth,canvas.getWidth()),minHeight=Math.min(+this.options.minHeight,canvas.getHeight()),leftX=Math.min(fromX,toX),rightX=Math.max(fromX,toX),topY=Math.min(fromY,toY),bottomY=Math.max(fromY,toY);leftX=Math.max(0,leftX),rightX=Math.min(canvas.getWidth(),rightX),topY=Math.max(0,topY),bottomY=Math.min(canvas.getHeight(),bottomY),minWidth>rightX-leftX&&(isRight?rightX=leftX+minWidth:leftX=rightX-minWidth),minHeight>bottomY-topY&&(isDown?bottomY=topY+minHeight:topY=bottomY-minHeight),0>leftX&&(rightX+=Math.abs(leftX),leftX=0),rightX>canvas.getWidth()&&(leftX-=rightX-canvas.getWidth(),rightX=canvas.getWidth()),0>topY&&(bottomY+=Math.abs(topY),topY=0),bottomY>canvas.getHeight()&&(topY-=bottomY-canvas.getHeight(),bottomY=canvas.getHeight());var width=rightX-leftX,height=bottomY-topY,currentRatio=width/height;if(this.options.ratio&&+this.options.ratio!==currentRatio){var ratio=+this.options.ratio;if(this.isKeyCroping&&(isLeft=this.isKeyLeft,isUp=this.isKeyUp),ratio>currentRatio){var newWidth=height*ratio;isLeft&&(leftX-=newWidth-width),width=newWidth}else if(currentRatio>ratio){var newHeight=height/(ratio*height/width);isUp&&(topY-=newHeight-height),height=newHeight}if(0>leftX&&(leftX=0),0>topY&&(topY=0),leftX+width>canvas.getWidth()){var newWidth=canvas.getWidth()-leftX;height=newWidth*height/width,width=newWidth,isUp&&(topY=fromY-height)}if(topY+height>canvas.getHeight()){var newHeight=canvas.getHeight()-topY;width=width*newHeight/height,height=newHeight,isLeft&&(leftX=fromX-width)}}this.cropZone.left=leftX,this.cropZone.top=topY,this.cropZone.width=width,this.cropZone.height=height,this.darkroom.canvas.bringToFront(this.cropZone),this.darkroom.dispatchEvent("crop:update")}})}(),function(){"use strict";Darkroom.plugins.save=Darkroom.Plugin.extend({defaults:{callback:function(){this.darkroom.selfDestroy()}},initialize:function(){var buttonGroup=this.darkroom.toolbar.createButtonGroup();this.destroyButton=buttonGroup.createButton({image:"save"}),this.destroyButton.addEventListener("click",this.options.callback.bind(this))}})}();PK m|K! README.mdnu W+A H5P Editor PHP Library
==========
A general library that is supposed to be used in most PHP implementations of H5P.
## License
All code is licensed under MIT LicensePK m|K6 6
.gitignorenu W+A *~
.sass-cache
/styles/nbproject/private/
vendor
.ideaPK m|K^B
h5peditor-storage.interface.phpnu W+A ' + ns.t('core', 'tutorial') + '').hide();
this.$exampleUrl = ns.$('' + ns.t('core', 'example') + '').hide();
// Create confirm dialog
var changeLibraryDialog = new H5P.ConfirmationDialog({
headerText: H5PEditor.t('core', 'changeLibrary'),
dialogText: H5PEditor.t('core', 'confirmChangeLibrary')
}).appendTo(document.body);
if (H5PIntegration.hubIsEnabled) {
this.selector = new ns.SelectorHub(libraries, defaultLibrary, changeLibraryDialog);
}
else {
this.selector = new ns.SelectorLegacy(libraries, defaultLibrary, changeLibraryDialog);
}
this.$selector = ns.$(this.selector.getElement());
/**
* @private
* @param {object} library
*/
var librarySelectHandler = function (library) {
that.currentLibrary = library.uberName;
that.loadSemantics(library.uberName, that.selector.getParams());
that.$tutorialUrl.attr('href', library.tutorialUrl ? library.tutorialUrl : '#').toggle(!!library.tutorialUrl);
that.$exampleUrl.attr('href', library.exampleUrl ? library.exampleUrl : '#').toggle(!!library.exampleUrl);
};
/**
* Event handler for loading a new library editor
* @private
*/
var loadLibrary = function () {
that.trigger('editorload', that.selector.currentLibrary);
that.selector.getSelectedLibrary(librarySelectHandler);
};
// Change library on confirmation
changeLibraryDialog.on('confirmed', loadLibrary);
// Revert selector on cancel
changeLibraryDialog.on('canceled', function () {
that.selector.resetSelection(that.currentLibrary, that.defaultParams);
});
// First time a library is selected in the editor
this.selector.on('selected', loadLibrary);
this.selector.on('resize', function () {
that.trigger('resize');
});
this.on('select', loadLibrary);
};
// Extends the event dispatcher
ns.LibrarySelector.prototype = Object.create(H5P.EventDispatcher.prototype);
ns.LibrarySelector.prototype.constructor = ns.LibrarySelector;
/**
* Sets the current library
*
* @param {string} library
*/
ns.LibrarySelector.prototype.setLibrary = function (library) {
this.trigger('select');
};
/**
* Append the selector html to the given container.
*
* @param {jQuery} $element
* @returns {undefined}
*/
ns.LibrarySelector.prototype.appendTo = function ($element) {
this.$parent = $element;
this.$selector.appendTo($element);
this.$tutorialUrl.appendTo($element);
this.$exampleUrl.appendTo($element);
};
/**
* Display loading message and load library semantics.
*
* @param {String} library
* @param {Object} params Pass in params to semantics
* @returns {unresolved}
*/
ns.LibrarySelector.prototype.loadSemantics = function (library, params) {
var that = this;
if (this.form !== undefined) {
// Remove old form.
this.form.remove();
}
if (library === '-') {
// No library chosen.
this.$parent.attr('class', 'h5peditor');
return;
}
this.$parent.attr('class', 'h5peditor ' + library.split(' ')[0].toLowerCase().replace('.', '-') + '-editor');
// Display loading message
var $loading = ns.$('' + ns.t('core', 'loading') + '
').appendTo(this.$parent);
this.$selector.attr('disabled', true);
ns.resetLoadedLibraries();
ns.loadLibrary(library, function (semantics) {
if (!semantics) {
that.form = ns.$('', {
'class': 'h5p-errors',
text: H5PEditor.t('core', 'noSemantics'),
insertAfter: $loading
});
}
else {
var overrideParams = {};
if (params) {
overrideParams = params;
that.defaultParams = overrideParams;
}
else if (library === that.defaultLibrary || library === that.defaultLibraryParameterized) {
overrideParams = that.defaultParams;
}
that.form = new ns.Form();
that.form.replace($loading);
that.form.currentLibrary = library;
that.form.processSemantics(semantics, overrideParams);
}
that.$selector.attr('disabled', false);
$loading.remove();
that.trigger('editorloaded', library);
});
};
/**
* Returns currently selected library
*
* @returns {string} Currently selected library
*/
ns.LibrarySelector.prototype.getCurrentLibrary = function () {
return this.currentLibrary;
};
/**
* Return params needed to start library.
*/
ns.LibrarySelector.prototype.getParams = function () {
if (this.form === undefined) {
return;
}
// Only return if all fields has validated.
var valid = true;
if (this.form.children !== undefined) {
for (var i = 0; i < this.form.children.length; i++) {
if (this.form.children[i].validate() === false) {
valid = false;
}
}
}
//return valid ? this.form.params : false;
return this.form.params; // TODO: Switch to the line above when we are able to tell the user where the validation fails
};
PK m|Kg" " scripts/h5peditor-editor.jsnu W+A /**
* @namespace
*/
var H5PEditor = (H5PEditor || {});
var ns = H5PEditor;
/**
* Construct the editor.
*
* @class H5PEditor.Editor
* @param {string} library
* @param {Object} defaultParams
* @param {Element} replace
* @param {Function} iframeLoaded
*/
ns.Editor = function (library, defaultParams, replace, iframeLoaded) {
var self = this;
// Library may return "0", make sure this doesn't return true in checks
library = library && library != 0 ? library : '';
// Define iframe DOM Element through jQuery
var $iframe = ns.$('', {
'css': {
display: 'block',
width: '100%',
height: '3em',
border: 'none',
zIndex: 101,
top: 0,
left: 0
},
'class': 'h5p-editor-iframe',
'frameBorder': '0'
});
// The DOM element is often used directly
var iframe = $iframe.get(0);
/**
* Set the iframe content and start loading the necessary assets
*
* @private
*/
var populateIframe = function () {
iframe.contentDocument.open();
iframe.contentDocument.write(
'' +
'' +
ns.wrap('') +
ns.wrap('') +
'' +
'' + ns.t('core', 'loading') + '
' +
'');
iframe.contentDocument.close();
iframe.contentDocument.documentElement.style.overflow = 'hidden';
};
/**
* Wrapper for binding iframe unload event to a callback for multiple
* devices.
*
* @private
* @param {jQuery} $window of iframe
* @param {function} action callback on unload
*/
var onUnload = function ($window, action) {
$window.one('beforeunload unload', function () {
$window.off('pagehide beforeunload unload');
action();
});
$window.on('pagehide', action);
};
/**
* Checks if iframe needs resizing, and then resize it.
*
* @private
*/
var resize = function () {
if (!iframe.contentDocument.body) {
return; // Prevent crashing when iframe is unloaded
}
if (iframe.clientHeight === iframe.contentDocument.body.scrollHeight &&
iframe.contentDocument.body.scrollHeight === iframe.contentWindow.document.body.clientHeight) {
return; // Do not resize unless page and scrolling differs
}
// Retain parent size to avoid jumping/scrolling
var parentHeight = iframe.parentElement.style.height;
iframe.parentElement.style.height = iframe.parentElement.clientHeight + 'px';
// Reset iframe height, in case content has shrinked.
iframe.style.height = iframe.contentWindow.document.body.clientHeight + 'px';
// Resize iframe so all content is visible. Use scrollHeight to make sure we get everything
iframe.style.height = iframe.contentDocument.body.scrollHeight + 'px';
// Free parent
iframe.parentElement.style.height = parentHeight;
};
// Register loaded event handler for iframe
$iframe.load(function () {
if (!iframe.contentWindow.H5P) {
// The iframe has probably been reloaded, losing its content
setTimeout(function () {
// Wait for next tick as a new 'load' can't be triggered recursivly
populateIframe();
}, 0);
return;
}
// Trigger loaded callback. Could this have been an event?
if (iframeLoaded) {
iframeLoaded.call(this.contentWindow);
}
var LibrarySelector = this.contentWindow.H5PEditor.LibrarySelector;
var $ = this.contentWindow.H5P.jQuery;
var $container = $('body > .h5p-editor');
this.contentWindow.H5P.$body = $(this.contentDocument.body);
// Load libraries data
$.ajax({
url: this.contentWindow.H5PEditor.getAjaxUrl(H5PIntegration.hubIsEnabled ? 'content-type-cache' : 'libraries')
}).fail(function () {
$container.html('Error, unable to load libraries.');
}).done(function (data) {
if (data.success === false) {
$container.html(data.message + ' (' + data.errorCode + ')');
return;
}
// Create library selector
self.selector = new LibrarySelector(data, library, defaultParams);
self.selector.appendTo($container.html(''));
// Resize iframe when selector resizes
self.selector.on('resize', resize);
/**
* Event handler for exposing events
*
* @private
* @param {H5P.Event} event
*/
var relayEvent = function (event) {
H5P.externalDispatcher.trigger(event);
};
self.selector.on('editorload', relayEvent);
self.selector.on('editorloaded', relayEvent);
// Set library if editing
if (library) {
self.selector.setLibrary(library);
}
});
// Start resizing the iframe
if (iframe.contentWindow.MutationObserver !== undefined) {
// If supported look for changes to DOM elements. This saves resources.
var running;
var limitedResize = function (mutations) {
if (!running) {
running = setTimeout(function () {
resize();
running = null;
}, 40); // 25 fps cap
}
};
new iframe.contentWindow.MutationObserver(limitedResize).observe(iframe.contentWindow.document.body, {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeOldValue: false,
characterDataOldValue: false
});
H5P.$window.resize(limitedResize);
resize();
}
else {
// Use an interval for resizing the iframe
(function resizeInterval() {
resize();
setTimeout(resizeInterval, 40); // No more than 25 times per second
})();
}
// Handle iframe being reloaded
onUnload($(iframe.contentWindow), function () {
if (self.formSubmitted) {
return;
}
// Keep track of previous state
library = self.getLibrary();
defaultParams = JSON.stringify(self.getParams(true));
});
});
// Insert iframe into DOM
$iframe.replaceAll(replace);
// Populate iframe with the H5P Editor
populateIframe();
};
/**
* Find out which library is used/selected.
*
* @alias H5PEditor.Editor#getLibrary
* @returns {string} Library name
*/
ns.Editor.prototype.getLibrary = function () {
if (this.selector !== undefined) {
return this.selector.getCurrentLibrary();
}
else if(this.selectedContentTypeId) {
return this.selectedContentTypeId;
}
else {
console.warn('no selector defined for "getLibrary"');
}
};
/**
* Get parameters needed to start library.
*
* @alias H5PEditor.Editor#getParams
* @returns {Object} Library parameters
*/
ns.Editor.prototype.getParams = function (notFormSubmit) {
if (!notFormSubmit) {
this.formSubmitted = true;
}
if (this.selector !== undefined) {
return this.selector.getParams();
}
else if(this.form){
return this.form.params;
}
else {
console.warn('no selector defined for "getParams"');
}
};
/**
* Editor translations index by library name or "core".
*
* @member {Object} H5PEditor.language
*/
ns.language = {};
/**
* Translate text strings.
*
* @method H5PEditor.t
* @param {string} library The library name(machineName), or "core".
* @param {string} key Translation string identifier.
* @param {Object} [vars] Placeholders and values to replace in the text.
* @returns {string} Translated string, or a text if string translation is missing.
*/
ns.t = function (library, key, vars) {
if (ns.language[library] === undefined) {
return 'Missing translations for library ' + library;
}
var translation;
if (library === 'core') {
if (ns.language[library][key] === undefined) {
return 'Missing translation for ' + key;
}
translation = ns.language[library][key];
}
else {
if (ns.language[library].libraryStrings === undefined || ns.language[library].libraryStrings[key] === undefined) {
return ns.t('core', 'missingTranslation', {':key': key});
}
translation = ns.language[library].libraryStrings[key];
}
// Replace placeholder with variables.
for (var placeholder in vars) {
if (vars[placeholder] === undefined) {
continue;
}
translation = translation.replace(placeholder, vars[placeholder]);
}
return translation;
};
/**
* Wraps multiple content between a prefix and a suffix.
*
* @method H5PEditor.wrap
* @param {string} prefix Inserted before the content.
* @param {Array} content List of content to be wrapped.
* @param {string} suffix Inserted after the content.
* @returns {string} All content put together with prefix and suffix.
*/
ns.wrap = function (prefix, content, suffix) {
var result = '';
for (var i = 0; i < content.length; i++) {
result += prefix + content[i] + suffix;
}
return result;
};
PK m|KPcwd scripts/h5peditor-boolean.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Creates a boolean field for the editor.
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Boolean}
*/
ns.Boolean = function (parent, field, params, setValue) {
if (params === undefined) {
this.value = false;
setValue(field, this.value);
}
else {
this.value = params;
}
this.field = field;
this.setValue = setValue;
// Setup event dispatching on change
this.changes = [];
this.triggerListeners = function (value) {
// Run callbacks
for (var i = 0; i < this.changes.length; i++) {
this.changes[i](value);
}
}
};
/**
* Create HTML for the boolean field.
*/
ns.Boolean.prototype.createHtml = function () {
var checked = (this.value !== undefined && this.value) ? ' checked' : '';
var content = '';
return ns.createBooleanFieldMarkup(this.field, content);
};
/**
* "Validate" the current boolean field.
*/
ns.Boolean.prototype.validate = function () {
return true;
};
/**
* Append the boolean field to the given wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.Boolean.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$input = this.$item.find('input');
this.$errors = this.$item.find('.h5p-errors');
this.$input.change(function () {
// Validate
that.value = that.$input.is(':checked');
that.setValue(that.field, that.value);
that.triggerListeners(that.value);
});
};
/**
* Remove this item.
*/
ns.Boolean.prototype.remove = function () {
this.$item.remove();
};
// Tell the editor what widget we are.
ns.widgets['boolean'] = ns.Boolean;
PK m|Ks! ! scripts/h5peditor-select.jsnu W+A var H5PEditor = H5PEditor || {};
H5PEditor.widgets.select = H5PEditor.Select = (function (E) {
/**
* Initialize a new widget.
*
* @param {object} parent
* @param {object} field
* @param {object} params
* @param {function} setValue
* @returns {_L3.C}
*/
function C(parent, field, params, setValue) {
this.field = field;
this.value = params;
this.setValue = setValue;
// Setup event dispatching on change
this.changes = [];
this.triggerListeners = function (value) {
// Run callbacks
for (var i = 0; i < this.changes.length; i++) {
this.changes[i](value);
}
}
}
/**
* Append widget to the DOM.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
C.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = E.$(this.createHtml()).appendTo($wrapper);
this.$select = this.$item.find('select');
this.$errors = this.$item.children('.h5p-errors');
this.$select.change(function () {
var val = that.validate();
if (val !== false) {
that.value = val;
that.setValue(that.field, val);
that.triggerListeners(val);
}
});
};
/**
* Generate HTML for the widget.
*
* @returns {String} HTML.
*/
C.prototype.createHtml = function () {
if (this.field.optional === true || this.field.default === undefined) {
var options = E.createOption('-', '-');
}
options += C.createOptionsHtml(this.field.options, this.value);
var select = '';
return E.createFieldMarkup(this.field, select);
};
/**
* Generate HTML for select options.
*
* @param {Array} options
* @param {string} selected value
* @return {string}
*/
C.createOptionsHtml = function (options, selected) {
var html = '';
for (var i = 0; i < options.length; i++) {
html += E.createOption(options[i].value, options[i].label, options[i].value === selected);
}
return html;
};
/**
* Validate this field.
*
* @returns {Boolean}
*/
C.prototype.validate = function () {
var value = this.$select.val();
if (value === '-') {
value = undefined; // No value selected
}
if (this.field.optional !== true && value === undefined) {
// Not optional and no value selected, print required error
this.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': ns.t('core', 'textField')})));
return false;
}
// All valid. Remove old errors
var $errors = this.$errors.children();
if ($errors.length) {
$errors.remove();
}
return value;
};
/**
* Remove widget from DOM.
*
* @returns {undefined}
*/
C.prototype.remove = function () {
this.$item.remove();
};
return C;
})(H5PEditor);
PK m|KdQ<9 <9 scripts/h5peditor-html.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Adds a html text field to the form.
*
* @param {type} parent
* @param {type} field
* @param {type} params
* @param {type} setValue
* @returns {undefined}
*/
ns.Html = function (parent, field, params, setValue) {
this.parent = parent;
this.field = field;
this.value = params;
this.setValue = setValue;
this.tags = ns.$.merge(['br'], (this.field.tags || this.defaultTags));
};
ns.Html.first = true;
ns.Html.prototype.defaultTags = ['strong', 'em', 'del', 'h2', 'h3', 'a', 'ul', 'ol', 'table', 'hr'];
// This should probably be named "hasTag()" instead...
// And might be more efficient if this.tags.contains() were used?
ns.Html.prototype.inTags = function (value) {
return (ns.$.inArray(value.toLowerCase(), this.tags) >= 0);
};
ns.Html.prototype.createToolbar = function () {
var basicstyles = [];
var paragraph = [];
var formats = [];
var inserts = [];
var toolbar = [];
// Basic styles
if (this.inTags("strong") || this.inTags("b")) {
basicstyles.push('Bold');
// Might make "strong" duplicated in the tag lists. Which doesn't really
// matter. Note: CKeditor will only make strongs.
this.tags.push("strong");
}
if (this.inTags("em") || this.inTags("i")) {
basicstyles.push('Italic');
// Might make "em" duplicated in the tag lists. Which again
// doesn't really matter. Note: CKeditor will only make ems.
this.tags.push("em");
}
if (this.inTags("u")) basicstyles.push('Underline');
if (this.inTags("strike") || this.inTags("del") || this.inTags("s")) {
basicstyles.push('Strike');
// Might make "strike" or "del" or both duplicated in the tag lists. Which
// again doesn't really matter.
this.tags.push("strike");
this.tags.push("del");
this.tags.push("s");
}
if (this.inTags("sub")) basicstyles.push("Subscript");
if (this.inTags("sup")) basicstyles.push("Superscript");
if (basicstyles.length > 0) {
basicstyles.push("-");
basicstyles.push("RemoveFormat");
toolbar.push({
name: 'basicstyles',
items: basicstyles
});
}
// Alignment is added to all wysiwygs
toolbar.push({
name: "justify",
items: ["JustifyLeft", "JustifyCenter", "JustifyRight"]
});
// Paragraph styles
if (this.inTags("ul")) {
paragraph.push("BulletedList");
this.tags.push("li");
}
if (this.inTags("ol")) {
paragraph.push("NumberedList");
this.tags.push("li");
}
if (this.inTags("blockquote")) paragraph.push("Blockquote");
if (paragraph.length > 0) {
toolbar.push(paragraph);
}
// Links.
if (this.inTags("a")) {
var items = ["Link", "Unlink"];
if (this.inTags("anchor")) {
items.push("Anchor");
}
toolbar.push({
name: "links",
items: items
});
}
// Inserts
if (this.inTags("img")) inserts.push("Image");
if (this.inTags("table")) {
inserts.push("Table");
ns.$.merge(this.tags, ["tr", "td", "th", "colgroup", "thead", "tbody", "tfoot"]);
}
if (this.inTags("hr")) inserts.push("HorizontalRule");
if (inserts.length > 0) {
toolbar.push({
name: "insert",
items: inserts
});
}
// Create wrapper for text styling options
var styles = {
name: "styles",
items: []
};
var colors = {
name: "colors",
items: []
};
// Add format group if formatters in tags (h1, h2, etc). Formats use their
// own format_tags to filter available formats.
if (this.inTags("h1")) formats.push("h1");
if (this.inTags("h2")) formats.push("h2");
if (this.inTags("h3")) formats.push("h3");
if (this.inTags("h4")) formats.push("h4");
if (this.inTags("h5")) formats.push("h5");
if (this.inTags("h6")) formats.push("h6");
if (this.inTags("address")) formats.push("address");
if (this.inTags("pre")) formats.push("pre");
if (formats.length > 0 || this.inTags('p') || this.inTags('div')) {
formats.push("p"); // If the formats are shown, always have a paragraph..
this.tags.push("p");
styles.items.push('Format');
}
var ret = {
toolbar: toolbar
};
if (this.field.font !== undefined) {
this.tags.push('span');
/**
* Help set specified values for property.
*
* @private
* @param {Array} values list
* @param {string} prop Property
* @param {string} [defProp] Default property name
*/
var setValues = function (values, prop, defProp) {
ret[prop] = '';
for (var i = 0; i < values.length; i++) {
var val = values[i];
if (val.label && val.css) {
// Add label and CSS
ret[prop] += val.label + '/' + val.css + ';';
// Check if default value
if (defProp && val.default) {
ret[defProp] = val.label;
}
}
}
};
/**
* @private
* @param {Array} values
* @returns {string}
*/
var getColors = function (values) {
var colors = '';
for (var i = 0; i < values.length; i++) {
var val = values[i];
if (val.label && val.css) {
var css = val.css.match(/^#?([a-f0-9]{3}[a-f0-9]{3}?)$/i);
if (!css) {
continue;
}
// Add label and CSS
if (colors) {
colors += ',';
}
colors += val.label + '/' + css[1];
}
}
return colors;
};
if (this.field.font.family) {
// Font family chooser
styles.items.push('Font');
if (this.field.font.family instanceof Array) {
// Use specified families
setValues(this.field.font.family, 'font_names', 'font_defaultLabel');
}
}
if (this.field.font.size) {
// Font size chooser
styles.items.push('FontSize');
ret.fontSize_sizes = '';
if (this.field.font.size instanceof Array) {
// Use specified sizes
setValues(this.field.font.size, 'fontSize_sizes', 'fontSize_defaultLabel');
}
else {
ret.fontSize_defaultLabel = '100%';
// Standard font size that is used. (= 100%)
var defaultFont = 16;
// Standard font sizes that is available.
var defaultAvailable = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72];
for (var i = 0; i < defaultAvailable.length; i++) {
// Calculate percentage of standard font size. This enables scaling
// in content types without rounding errors across browsers.
var em = defaultAvailable[i] / 16;
ret.fontSize_sizes += (em * 100) + '%/' + em + 'em;';
}
}
}
if (this.field.font.color) {
// Text color chooser
colors.items.push('TextColor');
if (this.field.font.color instanceof Array) {
ret.colorButton_colors = getColors(this.field.font.color);
ret.colorButton_enableMore = false;
}
}
if (this.field.font.background) {
// Text background color chooser
colors.items.push('BGColor');
if (this.field.font.background instanceof Array) {
ret.colorButton_colors = getColors(this.field.font.color);
ret.colorButton_enableMore = false;
}
}
}
// Add the text styling options
if (styles.items.length) {
toolbar.push(styles);
}
if (colors.items.length) {
toolbar.push(colors);
}
// Set format_tags if not empty. CKeditor does not like empty format_tags.
if (formats.length) {
ret.format_tags = formats.join(';');
}
// Enable selection of enterMode in module semantics.
if (this.field.enterMode === 'p' || formats.length > 0) {
this.tags.push('p');
ret.enterMode = CKEDITOR.ENTER_P;
} else {
// Default to DIV, not allowing BR at all.
this.tags.push('div');
ret.enterMode = CKEDITOR.ENTER_DIV;
}
return ret;
};
/**
* Append field to wrapper.
*
* @param {type} $wrapper
* @returns {undefined}
*/
ns.Html.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$input = this.$item.children('.ckeditor');
this.$errors = this.$item.children('.h5p-errors');
ns.bindImportantDescriptionEvents(this, this.field.name, this.parent);
var ckConfig = {
extraPlugins: "",
startupFocus: true,
enterMode: CKEDITOR.ENTER_DIV,
allowedContent: true, // Disables the ckeditor content filter, might consider using it later... Must make sure it doesn't remove math...
protectedSource: []
};
ns.$.extend(ckConfig, this.createToolbar());
// Look for additions in HtmlAddons
if (ns.HtmlAddons) {
for (var tag in ns.HtmlAddons) {
if (that.inTags(tag)) {
for (var provider in ns.HtmlAddons[tag]) {
ns.HtmlAddons[tag][provider](ckConfig, that.tags);
}
}
}
}
this.$item.children('.ckeditor').focus(function () {
// Blur is not fired on destroy. Therefore we need to keep track of it!
var blurFired = false;
// Remove placeholder
that.$placeholder = that.$item.find('.h5peditor-ckeditor-placeholder').detach();
if (ns.Html.first) {
CKEDITOR.basePath = ns.basePath + '/ckeditor/';
}
if (ns.Html.current === that) {
return;
}
// Remove existing CK instance.
ns.Html.removeWysiwyg();
ns.Html.current = that;
ckConfig.width = this.offsetWidth - 8; // Avoid miscalculations
that.ckeditor = CKEDITOR.replace(this, ckConfig);
that.ckeditor.on('focus', function () {
blurFired = false;
});
that.ckeditor.once('destroy', function () {
// In some cases, the blur event is not fired. Need to be sure it is, so that
// validation and saving is done
if (!blurFired) {
blur();
}
// Display placeholder if:
// -- The value held by the field is empty AND
// -- The value shown in the UI is empty AND
// -- A placeholder is defined
var value = that.ckeditor !== undefined ? that.ckeditor.getData() : that.$input.html();
if (that.$placeholder.length !== 0 && (value === undefined || value.length === 0) && (that.value === undefined || that.value.length === 0)) {
that.$placeholder.appendTo(that.$item.find('.ckeditor'));
}
});
var blur = function () {
blurFired = true;
// Do not validate if the field has been hidden.
if (that.$item.is(':visible')) {
that.validate();
}
};
that.ckeditor.on('blur', blur);
// Add events to ckeditor. It is beeing done here since we know it exists
// at this point... Use case from commit message: "Make the default
// linkTargetType blank for ckeditor" - STGW
if (ns.Html.first) {
CKEDITOR.on('dialogDefinition', function(e) {
// Take the dialog name and its definition from the event data.
var dialogName = e.data.name;
var dialogDefinition = e.data.definition;
// Check if the definition is from the dialog window you are interested in (the "Link" dialog window).
if (dialogName === 'link') {
// Get a reference to the "Link Info" tab.
var targetTab = dialogDefinition.getContents('target');
// Set the default value for the URL field.
var urlField = targetTab.get('linkTargetType');
urlField['default'] = '_blank';
}
// Override show event handler
var onShow = dialogDefinition.onShow;
dialogDefinition.onShow = function () {
if (onShow !== undefined) {
onShow.apply(this, arguments);
}
// Grab current item
var $item = ns.Html.current.$item;
// Position dialog above text field
var itemPos = $item.offset();
var itemWidth = $item.width();
var itemHeight = $item.height();
var dialogSize = this.getSize();
var x = itemPos.left + (itemWidth / 2) - (dialogSize.width / 2);
var y = itemPos.top + (itemHeight / 2) - (dialogSize.height / 2);
this.move(x, y, true);
};
});
ns.Html.first = false;
}
});
};
/**
* Create HTML for the HTML field.
*/
ns.Html.prototype.createHtml = function () {
var input = '';
if (this.value !== undefined) {
input += this.value;
}
else if (this.field.placeholder !== undefined) {
input += '' + this.field.placeholder + '';
}
input += '
';
return ns.createFieldMarkup(this.field, ns.createImportantDescription(this.field.important) + input);
};
/**
* Validate the current text field.
*/
ns.Html.prototype.validate = function () {
var that = this;
if (that.$errors.children().length) {
that.$errors.empty();
this.$input.addClass('error');
}
// Get contents from editor
var value = this.ckeditor !== undefined ? this.ckeditor.getData() : this.$input.html();
// Remove placeholder text if any:
value = value.replace(/.*<\/span>/, '');
var $value = ns.$('' + value + '
');
var textValue = $value.text();
// Check if we have any text at all.
if (!this.field.optional && !textValue.length) {
// We can accept empty text, if there's an image instead.
if (! (this.inTags("img") && $value.find('img').length > 0)) {
this.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': ns.t('core', 'textField')})));
}
}
// Verify HTML tags. Removes tags not in allowed tags. Will replace with
// the tag's content. So if we get an unallowed container, the contents
// will remain, without the container.
$value.find('*').each(function () {
if (! that.inTags(this.tagName)) {
ns.$(this).replaceWith(ns.$(this).contents());
}
});
value = $value.html();
// Display errors and bail if set.
if (that.$errors.children().length) {
return false;
} else {
this.$input.removeClass('error');
}
this.value = value;
this.setValue(this.field, value);
this.$input.change(); // Trigger change event.
return value;
};
/**
* Destroy H5PEditor existing CK instance. If it exists.
*/
ns.Html.removeWysiwyg = function () {
if (ns.Html.current !== undefined) {
try {
ns.Html.current.ckeditor.destroy();
}
catch (e) {
// No-op, just stop error from propagating. This usually occurs if
// the CKEditor DOM has been removed together with other DOM data.
}
ns.Html.current = undefined;
}
};
/**
* Remove this item.
*/
ns.Html.prototype.remove = function () {
this.$item.remove();
};
ns.widgets.html = ns.Html;
PK m|K scripts/h5peditor-form.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Construct a form from library semantics.
*/
ns.Form = function () {
var self = this;
this.params = {};
this.passReadies = false;
this.commonFields = {};
this.$form = ns.$('' +
''
);
this.$common = this.$form.find('.common > .fields');
this.library = '';
// Add title expand/collapse button
ns.$('', {
'class': 'h5peditor-label',
title: ns.t('core', 'expandCollapse'),
role: 'button',
tabIndex: 0,
html: '' + ns.t('core', 'commonFields'),
on: {
click: function () {
self.$common.parent().toggleClass('collapsed');
},
keypress: function (event) {
if ((event.charCode || event.keyCode) === 32) {
self.$common.parent().toggleClass('collapsed');
event.preventDefault();
}
}
},
prependTo: this.$common.parent()
});
// Alternate background colors
this.zebra = "odd";
};
/**
* Replace the given element with our form.
*
* @param {jQuery} $element
* @returns {undefined}
*/
ns.Form.prototype.replace = function ($element) {
$element.replaceWith(this.$form);
this.offset = this.$form.offset();
// Prevent inputs and selects in an h5peditor form from submitting the main
// framework form.
this.$form.on('keydown', 'input,select', function (event) {
if (event.keyCode === 13) {
// Prevent enter key from submitting form.
return false;
}
});
};
/**
* Remove the current form.
*/
ns.Form.prototype.remove = function () {
ns.removeChildren(this.children);
this.$form.remove();
};
/**
* Wrapper for processing the semantics.
*
* @param {Array} semantics
* @param {Object} defaultParams
* @returns {undefined}
*/
ns.Form.prototype.processSemantics = function (semantics, defaultParams) {
this.params = defaultParams;
ns.processSemanticsChunk(semantics, this.params, this.$form.children('.tree'), this);
};
/**
* Collect functions to execute once the tree is complete.
*
* @param {function} ready
* @returns {undefined}
*/
ns.Form.prototype.ready = function (ready) {
this.readies.push(ready);
};
PK m|K(: : scripts/h5peditor-text.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Create a text field for the form.
*
* @param {mixed} parent
* @param {Object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Text}
*/
ns.Text = function (parent, field, params, setValue) {
this.field = field;
this.value = params;
this.setValue = setValue;
this.changeCallbacks = [];
};
/**
* Append field to wrapper.
*
* @param {type} $wrapper
* @returns {undefined}
*/
ns.Text.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$input = this.$item.find('input');
this.$errors = this.$item.children('.h5p-errors');
this.$input.change(function () {
// Validate
var value = that.validate();
if (value !== false) {
// Set param
if (H5P.trim(value) === '') {
// Avoid storing empty strings. (will be valid if field is optional)
delete that.value;
that.setValue(that.field);
}
else {
that.value = value;
that.setValue(that.field, ns.htmlspecialchars(value));
}
for (var i = 0; i < that.changeCallbacks.length; i++) {
that.changeCallbacks[i](value);
}
}
});
};
/**
* Run callback when value changes.
*
* @param {function} callback
* @returns {Number|@pro;length@this.changeCallbacks}
*/
ns.Text.prototype.change = function (callback) {
this.changeCallbacks.push(callback);
callback();
return this.changeCallbacks.length - 1;
};
/**
* Create HTML for the text field.
*/
ns.Text.prototype.createHtml = function () {
var input = ns.createText(this.value, this.field.maxLength, this.field.placeholder);
return ns.createFieldMarkup(this.field, input);
};
/**
* Validate the current text field.
*/
ns.Text.prototype.validate = function () {
var that = this;
var value = H5P.trim(this.$input.val());
if (this.$errors.html().length > 0) {
this.$input.addClass('error');
}
// Clear errors before showing new ones
this.$errors.html('');
if ((that.field.optional === undefined || !that.field.optional) && !value.length) {
this.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': ns.t('core', 'textField')})));
}
else if (value.length > this.field.maxLength) {
this.$errors.append(ns.createError(ns.t('core', 'tooLong', {':max': this.field.maxLength})));
}
else if (this.field.regexp !== undefined && value.length && !value.match(new RegExp(this.field.regexp.pattern, this.field.regexp.modifiers))) {
this.$errors.append(ns.createError(ns.t('core', 'invalidFormat')));
}
return ns.checkErrors(this.$errors, this.$input, value);
};
/**
* Remove this item.
*/
ns.Text.prototype.remove = function () {
this.$item.remove();
};
// Tell the editor what widget we are.
ns.widgets.text = ns.Text;
PK m|Kc ' scripts/h5peditor-semantic-structure.jsnu W+A /** @namespace H5PEditor */
var H5PEditor = H5PEditor || {};
H5PEditor.SemanticStructure = (function ($) {
var self = this;
/**
* The base of the semantic structure system.
* All semantic structure class types will inherit this class.
*
* @class
* @param {Object} field
* @param {Object} defaultWidget
*/
function SemanticStructure(field, defaultWidget) {
var self = this;
// Initialize event inheritance
H5P.EventDispatcher.call(self);
/**
* Determine this fields label. Used in error messages.
* @public
*/
self.label = (field.label === undefined ? field.name : field.label);
// Support old editor libraries
self.field = {};
/**
* Global instance variables.
* @private
*/
var $widgetSelect, $wrapper, $inner, $errors, $content, $helpText, widgets;
/**
* Initialize. Wrapped to avoid leaking variables
* @private
*/
var init = function () {
// Create field wrapper
$wrapper = $('', {
'class': 'field ' + field.type + ' ' + H5PEditor.createImportance(field.importance)
});
/* We want to be in control of the label, description and errors
containers to give the editor some structure. Also we do not provide
direct access to the field object to avoid cluttering semantics.json with
non-semantic properties and options. Getters and setters will be
created for what is needed. */
// Create field label
var $label;
if (field.label !== 0) {
// Add label
$label = createLabel(self.label, field.optional).appendTo($wrapper);
}
// Create description
var $description;
if (field.description !== undefined) {
$description = $('', {
'class': 'h5peditor-field-description',
text: field.description,
appendTo: $wrapper
});
$description.html($description.html().replace('\n', '
'));
}
widgets = getValidWidgets();
if (widgets.length > 1) {
// Create widget select box
$widgetSelect = $('', {
'class': 'h5peditor-widget-select',
title: H5PEditor.t('core', 'editMode'),
appendTo: $wrapper
});
for (var i = 0; i < widgets.length; i++) {
addWidgetOption(widgets[i], i === 0);
}
// Allow custom styling when selector is present
$wrapper.addClass('h5peditor-widgets');
}
// Create inner wrapper
$inner = $('', {
'class': 'h5peditor-widget-wrapper' + (widgets.length > 1 ? ' content' : ' '),
appendTo: $wrapper
});
$content = $('', {
'class': 'h5peditor-field-content'
});
// Create errors container
$errors = $('', {
'class': 'h5p-errors'
});
// Create help text
$helpText = $('', {
'class': 'h5p-help-text'
});
};
/**
* Add widget select option.
*
* @private
*/
var addWidgetOption = function (widget, active) {
var $option = $('', {
'class': 'h5peditor-widget-option' + (active ? ' ' + CLASS_WIDGET_ACTIVE : ''),
text: widget.label,
role: 'button',
tabIndex: 1,
on: {
click: function () {
// Update UI
$widgetSelect.children('.' + CLASS_WIDGET_ACTIVE).removeClass(CLASS_WIDGET_ACTIVE);
$option.addClass(CLASS_WIDGET_ACTIVE);
// Change Widget
changeWidget(widget.name);
}
}
}).appendTo($widgetSelect);
};
/**
* Get a list of widgets that are valid and loaded.
*
* @private
* @throws {TypeError} widgets must be an array
* @returns {Array} List of valid widgets
*/
var getValidWidgets = function () {
if (field.widgets === undefined) {
// No widgets specified use default
return [defaultWidget];
}
if (!(field.widgets instanceof Array)) {
throw TypeError('widgets must be an array');
}
// Check if specified widgets are valid
var validWidgets = [];
for (var i = 0; i < field.widgets.length; i++) {
var widget = field.widgets[i];
if (getWidget(widget.name)) {
validWidgets.push(widget);
}
}
if (!validWidgets.length) {
// There are no valid widgets, add default
validWidgets.push(self.default);
}
return validWidgets;
};
/**
* Finds the widget class with the given name.
*
* @private
* @param {String} name
* @returns {Class}
*/
var getWidget = function (name) {
return H5PEditor[name];
};
/**
* Change the UI widget.
*
* @private
* @param {String} name
*/
var changeWidget = function (name) {
if (self.widget !== undefined) {
// Validate our fields first to makes sure all "stored" from their widgets
self.validate();
// Remove old widgets
self.widget.remove();
}
// TODO: Improve error handling?
var widget = getWidget(name);
self.widget = new widget(self);
self.trigger('changeWidget');
self.widget.appendTo($inner);
// Add errors container and description.
$errors.appendTo($inner);
if (self.widget.helpText !== undefined) {
$helpText.html(self.widget.helpText).appendTo($inner);
}
else {
$helpText.detach();
}
};
/**
* Appends the field widget to the given container.
*
* @public
* @param {jQuery} $container
*/
self.appendTo = function ($container) {
// Use first widget by default
changeWidget(widgets[0].name);
$wrapper.appendTo($container);
};
/**
* Remove this field and widget.
*
* @public
*/
self.remove = function () {
self.widget.remove();
$wrapper.remove();
};
/**
* Remove this field and widget.
*
* @public
* @param {String} message
*/
self.setError = function (message) {
$errors.append(H5PEditor.createError(message));
};
/**
* Clear error messages.
*
* @public
*/
self.clearErrors = function () {
$errors.html('');
};
/**
* Get the name of this field.
*
* @public
* @returns {String} Name of the current field
*/
self.getName = function () {
return field.name;
};
// Must be last
init();
}
// Extends the event dispatcher
SemanticStructure.prototype = Object.create(H5P.EventDispatcher.prototype);
SemanticStructure.prototype.constructor = SemanticStructure;
/**
* Create generic editor label.
*
* @private
* @param {String} text
* @returns {jQuery}
*/
var createLabel = function (text, optional) {
return $('', {
'class': 'h5peditor-label' + (optional ? '' : ' h5peditor-required'),
text: text
});
};
/**
* @constant
*/
var CLASS_WIDGET_ACTIVE = 'h5peditor-widget-active';
return SemanticStructure;
})(H5P.jQuery);
PK m|KLc_ c_ scripts/h5peditor.jsnu W+A /**
* This file contains helper functions for the editor.
*/
// Grab common resources set in parent window, but avoid sharing back resources set in iframe)
var ns = H5PEditor = H5P.jQuery.extend(false, {}, window.parent.H5PEditor);
ns.$ = H5P.jQuery;
// Load needed resources from parent.
H5PIntegration = H5P.jQuery.extend(false, {}, window.parent.H5PIntegration);
H5PIntegration.loadedJs = {};
H5PIntegration.loadedCss = {};
/**
* Keep track of our widgets.
*/
ns.widgets = {};
/**
* Caches library data (semantics, js and css)
*/
ns.libraryCache = {};
/**
* Keeps track of callbacks to run once a library gets loaded.
*/
ns.loadedCallbacks = {};
/**
* Keep track of which libraries have been loaded in the browser, i.e CSS is
* added and JS have been run
*
* @type {Object}
*/
ns.libraryLoaded = {};
/**
* Indiciates if the user is using Internet Explorer.
*/
ns.isIE = navigator.userAgent.match(/; MSIE \d+.\d+;/) !== null;
/**
* Helper function invoked when a library is requested. Will add CSS and eval JS
* if not already done.
*
* @private
* @param {string} libraryName On the form "machineName majorVersion.minorVersion"
* @param {Function} callback
*/
ns.libraryRequested = function (libraryName, callback) {
var libraryData = ns.libraryCache[libraryName];
if (!ns.libraryLoaded[libraryName]) {
// Add CSS.
if (libraryData.css !== undefined) {
var css = '';
for (var path in libraryData.css) {
if (!H5P.cssLoaded(path)) {
css += libraryData.css[path];
H5PIntegration.loadedCss.push(path);
}
}
if (css) {
ns.$('head').append('');
}
}
// Add JS.
if (libraryData.javascript !== undefined) {
var js = '';
for (var path in libraryData.javascript) {
if (!H5P.jsLoaded(path)) {
js += libraryData.javascript[path];
H5PIntegration.loadedJs.push(path);
}
}
if (js) {
var k = eval.apply(window, [js]);
}
}
ns.libraryLoaded[libraryName] = true;
}
callback(ns.libraryCache[libraryName].semantics);
};
/**
* Loads the given library, inserts any css and js and
* then runs the callback with the samantics as an argument.
*
* @param {string} libraryName
* On the form machineName majorVersion.minorVersion
* @param {function} callback
* @returns {undefined}
*/
ns.loadLibrary = function (libraryName, callback) {
switch (ns.libraryCache[libraryName]) {
default:
// Get semantics from cache.
ns.libraryRequested(libraryName, callback);
break;
case 0:
// Add to queue.
ns.loadedCallbacks[libraryName].push(callback);
break;
case undefined:
// Load semantics.
ns.libraryCache[libraryName] = 0; // Indicates that others should queue.
ns.loadedCallbacks[libraryName] = []; // Other callbacks to run once loaded.
var library = ns.libraryFromString(libraryName);
var url = ns.getAjaxUrl('libraries', library);
// Add content language to URL
if (ns.contentLanguage !== undefined) {
url += (url.indexOf('?') === -1 ? '?' : '&') + 'language=' + ns.contentLanguage;
}
// Fire away!
ns.$.ajax({
url: url,
success: function (libraryData) {
var semantics = libraryData.semantics;
if (libraryData.language !== null) {
var language = JSON.parse(libraryData.language);
semantics = ns.$.extend(true, [], semantics, language.semantics);
}
libraryData.semantics = semantics;
ns.libraryCache[libraryName] = libraryData;
ns.libraryRequested(libraryName, callback);
// Run queue.
for (var i = 0; i < ns.loadedCallbacks[libraryName].length; i++) {
ns.loadedCallbacks[libraryName][i](libraryData.semantics);
}
},
error: function(jqXHR, textStatus, errorThrown) {
if (window['console'] !== undefined) {
console.log('Ajax request failed');
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
}
},
dataType: 'json'
});
}
};
/**
* Reset loaded libraries - i.e removes CSS added previously.
* @method
* @return {[type]}
*/
ns.resetLoadedLibraries = function () {
ns.$('head style.h5p-editor-style').remove();
H5PIntegration.loadedCss = [];
H5PIntegration.loadedJs = [];
ns.loadedCallbacks = {};
ns.libraryLoaded = {};
}
/**
* Recursive processing of the semantics chunks.
*
* @param {array} semanticsChunk
* @param {object} params
* @param {jQuery} $wrapper
* @param {mixed} parent
* @returns {undefined}
*/
ns.processSemanticsChunk = function (semanticsChunk, params, $wrapper, parent) {
var ancestor;
parent.children = [];
if (parent.passReadies === undefined) {
throw 'Widget tried to run processSemanticsChunk without handling ready callbacks. [field:' + parent.field.type + ':' + parent.field.name + ']';
}
if (!parent.passReadies) {
// If the parent can't pass ready callbacks we need to take care of them.
parent.readies = [];
}
for (var i = 0; i < semanticsChunk.length; i++) {
var field = semanticsChunk[i];
// Check generic field properties.
if (field.name === undefined) {
throw ns.t('core', 'missingProperty', {':index': i, ':property': 'name'});
}
if (field.type === undefined) {
throw ns.t('core', 'missingProperty', {':index': i, ':property': 'type'});
}
// Set default value.
if (params[field.name] === undefined && field['default'] !== undefined) {
params[field.name] = field['default'];
}
var widget = ns.getWidgetName(field);
// TODO: Remove later, this is here for debugging purposes.
if (ns.widgets[widget] === undefined) {
$wrapper.append('[field:' + field.type + ':' + widget + ':' + field.name + ']
');
continue;
}
// Add common fields to bottom of form.
if (field.common !== undefined && field.common) {
if (ancestor === undefined) {
ancestor = ns.findAncestor(parent);
}
ns.addCommonField(field, parent, params, ancestor);
continue;
}
var fieldInstance = new ns.widgets[widget](parent, field, params[field.name], function (field, value) {
if (value === undefined) {
delete params[field.name];
}
else {
params[field.name] = value;
}
});
fieldInstance.appendTo($wrapper);
parent.children.push(fieldInstance);
}
if (!parent.passReadies) {
// Run ready callbacks.
for (var i = 0; i < parent.readies.length; i++) {
parent.readies[i]();
}
delete parent.readies;
}
};
/**
* Add a field to the common container.
*
* @param {object} field
* @param {object} parent
* @param {object} params
* @param {object} ancestor
* @returns {undefined}
*/
ns.addCommonField = function (field, parent, params, ancestor) {
var commonField;
if (ancestor.commonFields[parent.library] === undefined) {
ancestor.commonFields[parent.library] = {};
}
ancestor.commonFields[parent.library][parent.currentLibrary] =
ancestor.commonFields[parent.library][parent.currentLibrary] || {};
if (ancestor.commonFields[parent.library][parent.currentLibrary][field.name] === undefined) {
var widget = ns.getWidgetName(field);
ancestor.commonFields[parent.library][parent.currentLibrary][field.name] = {
instance: new ns.widgets[widget](parent, field, params[field.name], function (field, value) {
for (var i = 0; i < commonField.setValues.length; i++) {
commonField.setValues[i](field, value);
}
}),
setValues: [],
parents: []
};
}
commonField = ancestor.commonFields[parent.library][parent.currentLibrary][field.name];
commonField.parents.push(ns.findLibraryAncestor(parent));
commonField.setValues.push(function (field, value) {
if (value === undefined) {
delete params[field.name];
}
else {
params[field.name] = value;
}
});
if (commonField.setValues.length === 1) {
ancestor.$common.parent().removeClass('hidden');
commonField.instance.appendTo(ancestor.$common);
commonField.params = params[field.name];
}
else {
params[field.name] = commonField.params;
}
parent.children.push(commonField.instance);
};
/**
* Find the nearest library ancestor. Used when adding commonfields.
*
* @param {object} parent
* @returns {ns.findLibraryAncestor.parent|@exp;ns@call;findLibraryAncestor}
*/
ns.findLibraryAncestor = function (parent) {
if (parent.parent === undefined || parent.field.type === 'library') {
return parent;
}
return ns.findLibraryAncestor(parent.parent);
};
/**
* getParentZebra
*
* Alternate the background color of fields
*
* @param parent
* @returns {string} to determine background color of callee
*/
ns.getParentZebra = function (parent) {
if (parent.zebra) {
return parent.zebra;
}
else {
return ns.getParentZebra(parent.parent);
}
};
/**
* Find the nearest ancestor which handles commonFields.
*
* @param {type} parent
* @returns {@exp;ns@call;findAncestor|ns.findAncestor.parent}
*/
ns.findAncestor = function (parent) {
if (parent.commonFields === undefined) {
return ns.findAncestor(parent.parent);
}
return parent;
};
/**
* Call remove on the given children.
*
* @param {Array} children
* @returns {unresolved}
*/
ns.removeChildren = function (children) {
if (children === undefined) {
return;
}
for (var i = 0; i < children.length; i++) {
// Common fields will be removed by library.
var isCommonField = (children[i].field === undefined ||
children[i].field.common === undefined ||
!children[i].field.common);
var hasRemove = (children[i].remove instanceof Function ||
typeof children[i].remove === 'function');
if (isCommonField && hasRemove) {
children[i].remove();
}
}
};
/**
* Find field from path.
*
* @param {String} path
* @param {Object} parent
* @returns {@exp;ns.Form@call;findField|Boolean}
*/
ns.findField = function (path, parent) {
if (typeof path === 'string') {
path = path.split('/');
}
if (path[0] === '..') {
path.splice(0, 1);
return ns.findField(path, parent.parent);
}
if (parent.children) {
for (var i = 0; i < parent.children.length; i++) {
if (parent.children[i].field.name === path[0]) {
path.splice(0, 1);
if (path.length) {
return ns.findField(path, parent.children[i]);
}
else {
return parent.children[i];
}
}
}
}
return false;
};
/**
* Follow a field and get all changes to its params.
*
* @param {Object} parent The parent object of the field.
* @param {String} path Relative to parent object.
* @param {Function} callback Gets called for params changes.
* @returns {undefined}
*/
ns.followField = function (parent, path, callback) {
if (path === undefined) {
return;
}
// Find field when tree is ready.
parent.ready(function () {
var def;
if (path instanceof Object) {
// We have an object with default values
def = H5P.cloneObject(path);
if (path.field === undefined) {
callback(path, null);
return; // Exit if we have no field to follow.
}
path = def.field;
delete def.field;
}
var field = ns.findField(path, parent);
if (!field) {
throw ns.t('core', 'unknownFieldPath', {':path': path});
}
if (field.changes === undefined) {
throw ns.t('core', 'noFollow', {':path': path});
}
var params = (field.params === undefined ? def : field.params);
callback(params, field.changes.length + 1);
field.changes.push(function () {
var params = (field.params === undefined ? def : field.params);
callback(params);
});
});
};
/**
* Create HTML wrapper for error messages.
*
* @param {String} message
* @returns {String}
*/
ns.createError = function (message) {
return '' + message + '
';
};
/**
* Turn a numbered importance into a string.
*
* @param {string} importance
* @returns {String}
*/
ns.createImportance = function (importance) {
return importance ? 'importance-' + importance : '';
};
/**
* Create HTML wrapper for field items.
* Makes sure the different elements are placed in an consistent order.
*
* @param {string} type
* @param {string} [label]
* @param {string} [description]
* @param {string} [content]
* @deprecated since version 1.12 (Jan. 2017, will be removed Jan. 2018). Use createFieldMarkup instead.
* @see createFieldMarkup
* @returns {string} HTML
*/
ns.createItem = function (type, label, description, content) {
return '' +
(label ? label : '') +
(description ? '
' + description + '
' : '') +
(content ? content : '') +
'
' +
'
';
};
/**
* An object describing the semantics of a field
* @typedef {Object} SemanticField
* @property {string} name
* @property {string} type
* @property {string} label
* @property {string} [importance]
* @property {string} [description]
* @property {string} [widget]
* @property {boolean} [optional]
*/
/**
* Create HTML wrapper for a field item.
* Replacement for createItem()
*
* @since 1.12
* @param {SemanticField} field
* @param {string} content
*
* @return {string}
*/
ns.createFieldMarkup = function (field, content) {
content = content || '';
var markup = this.createLabel(field) + this.createDescription(field.description) + content;
return this.wrapFieldMarkup(field, markup);
};
/**
* Create HTML wrapper for a boolean field item.
*
* @param {SemanticField} field
* @param {string} content
*
* @return {string}
*/
ns.createBooleanFieldMarkup = function (field, content) {
var markup =
'' +
this.createDescription(field.description);
return this.wrapFieldMarkup(field, markup);
};
/**
* Wraps a field with some metadata classes, and adds error field
*
* @param {SemanticField} field
* @param {string} markup
*
* @private
* @return {string}
*/
ns.wrapFieldMarkup = function (field, markup) {
// removes undefined and joins
var wrapperClasses = this.joinNonEmptyStrings(['field', 'field-name-' + field.name, field.type, ns.createImportance(field.importance), field.widget]);
// wrap and return
return '';
};
/**
* Joins an array of strings if they are defined and non empty
*
* @param {string[]} arr
* @param {string} [separator] Default is space
* @return {string}
*/
ns.joinNonEmptyStrings = function (arr, separator) {
separator = separator || ' ';
return arr.filter(function (str) {
return str !== undefined && str.length > 0;
}).join(separator);
};
/**
* Create HTML for select options.
*
* @param {String} value
* @param {String} text
* @param {Boolean} selected
* @returns {String}
*/
ns.createOption = function (value, text, selected) {
return '';
};
/**
* Create HTML for text input.
*
* @param {String} value
* @param {number} maxLength
* @param {String} placeholder
*
* @returns {String}
*/
ns.createText = function (value, maxLength, placeholder) {
var html = '';
return html;
};
/**
* Create a label to wrap content in.
*
* @param {SemanticField} field
* @param {String} [content]
* @returns {String}
*/
ns.createLabel = function (field, content) {
var html = '';
};
/**
* Create a description
* @param {String} description
* @returns {string}
*/
ns.createDescription = function (description) {
var html = '';
if (description !== undefined) {
html += '' + description + '
';
}
return html;
};
/**
* Create an important description
* @param {Object} importantDescription
* @returns {String}
*/
ns.createImportantDescription = function (importantDescription) {
var html = '';
if (importantDescription !== undefined) {
html += '' +
'
' +
'
' +
'
' +
'' +
ns.t('core', 'hide') +
'' +
'
' +
'
' +
'' +
'
' +
ns.t('core', 'importantInstructions') +
'';
if (importantDescription.description !== undefined) {
html += '
' +
importantDescription.description +
'
';
}
if (importantDescription.example !== undefined) {
html += '
' +
'
' +
'' +
ns.t('core', 'example') +
':' +
'
' +
'
' +
'' +
importantDescription.example +
'' +
'
' +
'
';
}
html += '
' +
'' +
ns.t('core', 'showImportantInstructions') +
'';
}
return html;
};
/**
* Bind events to important description
* @param {Object} widget
* @param {String} fieldName
* @param {Object} parent
*/
ns.bindImportantDescriptionEvents = function (widget, fieldName, parent) {
var that = this;
var context;
if (!widget.field.important) {
return;
}
// Generate a context string for using as referance in ex. localStorage.
var librarySelector = ns.findLibraryAncestor(parent);
if (librarySelector.currentLibrary !== undefined) {
var lib = librarySelector.currentLibrary.split(' ')[0];
context = (lib + '-' + fieldName).replace(/\.|_/g,'-') + '-important-description-open';
}
var $importantField = widget.$item.find('.h5peditor-field-important-description');
// Set first occurance to visible
ns.storage.get(context, function (value) {
if (value === undefined || value === true) {
widget.$item.addClass('important-description-visible');
}
});
widget.$item.addClass('has-important-description');
// Bind events to toggle button and update aria-pressed
widget.$item.find('.important-description-show')
.click(function () {
widget.$item.addClass('important-description-visible');
ns.storage.set(context, true);
})
.keydown(function () {
if (event.which == 13 || event.which == 32) {
ns.$(this).trigger('click');
event.preventDefault();
}
});
// Bind events to close button and update aria-pressed of toggle button
widget.$item.find('.important-description-close')
.click(function () {
widget.$item.removeClass('important-description-visible');
ns.storage.set(context, false);
})
.keydown(function () {
if (event.which == 13 || event.which == 32) {
ns.$(this).trigger('click');
event.preventDefault();
}
});
};
/**
* Check if any errors has been set.
*
* @param {jQuery} $errors
* @param {jQuery} $input
* @param {String} value
* @returns {mixed}
*/
ns.checkErrors = function ($errors, $input, value) {
if ($errors.children().length) {
$input.keyup(function (event) {
if (event.keyCode === 9) { // TAB
return;
}
$errors.html('');
$input.removeClass('error');
$input.unbind('keyup');
});
return false;
}
return value;
};
/**
* @param {object} library
* with machineName, majorVersion and minorVersion params
* @returns {string}
* Concatinated version of the library
*/
ns.libraryToString = function (library) {
return library.name + ' ' + library.majorVersion + '.' + library.minorVersion;
};
/**
* TODO: Remove from here, and use from H5P instead(move this to the h5p.js...)
*
* @param {string} library
* library in the format machineName majorVersion.minorVersion
* @returns
* library as an object with machineName, majorVersion and minorVersion properties
* return false if the library parameter is invalid
*/
ns.libraryFromString = function (library) {
var regExp = /(.+)\s(\d+)\.(\d+)$/g;
var res = regExp.exec(library);
if (res !== null) {
return {
'machineName': res[1],
'majorVersion': res[2],
'minorVersion': res[3]
};
}
else {
H5P.error('Invalid überName');
return false;
}
};
/**
* Helper function for detecting field widget.
*
* @param {Object} field
* @returns {String} Widget name
*/
ns.getWidgetName = function (field) {
return (field.widget === undefined ? field.type : field.widget);
};
/**
* Mimics how php's htmlspecialchars works (the way we uses it)
*/
ns.htmlspecialchars = function(string) {
return string.toString().replace(//g, '>').replace(/'/g, ''').replace(/"/g, '"');
};
/**
* Makes it easier to add consistent buttons across the editor widget.
*
* @param {string} id Typical CSS class format
* @param {string} title Human readable format
* @param {function} handler Action handler when triggered
* @param {boolean} [displayTitle=false] Show button with text
* @return {H5P.jQuery}
*/
ns.createButton = function (id, title, handler, displayTitle) {
var options = {
class: 'h5peditor-button ' + (displayTitle ? 'h5peditor-button-textual ' : '') + id,
role: 'button',
tabIndex: 0,
'aria-disabled': 'false',
on: {
click: function (event) {
handler.call(this);
},
keydown: function (event) {
switch (event.which) {
case 13: // Enter
case 32: // Space
handler.call(this);
event.preventDefault();
}
}
}
};
// Determine if we're a icon only button or have a textual label
options[displayTitle ? 'html' : 'aria-label'] = title;
return ns.$('', options);
};
// Factory for creating storage instance
ns.storage = (function () {
var instance = {
get: function (key, next) {
var value;
// Get value from browser storage
if (window.localStorage !== undefined) {
value = !!window.localStorage.getItem(key);
}
// Try to get a better value from user data storage
try {
H5P.getUserData(0, key, function (err, result) {
if (!err) {
value = result;
}
next(value);
});
}
catch (err) {
next(value);
}
},
set: function (key, value) {
// Store in browser
if (window.localStorage !== undefined) {
window.localStorage.setItem(key, value);
}
// Try to store in user data storage
try {
H5P.setUserData(0, key, value);
}
catch (err) {}
},
};
return instance;
})();
PK m|K2#52 2 scripts/h5peditor-image.jsnu W+A /*global H5P*/
var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Adds an image upload field with image editing tool to the form.
*
* @param {Object} parent Parent widget of this widget
* @param {Object} field Semantic fields
* @param {Object} params Existing image parameters
* @param {function} setValue Function for updating parameters
* @returns {ns.widgets.image}
*/
ns.widgets.image = function (parent, field, params, setValue) {
var self = this;
// Initialize inheritance
ns.File.call(self, parent, field, params, setValue);
this.parent = parent;
this.field = field;
this.params = params;
this.setValue = setValue;
this.library = parent.library + '/' + field.name;
if (params !== undefined) {
this.copyright = params.copyright;
}
// Keep track of editing image
this.isEditing = false;
// Keep track of type of image that is being uploaded
this.isOriginalImage = false;
this.changes = [];
this.passReadies = true;
parent.ready(function () {
self.passReadies = false;
});
this.confirmationDialog = new H5P.ConfirmationDialog({
headerText: H5PEditor.t('core', 'removeImage'),
bodyText: H5PEditor.t('core', 'confirmImageRemoval')
});
this.confirmationDialog.on('confirmed', function () {
self.removeImage();
});
// When uploading starts
self.on('upload', function () {
// Hide edit image button
self.$editImage.addClass('hidden');
if (!self.isUploadingData()) {
// Uploading new original image
self.isOriginalImage = true;
}
});
// When a new file has been uploaded
self.on('fileUploaded', function (event) {
// Uploaded new original image
if (self.isOriginalImage) {
self.isOriginalImage = false;
delete self.params.originalImage;
}
// Store width and height
self.params.width = event.data.width;
self.params.height = event.data.height;
// Show edit image button
self.$editImage.removeClass('hidden');
self.isEditing = false;
});
};
ns.widgets.image.prototype = Object.create(ns.File.prototype);
ns.widgets.image.prototype.constructor = ns.widgets.image;
/**
* Append field to the given wrapper.
*
* @param {jQuery} $wrapper
*/
ns.widgets.image.prototype.appendTo = function ($wrapper) {
var self = this;
var htmlString = '' +
'' +
'' +
'' +
'
' +
'';
var html = ns.createFieldMarkup(this.field, htmlString);
var $container = ns.$(html).appendTo($wrapper);
this.$editImage = $container.find('.h5p-editing-image-button');
this.$copyrightButton = $container.find('.h5p-copyright-button');
this.$file = $container.find('.file');
this.$errors = $container.find('.h5p-errors');
this.addFile();
var $dialog = $container.find('.h5p-editor-dialog');
$container.find('.h5p-copyright-button').add($dialog.find('.h5p-close')).click(function () {
$dialog.toggleClass('h5p-open');
return false;
});
var editImagePopup = new H5PEditor.ImageEditingPopup(this.field.ratio);
editImagePopup.on('savedImage', function (e) {
// Not editing any longer
self.isEditing = false;
// No longer an original image
self.isOriginalImage = false;
// Set current source as original image, if no original image
if (!self.params.originalImage) {
self.params.originalImage = {
path: self.params.path,
mime: self.params.mime,
height: self.params.height,
width: self.params.width
};
}
// Upload new image
self.uploadData(e.data);
});
editImagePopup.on('resetImage', function () {
var imagePath = self.params.originalImage ? self.params.originalImage.path
: self.params.path;
var imageSrc = H5P.getPath(imagePath, H5PEditor.contentId);
editImagePopup.setImage(imageSrc);
});
editImagePopup.on('canceled', function () {
self.isEditing = false;
});
editImagePopup.on('initialized', function () {
// Remove throbber from image
self.$editImage.removeClass('loading');
});
$container.find('.h5p-editing-image-button').click(function () {
if (self.params && self.params.path) {
var imageSrc;
if (!self.isEditing) {
imageSrc = H5P.getPath(self.params.path, H5PEditor.contentId);
self.isEditing = true;
}
self.$editImage.toggleClass('loading');
// Add throbber to image
editImagePopup.show(ns.$(this).offset(), imageSrc);
}
});
ns.File.addCopyright(self, $dialog, function (field, value) {
if (self.params !== undefined) {
self.params.copyright = value;
}
self.copyright = value;
});
};
/**
* Sync copyright.
*/
ns.widgets.image.prototype.setCopyright = function (value) {
this.copyright = this.params.copyright = value;
};
/**
* Creates thumbnail HTML and actions.
*
* @returns {boolean} True if file was added, false if file was removed
*/
ns.widgets.image.prototype.addFile = function () {
var that = this;
if (this.params === undefined) {
// No image look
this.$file
.html(
'' +
'' + ns.t('core', 'add') + '
' +
''
)
.children('.add')
.click(function () {
that.openFileSelector();
return false;
});
// Remove edit image button
this.$editImage.addClass('hidden');
this.$copyrightButton.addClass('hidden');
this.isEditing = false;
return false;
}
var source = H5P.getPath(this.params.path, H5PEditor.contentId);
var altText = (this.field.label === undefined ? '' : this.field.label);
var fileHtmlString =
'' +
'' +
'' +
'';
this.$file.html(fileHtmlString)
.children(':eq(0)')
.click(function () {
that.openFileSelector();
return false;
})
.children('img')
.attr('src', source)
.end()
.next()
.click(function () {
that.confirmRemovalDialog.show(that.$file.offset().top);
return false;
});
// Uploading original image
that.$editImage.removeClass('hidden');
that.$copyrightButton.removeClass('hidden');
// Notify listeners that image was changed to params
that.trigger('changedImage', this.params);
return true;
};
/**
* Remove image
*/
ns.widgets.image.prototype.removeImage = function () {
// Notify listeners that we removed image with params
this.trigger('removedImage', this.params);
delete this.params;
this.setValue(this.field);
this.addFile();
for (var i = 0; i < this.changes.length; i++) {
this.changes[i]();
}
};
/**
* Validate this item
*/
ns.widgets.image.prototype.validate = function () {
return true;
};
/**
* Remove this item.
*/
ns.widgets.image.prototype.remove = function () {
// TODO: Check what happens when removed during upload.
this.$file.parent().remove();
};
/**
* Collect functions to execute once the tree is complete.
*
* @param {function} ready
*/
ns.widgets.image.prototype.ready = function (ready) {
if (this.passReadies) {
this.parent.ready(ready);
}
else {
ready();
}
};
PK m|K[y y scripts/h5peditor-init.jsnu W+A //var H5PEditor = (H5PEditor || {});
(function ($, ns) {
H5PEditor.init = function ($form, $type, $upload, $create, $editor, $library, $params) {
H5PEditor.$ = H5P.jQuery;
H5PEditor.basePath = H5PIntegration.editor.libraryUrl;
H5PEditor.fileIcon = H5PIntegration.editor.fileIcon;
H5PEditor.ajaxPath = H5PIntegration.editor.ajaxPath;
H5PEditor.filesPath = H5PIntegration.editor.filesPath;
H5PEditor.apiVersion = H5PIntegration.editor.apiVersion;
// Semantics describing what copyright information can be stored for media.
H5PEditor.copyrightSemantics = H5PIntegration.editor.copyrightSemantics;
// Required styles and scripts for the editor
H5PEditor.assets = H5PIntegration.editor.assets;
// Required for assets
H5PEditor.baseUrl = '';
if (H5PIntegration.editor.nodeVersionId !== undefined) {
H5PEditor.contentId = H5PIntegration.editor.nodeVersionId;
}
var h5peditor;
$create.hide();
var library = $library.val();
$type.change(function () {
if ($type.filter(':checked').val() === 'upload') {
$create.hide();
$upload.show();
}
else {
$upload.hide();
if (h5peditor === undefined) {
h5peditor = new ns.Editor(library, $params.val(), $editor[0]);
}
$create.show();
}
});
if ($type.filter(':checked').val() === 'upload') {
$type.change();
}
else {
$type.filter('input[value="create"]').attr('checked', true).change();
}
$form.submit(function () {
if (h5peditor !== undefined) {
var params = h5peditor.getParams();
if (params !== undefined) {
$library.val(h5peditor.getLibrary());
$params.val(JSON.stringify(params));
}
}
});
};
H5PEditor.getAjaxUrl = function (action, parameters) {
var url = H5PIntegration.editor.ajaxPath + action;
if (parameters !== undefined) {
for (var property in parameters) {
if (parameters.hasOwnProperty(property)) {
url += '&' + property + '=' + parameters[property];
}
}
}
return url;
};
})(H5P.jQuery, H5PEditor);
PK m|K_C ! scripts/h5peditor-selector-hub.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* @class
* @alias H5PEditor.SelectorHub
*/
ns.SelectorHub = function (libraries, selectedLibrary, changeLibraryDialog) {
var self = this;
H5P.EventDispatcher.call(this);
/**
* Looks up content type object
*
* @param {string} machineName
* @return {object}
*/
this.getContentType = function (machineName) {
for (var i = 0; i < libraries.libraries.length; i++) {
var contentType = libraries.libraries[i];
if (contentType.machineName === machineName) {
return contentType;
}
}
};
var state = {
contentId: H5PEditor.contentId || 0,
contentTypes: libraries,
getAjaxUrl: H5PEditor.getAjaxUrl
};
if (selectedLibrary) {
var contentType = this.getContentType(selectedLibrary.split(' ')[0]);
state.title = contentType ? contentType.title || contentType.machineName : selectedLibrary.split(' ')[0];
}
// Initialize hub client
this.client = new H5P.HubClient(state, H5PEditor.language.core);
// Default to nothing selected and empty params
this.currentLibrary = selectedLibrary;
// Listen for content type selection
this.client.on('select', function (event) {
var contentType = event;
// Already selected library
if (contentType.machineName === self.currentLibrary.split(' ')[0]) {
return;
}
if (!self.currentLibrary) {
self.currentLibrary = self.createContentTypeId(contentType, true);
self.trigger('selected');
return;
}
self.currentLibrary = self.createContentTypeId(contentType, true);
delete self.currentParams;
changeLibraryDialog.show(ns.$(self.getElement()).offset().top);
}, this);
// Listen for uploads
this.client.on('upload', function (event) {
libraries = event.contentTypes;
var previousLibrary = self.currentLibrary;
// Use version from event data
const uploadedVersion = event.h5p.preloadedDependencies
.filter(function (dependency) {
return dependency.machineName === event.h5p.mainLibrary;
});
self.currentLibrary = self.createContentTypeId(uploadedVersion[0]);
self.currentParams = event.content;
// Change library immediately or show confirmation dialog
if (!previousLibrary) {
self.trigger('selected');
}
else {
changeLibraryDialog.show(ns.$(self.getElement()).offset().top);
}
}, this);
this.client.on('update', function (event) {
// Handle update to the content type cache
libraries = event;
});
this.client.on('resize', function () {
self.trigger('resize');
});
};
// Extends the event dispatcher
ns.SelectorHub.prototype = Object.create(H5P.EventDispatcher.prototype);
ns.SelectorHub.prototype.constructor = ns.SelectorHub;
/**
* Reset current library to the provided library.
*
* @param {string} library Full library name
* @param {Object} params Library parameters
*/
ns.SelectorHub.prototype.resetSelection = function (library, params) {
this.currentLibrary = library;
this.currentParams = params;
var contentType = this.getContentType(library.split(' ')[0]);
this.client.setPanelTitle(contentType.title || contentType.machineName);
};
/**
* Get currently selected library
*
* @param {function} next Callback
*/
ns.SelectorHub.prototype.getSelectedLibrary = function (next) {
var selected = {
uberName: this.currentLibrary
};
var contentType = this.getContentType(this.currentLibrary.split(' ')[0]);
if (contentType) {
selected.tutorialUrl = contentType.tutorial;
selected.exampleUrl = contentType.example;
}
return next(selected);
};
/**
* Get params connected with the currently selected library
*
* @returns {string} Parameters connected to the selected library
*/
ns.SelectorHub.prototype.getParams = function () {
return this.currentParams;
};
/**
* Returns the html element for the hub
*
* @public
* @return {HTMLElement}
*/
ns.SelectorHub.prototype.getElement = function(){
return this.client.getElement();
};
/**
* Takes a content type, and extracts the full id (ubername)
*
* @param {ContentType} contentType
* @param {boolean} [useLocalVersion] Decides if we should use local version or cached version
*
* @private
* @return {string}
*/
ns.SelectorHub.prototype.createContentTypeId = function (contentType, useLocalVersion) {
var id = contentType.machineName;
if (useLocalVersion) {
id += ' ' + contentType.localMajorVersion + '.' + contentType.localMinorVersion;
}
else {
id += ' ' + contentType.majorVersion + '.' + contentType.minorVersion;
}
return id;
};
PK m|Ktg g $ scripts/h5peditor-selector-legacy.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* @class
* @alias H5PEditor.SelectorLegacy
*/
ns.SelectorLegacy = function (libraries, selectedLibrary, changeLibraryDialog) {
var self = this;
H5P.EventDispatcher.call(this);
var defaultLibraryParameterized = selectedLibrary ? selectedLibrary.replace('.', '-').toLowerCase() : undefined;
this.currentLibrary = selectedLibrary;
var options = '';
for (var i = 0; i < libraries.length; i++) {
var library = libraries[i];
var libraryName = ns.libraryToString(library);
// Never deny editing existing content
// For new content deny old or restricted libs.
if (selectedLibrary === libraryName ||
((library.restricted === undefined || !library.restricted) &&
library.isOld !== true
)
) {
options += '';
}
}
this.$selector = ns.$('' +
''
).change(function () {
// Use timeout to avoid bug in Chrome >44, when confirm is used inside change event.
// Ref. https://code.google.com/p/chromium/issues/detail?id=525629
setTimeout(function () {
if (!self.currentLibrary) {
self.currentLibrary = self.$selector.val();
self.trigger('selected');
return;
}
self.currentLibrary = self.$selector.val();
changeLibraryDialog.show(self.$selector.offset().top);
}, 0);
});
};
/**
* Reset selector to provided library
*
* @param {string} library
*/
ns.SelectorLegacy.prototype.resetSelection = function (library) {
this.$selector.val(library);
}
/**
* Get currently selected library.
*
* @returns {string}
*/
ns.SelectorLegacy.prototype.getSelectedLibrary = function (next) {
var that = this;
var $option = this.$selector.find(':selected');
next({
uberName: that.currentLibrary,
tutorialUrl: $option.data('tutorial-url'),
exampleUrl: $option.data('example-url')
});
}
/**
* Not possible to load new params into legacy selector, always returns undefined.
*
* @returns {undefined}
*/
ns.SelectorLegacy.prototype.getParams = function () {
return undefined;
}
/**
* Returns the html element for the hub
*
* @return {HTMLElement}
*/
ns.SelectorLegacy.prototype.getElement = function(){
return this.$selector.get(0);
};
PK m|K
~: : ' scripts/h5peditor-library-list-cache.jsnu W+A /** @namespace H5PEditor */
var H5PEditor = H5PEditor || {};
/**
* The library list cache
*
* @type Object
*/
var llc = H5PEditor.LibraryListCache = {
libraryCache: {},
librariesComingIn: {},
librariesMissing: {},
que: []
};
/**
* Get data for a list of libraries
*
* @param {Array} libraries - list of libraries to load info for (uber names)
* @param {Function} handler - Callback when list of libraries is loaded
* @param {Function} thisArg - Context for the callback function
*/
llc.getLibraries = function(libraries, handler, thisArg) {
var cachedLibraries = [];
var status = 'hasAll';
for (var i = 0; i < libraries.length; i++) {
if (libraries[i] in llc.libraryCache) {
// Libraries that are missing on the server are set to null...
if (llc.libraryCache[libraries[i]] !== null) {
cachedLibraries.push(llc.libraryCache[libraries[i]]);
}
}
else if (libraries[i] in llc.librariesComingIn) {
if (status === 'hasAll') {
status = 'onTheWay';
}
}
else {
status = 'requestThem';
llc.librariesComingIn[libraries[i]] = true;
}
}
switch (status) {
case 'hasAll':
handler.call(thisArg, cachedLibraries);
break;
case 'onTheWay':
llc.que.push({libraries: libraries, handler: handler, thisArg: thisArg});
break;
case 'requestThem':
var ajaxParams = {
type: "POST",
url: H5PEditor.getAjaxUrl('libraries'),
success: function(data) {
llc.setLibraries(data, libraries);
handler.call(thisArg, data);
llc.runQue();
},
data: {
'libraries': libraries
},
dataType: "json"
};
H5PEditor.$.ajax(ajaxParams);
break;
}
};
/**
* Call all qued handlers
*/
llc.runQue = function() {
var l = llc.que.length;
for (var i = 0; i < l; i++) {
var handlerObject = llc.que.shift();
llc.getLibraries(handlerObject.libraries, handlerObject.handler, handlerObject.thisArg);
}
};
/**
* We've got new libraries from the server, save them
*
* @param {Array} libraries - Libraries with info from server
* @param {Array} requestedLibraries - List of what libraries we requested
*/
llc.setLibraries = function(libraries, requestedLibraries) {
var reqLibraries = requestedLibraries.slice();
for (var i = 0; i < libraries.length; i++) {
llc.libraryCache[libraries[i].uberName] = libraries[i];
if (libraries[i].uberName in llc.librariesComingIn) {
delete llc.librariesComingIn[libraries[i].uberName];
}
var index = reqLibraries.indexOf(libraries[i].uberName);
if (index > -1) {
reqLibraries.splice(index, 1);
}
}
for (var i = 0; i < reqLibraries.length; i++) {
llc.libraryCache[reqLibraries[i]] = null;
if (reqLibraries[i] in llc.librariesComingIn) {
delete llc.librariesComingIn[libraries[i]];
}
}
};
PK m|K" " scripts/h5peditor-library.jsnu W+A var H5PEditor = (H5PEditor || {});
var ns = H5PEditor;
/**
* Callback for setting new parameters.
*
* @callback H5PEditor.newParams
* @param {Object} field Current field details.
* @param {Object} params New parameters.
*/
/**
* Create a field where one can select and include another library to the form.
*
* @class H5PEditor.Library
* @extends H5P.EventDispatcher
* @param {Object} parent Parent field in editor.
* @param {Object} field Details for current field.
* @param {Object} params Default parameters.
* @param {newParams} setValue Callback for setting new parameters.
*/
ns.Library = function (parent, field, params, setValue) {
var self = this;
H5P.EventDispatcher.call(this);
if (params === undefined) {
this.params = {
params: {}
};
// If you do a console log here it might show that this.params is
// something else than what we set it to. One of life's big mysteries...
setValue(field, this.params);
} else {
this.params = params;
}
this.field = field;
this.parent = parent;
this.changes = [];
this.optionsLoaded = false;
this.library = parent.library + '/' + field.name;
this.passReadies = true;
parent.ready(function () {
self.passReadies = false;
});
// Confirmation dialog for changing library
this.confirmChangeLibrary = new H5P.ConfirmationDialog({
headerText: H5PEditor.t('core', 'changeLibrary'),
dialogText: H5PEditor.t('core', 'confirmChangeLibrary')
}).appendTo(document.body);
// Load library on confirmation
this.confirmChangeLibrary.on('confirmed', function () {
self.loadLibrary(self.$select.val());
});
// Revert to current library on cancel
this.confirmChangeLibrary.on('canceled', function () {
self.$select.val(self.currentLibrary);
});
};
ns.Library.prototype = Object.create(H5P.EventDispatcher.prototype);
ns.Library.prototype.constructor = ns.Library;
/**
* Append the library selector to the form.
*
* @alias H5PEditor.Library#appendTo
* @param {H5P.jQuery} $wrapper
*/
ns.Library.prototype.appendTo = function ($wrapper) {
var that = this;
var html = '';
if (this.field.label !== 0) {
html = '';
}
html += ns.createDescription(this.field.description);
html = '' + html + '
';
// TODO: Remove errors, it is deprecated
html += '
';
this.$myField = ns.$(html).appendTo($wrapper);
this.$select = this.$myField.children('select');
this.$libraryWrapper = this.$myField.children('.libwrap');
ns.LibraryListCache.getLibraries(that.field.options, that.librariesLoaded, that);
};
/**
* Handler for when the library list has been loaded
*
* @alias H5PEditor.Library#librariesLoaded
* @param {Array} libList
*/
ns.Library.prototype.librariesLoaded = function (libList) {
this.libraries = libList;
var self = this;
var options = ns.createOption('-', '-');
for (var i = 0; i < self.libraries.length; i++) {
var library = self.libraries[i];
if (library.uberName === self.params.library ||
(library.title !== undefined && (library.restricted === undefined || !library.restricted))) {
options += ns.createOption(library.uberName, library.title, library.uberName === self.params.library);
}
}
self.$select.html(options).change(function () {
// Use timeout to avoid bug in Chrome >44, when confirm is used inside change event.
// Ref. https://code.google.com/p/chromium/issues/detail?id=525629
setTimeout(function () {
// Check if library is selected
if (self.params.library) {
// Confirm changing library
self.confirmChangeLibrary.show(self.$select.offset().top);
} else {
// Load new library
self.loadLibrary(self.$select.val());
}
}, 0);
});
if (self.libraries.length === 1) {
self.$select.hide();
self.$myField.children('.h5peditor-label').hide();
self.loadLibrary(self.$select.children(':last').val(), true);
}
if (self.runChangeCallback === true) {
// In case a library has been selected programmatically trigger change events, e.g. a default library.
self.change();
self.runChangeCallback = false;
}
// Load default library.
if (this.params.library !== undefined) {
self.loadLibrary(this.params.library, true);
}
};
/**
* Load the selected library.
*
* @alias H5PEditor.Library#loadLibrary
* @param {string} libraryName On the form machineName.majorVersion.minorVersion
* @param {boolean} [preserveParams]
*/
ns.Library.prototype.loadLibrary = function (libraryName, preserveParams) {
var that = this;
this.removeChildren();
if (libraryName === '-') {
delete this.params.library;
delete this.params.params;
delete this.params.subContentId;
this.$libraryWrapper.attr('class', 'libwrap');
return;
}
this.$libraryWrapper.html(ns.t('core', 'loading')).attr('class', 'libwrap ' + libraryName.split(' ')[0].toLowerCase().replace('.', '-') + '-editor');
ns.loadLibrary(libraryName, function (semantics) {
that.currentLibrary = libraryName;
that.params.library = libraryName;
if (preserveParams === undefined || !preserveParams) {
// Reset params
that.params.params = {};
}
if (that.params.subContentId === undefined) {
that.params.subContentId = H5P.createUUID();
}
ns.processSemanticsChunk(semantics, that.params.params, that.$libraryWrapper.html(''), that);
if (that.libraries !== undefined) {
that.change();
}
else {
that.runChangeCallback = true;
}
});
};
/**
* Add the given callback or run it.
*
* @alias H5PEditor.Library#change
* @param {Function} callback
*/
ns.Library.prototype.change = function (callback) {
if (callback !== undefined) {
// Add callback
this.changes.push(callback);
}
else {
// Find library
var library, i;
for (i = 0; i < this.libraries.length; i++) {
if (this.libraries[i].uberName === this.currentLibrary) {
library = this.libraries[i];
break;
}
}
// Run callbacks
for (i = 0; i < this.changes.length; i++) {
this.changes[i](library);
}
}
};
/**
* Validate this field and its children.
*
* @alias H5PEditor.Library#validate
* @returns {boolean}
*/
ns.Library.prototype.validate = function () {
var valid = true;
if (this.children) {
for (var i = 0; i < this.children.length; i++) {
if (this.children[i].validate() === false) {
valid = false;
}
}
}
else if (this.libraries && this.libraries.length) {
valid = false;
}
return (this.field.optional ? true : valid);
};
/**
* Collect functions to execute once the tree is complete.
*
* @alias H5PEditor.Library#ready
* @param {Function} ready
*/
ns.Library.prototype.ready = function (ready) {
if (this.passReadies) {
this.parent.ready(ready);
}
else {
this.readies.push(ready);
}
};
/**
* Custom remove children that supports common fields.
*
* * @alias H5PEditor.Library#removeChildren
*/
ns.Library.prototype.removeChildren = function () {
if (this.currentLibrary === '-' || this.children === undefined) {
return;
}
var ancestor = ns.findAncestor(this.parent);
for (var libraryPath in ancestor.commonFields) {
var library = libraryPath.split('/')[0];
if (library === this.currentLibrary) {
var remove = false;
for (var fieldName in ancestor.commonFields[libraryPath]) {
var field = ancestor.commonFields[libraryPath][fieldName];
if (field.parents.length === 1) {
field.instance.remove();
remove = true;
}
for (var i = 0; i < field.parents.length; i++) {
if (field.parents[i] === this) {
field.parents.splice(i, 1);
field.setValues.splice(i, 1);
}
}
}
if (remove) {
delete ancestor.commonFields[libraryPath];
}
}
}
ns.removeChildren(this.children);
};
/**
* Allows ancestors and widgets to do stuff with our children.
*
* @alias H5PEditor.Library#forEachChild
* @param {Function} task
*/
ns.Library.prototype.forEachChild = function (task) {
for (var i = 0; i < this.children.length; i++) {
if (task(this.children[i], i)) {
return;
}
}
};
/**
* Called when this item is being removed.
*
* @alias H5PEditor.Library#remove
*/
ns.Library.prototype.remove = function () {
this.removeChildren();
if (this.$select !== undefined) {
this.$select.parent().remove();
}
};
// Tell the editor what widget we are.
ns.widgets.library = ns.Library;
PK m|K{ scripts/h5peditor-none.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Create a field without html
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
*/
ns.None = function (parent, field, params, setValue) {
this.parent = parent;
this.field = field;
this.params = params;
this.setValue = setValue;
};
/**
* Implementation of appendTo
*
* None doesn't append anything
*
* @param {jQuery} $wrapper
*/
ns.None.prototype.appendTo = function ($wrapper) {};
/**
* Implementation of validate
*
* None allways validates
*/
ns.None.prototype.validate = function () {
return true;
};
/**
* Collect functions to execute once the tree is complete.
*
* @param {function} ready
*/
ns.None.prototype.ready = function (ready) {
this.parent.ready(ready);
};
/**
* Remove this item.
*/
ns.None.prototype.remove = function () {
ns.removeChildren(this.children);
};
// Tell the editor what widget we are.
ns.widgets.none = ns.None;PK m|KdA$ A$ scripts/h5peditor-list.jsnu W+A /** @namespace H5PEditor */
var H5PEditor = H5PEditor || {};
H5PEditor.List = (function ($) {
/**
* List structure.
*
* @class
* @param {*} parent structure
* @param {Object} field Semantic description of field
* @param {Array} [parameters] Default parameters for this field
* @param {Function} setValue Call to set our parameters
*/
function List(parent, field, parameters, setValue) {
var self = this;
// Initialize semantics structure inheritance
H5PEditor.SemanticStructure.call(self, field, {
name: 'ListEditor',
label: H5PEditor.t('core', 'listLabel')
});
// Make it possible to travel up tree.
self.parent = parent; // (Could this be done a better way in the future?)
/**
* Keep track of child fields. Should not be exposed directly,
* create functions for using or finding the children.
*
* @private
* @type {Array}
*/
var children = [];
// Prepare the old ready callback system
var readyCallbacks = [];
var passReadyCallbacks = true;
parent.ready(function () {
passReadyCallbacks = false;
}); // (In the future we should use the event system for this, i.e. self.once('ready'))
// Listen for widget changes
self.on('changeWidget', function () {
// Append all items to new widget
for (var i = 0; i < children.length; i++) {
self.widget.addItem(children[i], i);
}
});
/**
* Add all items to list without appending to DOM.
*
* @public
*/
var init = function () {
var i;
if (parameters !== undefined && parameters.length) {
for (i = 0; i < parameters.length; i++) {
if (parameters[i] === null) {
parameters[i] = undefined;
}
addItem(i);
}
}
else {
if (field.defaultNum === undefined) {
// Use min or 1 if no default item number is set.
field.defaultNum = (field.min !== undefined ? field.min : 1);
}
// Add default number of fields.
for (i = 0; i < field.defaultNum; i++) {
addItem(i);
}
}
};
/**
* Make sure list is created when setting a parameter.
*
* @private
* @param {number} index
* @param {*} value
*/
var setParameters = function (index, value) {
if (parameters === undefined) {
// Create new parameters for list
parameters = [];
setValue(field, parameters);
}
parameters[index] = value;
};
/**
* Add item to list.
*
* @private
* @param {Number} index
* @param {*} [paramsOverride] Override params using this value.
*/
var addItem = function (index, paramsOverride) {
var childField = field.field;
var widget = H5PEditor.getWidgetName(childField);
if ((parameters === undefined || parameters[index] === undefined) && childField['default'] !== undefined) {
// Use default value
setParameters(index, childField['default']);
}
if (paramsOverride !== undefined) {
// Use override params
setParameters(index, paramsOverride);
}
var child = children[index] = new H5PEditor.widgets[widget](self, childField, parameters === undefined ? undefined : parameters[index], function (myChildField, value) {
var i = findIndex(child);
setParameters(i === undefined ? index : i, value);
});
return child;
};
/**
* Finds the index for the given child.
*
* @private
* @param {Object} child field instance
* @returns {Number} index
*/
var findIndex = function (child) {
for (var i = 0; i < children.length; i++) {
if (children[i] === child) {
return i;
}
}
};
/**
* Get the singular form of the items added in the list.
*
* @public
* @returns {String} The entity type
*/
self.getEntity = function () {
return (field.entity === undefined ? 'item' : field.entity);
};
/**
* Adds a new list item and child field at the end of the list
*
* @public
* @param {*} [paramsOverride] Override params using this value.
* @returns {Boolean}
*/
self.addItem = function (paramsOverride) {
var id = children.length;
if (field.max === id) {
return false;
}
var child = addItem(id, paramsOverride);
self.widget.addItem(child, id);
if (!passReadyCallbacks) {
// Run collected ready callbacks
for (var i = 0; i < readyCallbacks.length; i++) {
readyCallbacks[i]();
}
readyCallbacks = []; // Reset
}
return true;
};
/**
* Removes the list item at the given index.
*
* @public
* @param {Number} index
*/
self.removeItem = function (index) {
// Remove child field
children[index].remove();
children.splice(index, 1);
if (parameters !== undefined) {
// Clean up parameters
parameters.splice(index, 1);
if (!parameters.length) {
// Create new parameters for list
parameters = undefined;
setValue(field);
}
}
};
/**
* Removes all items.
* This is useful if a widget wants to reset the list.
*
* @public
*/
self.removeAllItems = function () {
if (parameters === undefined) {
return;
}
// Remove child fields
for (var i = 0; i < children.length; i++) {
children[i].remove();
}
children = [];
// Clean up parameters
parameters = undefined;
setValue(field);
};
/**
* Change the order of the items in the list.
* Be aware that this may change the index of other existing items.
*
* @public
* @param {Number} currentIndex
* @param {Number} newIndex
*/
self.moveItem = function (currentIndex, newIndex) {
// Update child fields
var child = children.splice(currentIndex, 1);
children.splice(newIndex, 0, child[0]);
// Update parameters
if (parameters) {
var params = parameters.splice(currentIndex, 1);
parameters.splice(newIndex, 0, params[0]);
}
};
/**
* Allows ancestors and widgets to do stuff with our children.
*
* @public
* @param {Function} task
*/
self.forEachChild = function (task) {
for (var i = 0; i < children.length; i++) {
task(children[i], i);
}
};
/**
* Collect callback to run when the editor is ready. If this item isn't
* ready yet, jusy pass them on to the parent item.
*
* @public
* @param {Function} ready
*/
self.ready = function (ready) {
if (passReadyCallbacks) {
parent.ready(ready);
}
else {
readyCallbacks.push(ready);
}
};
/**
* Make sure that this field and all child fields are valid.
*
* @public
* @returns {Boolean}
*/
self.validate = function () {
var self = this;
var valid = true;
// Remove old error messages
self.clearErrors();
// Make sure child fields are valid
for (var i = 0; i < children.length; i++) {
if (children[i].validate() === false) {
valid = false;
}
}
// Validate our self
if (field.max !== undefined && field.max > 0 &&
children !== undefined && children.length > field.max) {
// Invalid, more parameters than max allowed.
valid = false;
self.setError(H5PEditor.t('core', 'listExceedsMax', {':max': field.max}));
}
if (field.min !== undefined && field.min > 0 &&
(children === undefined || children.length < field.min)) {
// Invalid, less parameters than min allowed.
valid = false;
self.setError(H5PEditor.t('core', 'listBelowMin', {':min': field.min}));
}
return valid;
};
self.getImportance = function () {
if (field.importance !== undefined) {
return H5PEditor.createImportance(field.importance);
}
else if (field.field.importance !== undefined) {
return H5PEditor.createImportance(field.field.importance);
}
else {
return '';
}
};
/**
* Creates a copy of the current valid value. A copy is created to avoid
* mistakes like directly editing the parameter values, which will cause
* inconsistencies between the parameters and the editor widgets.
*
* @public
* @returns {Array}
*/
self.getValue = function () {
return (parameters === undefined ? parameters : $.extend(true, [], parameters));
};
/**
* Get a copy of the field semantics used by this list to create rows.
* @return {Object}
*/
self.getField = function () {
return $.extend(true, {}, field.field);
};
// Start the party!
init();
}
// Extends the semantics structure
List.prototype = Object.create(H5PEditor.SemanticStructure.prototype);
List.prototype.constructor = List;
return List;
})(H5P.jQuery);
// Register widget
H5PEditor.widgets.list = H5PEditor.List;
PK m|K'6 6 scripts/h5peditor-av.jsnu W+A var H5PEditor = H5PEditor || {};
/**
* Audio/Video module.
* Makes it possible to add audio or video through file uploads and urls.
*
*/
H5PEditor.widgets.video = H5PEditor.widgets.audio = H5PEditor.AV = (function ($) {
/**
* Constructor.
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
* @returns {_L3.C}
*/
function C(parent, field, params, setValue) {
var self = this;
// Initialize inheritance
H5PEditor.FileUploader.call(self, field);
this.parent = parent;
this.field = field;
this.params = params;
this.setValue = setValue;
this.changes = [];
if (params !== undefined && params[0] !== undefined) {
this.setCopyright(params[0].copyright);
}
// When uploading starts
self.on('upload', function () {
// Insert throbber
self.$uploading = $('' + H5PEditor.t('core', 'uploading') + '
').insertAfter(self.$add.hide());
// Clear old error messages
self.$errors.html('');
// Close dialog
self.$addDialog.removeClass('h5p-open');
});
// Handle upload complete
self.on('uploadComplete', function (event) {
var result = event.data;
// Clear out add dialog
this.$addDialog.find('.h5p-file-url').val('');
try {
if (result.error) {
throw result.error;
}
// Set params if none is set
if (self.params === undefined) {
self.params = [];
self.setValue(self.field, self.params);
}
// Add a new file/source
var file = {
path: result.data.path,
mime: result.data.mime,
copyright: self.copyright
};
var index = (self.updateIndex !== undefined ? self.updateIndex : self.params.length);
self.params[index] = file;
self.addFile(index);
// Trigger change callbacks (old event system)
for (var i = 0; i < self.changes.length; i++) {
self.changes[i](file);
}
}
catch (error) {
// Display errors
self.$errors.append(H5PEditor.createError(error));
}
if (self.$uploading !== undefined && self.$uploading.length !== 0) {
// Hide throbber and show add button
self.$uploading.remove();
self.$add.show();
}
});
}
C.prototype = Object.create(ns.FileUploader.prototype);
C.prototype.constructor = C;
/**
* Append widget to given wrapper.
*
* @param {jQuery} $wrapper
*/
C.prototype.appendTo = function ($wrapper) {
var self = this;
var imageHtml =
'' +
C.createAdd(self.field.type) +
'' + H5PEditor.t('core', 'editCopyright') + '' +
'';
var html = H5PEditor.createFieldMarkup(this.field, imageHtml);
var $container = $(html).appendTo($wrapper);
this.$files = $container.children('.file');
this.$add = $container.children('.h5p-add-file').click(function () {
self.$addDialog.addClass('h5p-open');
});
this.$addDialog = this.$add.next();
var $url = this.$addDialog.find('.h5p-file-url');
this.$addDialog.find('.h5p-cancel').click(function () {
self.updateIndex = undefined;
$url.val('');
self.$addDialog.removeClass('h5p-open');
});
this.$addDialog.find('.h5p-file-drop-upload')
.addClass('has-advanced-upload')
.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
e.preventDefault();
e.stopPropagation();
})
.on('dragover dragenter', function(e) {
$(this).addClass('over');
e.originalEvent.dataTransfer.dropEffect = 'copy';
})
.on('dragleave', function(e) {
$(this).removeClass('over');
})
.on('drop', function(e) {
self.uploadFiles(e.originalEvent.dataTransfer.files);
})
.click(function () {
self.openFileSelector();
});
this.$addDialog.find('.h5p-insert').click(function () {
self.useUrl($url.val().trim());
self.$addDialog.removeClass('h5p-open');
$url.val('');
});
this.$errors = $container.children('.h5p-errors');
if (this.params !== undefined) {
for (var i = 0; i < this.params.length; i++) {
this.addFile(i);
}
} else {
$container.find('.h5p-copyright-button').addClass('hidden');
}
var $dialog = $container.find('.h5p-editor-dialog');
$container.find('.h5p-copyright-button').add($dialog.find('.h5p-close')).click(function () {
$dialog.toggleClass('h5p-open');
return false;
});
ns.File.addCopyright(self, $dialog, function (field, value) {
self.setCopyright(value);
});
};
/**
* Add file icon with actions.
*
* @param {Number} index
*/
C.prototype.addFile = function (index) {
var that = this;
var fileHtml;
var file = this.params[index];
var rowInputId = 'h5p-av-' + index;
var defaultQualityName = H5PEditor.t('core', 'videoQualityDefaultLabel', { ':index': index + 1 });
var qualityName = (file.metadata && file.metadata.qualityName) ? file.metadata.qualityName : defaultQualityName;
// Check if source is YouTube
var youtubeRegex = C.providers.filter(function (provider) {
return provider.name === 'YouTube';
})[0].regexp;
var isYoutube = file.path && file.path.match(youtubeRegex);
// Only allow single source if YouTube
if (isYoutube) {
// Remove all other files except this one
that.$files.children().each(function (i) {
if (i !== that.updateIndex) {
that.removeFileWithElement($(this));
}
});
// Remove old element if updating
that.$files.children().each(function () {
$(this).remove();
})
// This is now the first and only file
index = 0;
}
this.$add.toggleClass('hidden', !!isYoutube);
// If updating remove and recreate element
if (that.updateIndex !== undefined) {
var $oldFile = this.$files.children(':eq(' + index + ')');
$oldFile.remove();
this.updateIndex = undefined;
}
// Create file with customizable quality if enabled and not youtube
if (this.field.enableCustomQualityLabel === true && !isYoutube) {
fileHtml = '' +
'' +
'
' + file.mime.split('/')[1] + '
' +
'
' +
'
' +
'
' +
'' +
'
' + H5PEditor.t('core', 'videoQuality') + '
' +
'
' +
'
' +
'
' +
'';
}
else {
fileHtml = '' +
'' +
'
' + file.mime.split('/')[1] + '
' +
'
' +
'
' +
'';
}
// Insert file element in appropriate order
var $file = $(fileHtml)
if (index >= that.$files.children().length) {
$file.appendTo(that.$files);
}
else {
$file.insertBefore(that.$files.children().eq(index));
}
this.$add.parent().find('.h5p-copyright-button').removeClass('hidden');
// Handle thumbnail click
$file
.children('.h5p-thumbnail')
.click(function () {
if (!that.$add.is(':visible')) {
return; // Do not allow editing of file while uploading
}
that.$addDialog.addClass('h5p-open').find('.h5p-file-url').val(that.params[index].path);
that.updateIndex = index;
});
// Handle remove button click
$file
.find('.h5p-remove')
.click(function () {
if (that.$add.is(':visible')) {
confirmRemovalDialog.show($file.offset().top);
}
return false;
});
// on input update
$file
.find('input')
.change(function() {
file.metadata = { qualityName: $(this).val() };
});
// Create remove file dialog
var confirmRemovalDialog = new H5P.ConfirmationDialog({
headerText: H5PEditor.t('core', 'removeFile'),
dialogText: H5PEditor.t('core', 'confirmRemoval', {':type': 'file'})
}).appendTo(document.body);
// Remove file on confirmation
confirmRemovalDialog.on('confirmed', function () {
that.removeFileWithElement($file);
if (that.$files.children().length === 0) {
that.$add.parent().find('.h5p-copyright-button').addClass('hidden');
}
});
};
/**
* Remove file at index
*
* @param {number} $file File element
*/
C.prototype.removeFileWithElement = function ($file) {
var index = $file.index();
// Remove from params.
if (this.params.length === 1) {
delete this.params;
this.setValue(this.field);
}
else {
this.params.splice(index, 1);
}
$file.remove();
this.$add.removeClass('hidden');
// Notify change listeners
for (var i = 0; i < this.changes.length; i++) {
this.changes[i]();
}
}
C.prototype.useUrl = function (url) {
if (this.params === undefined) {
this.params = [];
this.setValue(this.field, this.params);
}
var mime;
var matches = url.match(/\.(webm|mp4|ogv|m4a|mp3|ogg|oga|wav)/i);
if (matches !== null) {
mime = matches[matches.length - 1];
}
else {
// Try to find a provider
for (var i = 0; i < C.providers.length; i++) {
if (C.providers[i].regexp.test(url)) {
mime = C.providers[i].name;
break;
}
}
}
var file = {
path: url,
mime: this.field.type + '/' + (mime ? mime : 'unknown'),
copyright: this.copyright
};
var index = (this.updateIndex !== undefined ? this.updateIndex : this.params.length);
this.params[index] = file;
this.addFile(index);
for (var i = 0; i < this.changes.length; i++) {
this.changes[i](file);
}
};
/**
* Validate the field/widget.
*
* @returns {Boolean}
*/
C.prototype.validate = function () {
return true;
};
/**
* Remove this field/widget.
*/
C.prototype.remove = function () {
// TODO: Check what happens when removed during upload.
this.$errors.parent().remove();
};
/**
* Sync copyright between all video files.
*
* @returns {undefined}
*/
C.prototype.setCopyright = function (value) {
this.copyright = value;
if (this.params !== undefined) {
for (var i = 0; i < this.params.length; i++) {
this.params[i].copyright = value;
}
}
};
/**
* Collect functions to execute once the tree is complete.
*
* @param {function} ready
* @returns {undefined}
*/
C.prototype.ready = function (ready) {
if (this.passReadies) {
this.parent.ready(ready);
}
else {
ready();
}
};
/**
* HTML for add button.
*
* @param {string} type 'video' or 'audio'
* @returns {string} HTML
*/
C.createAdd = function (type) {
var inputPlaceholder = H5PEditor.t('core', type === 'audio' ? 'enterAudioUrl' : 'enterVideoUrl');
var inputTitle = H5PEditor.t('core', type === 'audio' ? 'enterAudioTitle' : 'enterVideoTitle');
var uploadTitle = H5PEditor.t('core', type === 'audio' ? 'uploadAudioTitle' : 'uploadVideoTitle')
var description = (type === 'audio' ? '' : '
' + H5PEditor.t('core', 'addVideoDescription') + '
');
return '
' +
'
' +
'
' +
'
' +
'
' + uploadTitle + '
' +
'
' +
'
' +
'
' +
'
' +
'
' +
'
' + H5PEditor.t('core', 'or') + '
' +
'
' +
'
' +
'
' +
'
' + inputTitle + '
' +
'
' +
'' +
'
' +
description +
'
' +
'
' +
'
' +
'' +
'' +
'
' +
'
';
};
/**
* Providers incase mime type is unknown.
* @public
*/
C.providers = [{
name: 'YouTube',
regexp: /(?:https?:\/\/)?(?:www\.)?(?:(?:youtube.com\/(?:attribution_link\?(?:\S+))?(?:v\/|embed\/|watch\/|(?:user\/(?:\S+)\/)?watch(?:\S+)v\=))|(?:youtu.be\/|y2u.be\/))([A-Za-z0-9_-]{11})/i
}];
return C;
})(H5P.jQuery);
PK m|KAaxf f scripts/h5peditor-dimensions.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Adds a dimensions field to the form.
*
* TODO: Make it possible to lock width/height ratio.
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Dimensions}
*/
ns.Dimensions = function (parent, field, params, setValue) {
var that = this;
this.parent = parent;
this.field = field;
this.changes = [];
// Find image field to get max size from.
H5PEditor.followField(parent, field.max, function (file) {
that.setMax(file);
});
// Find image field to get default size from.
H5PEditor.followField(parent, field['default'], function (file, index) {
// Make sure we don't set size if we have one in the default params.
if (params.width === undefined) {
that.setSize(file);
}
});
this.params = params;
this.setValue = setValue;
// Remove default field from params to avoid saving it.
if (this.params.field) {
this.params.field = undefined;
}
};
/**
* Set max dimensions.
*
* @param {Object} file
* @returns {unresolved}
*/
ns.Dimensions.prototype.setMax = function (file) {
if (file === undefined) {
return;
}
this.max = {
width: parseInt(file.width),
height: parseInt(file.height)
};
};
/**
* Set current dimensions.
*
* @param {string} width
* @param {string} height
* @returns {undefined}
*/
ns.Dimensions.prototype.setSize = function (file) {
if (file === undefined) {
return;
}
this.params = {
width: parseInt(file.width),
height: parseInt(file.height)
};
this.setValue(this.field, this.params);
this.$inputs.filter(':eq(0)').val(file.width).next().val(file.height);
for (var i = 0; i < this.changes.length; i++) {
this.changes[i](file.width, file.height);
}
};
/**
* Append the field to the given wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.Dimensions.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$inputs = this.$item.find('input');
this.$errors = this.$item.children('.h5p-errors');
this.$inputs.change(function () {
// Validate
var value = that.validate();
if (value) {
// Set param
that.params = value;
that.setValue(that.field, value);
for (var i = 0; i < that.changes.length; i++) {
that.changes[i](value.width, value.height);
}
}
}).click(function () {
return false;
});
};
/**
* Create HTML for the field.
*/
ns.Dimensions.prototype.createHtml = function () {
var input = ns.createText(this.params !== undefined ? this.params.width : undefined, 15, ns.t('core', 'width')) + ' x ' + ns.createText(this.params !== undefined ? this.params.height : undefined, 15, ns.t('core', 'height'));
return ns.createFieldMarkup(this.field, input);
};
/**
* Validate the current text field.
*/
ns.Dimensions.prototype.validate = function () {
var that = this;
var size = {};
this.$errors.html('');
this.$inputs.each(function (i) {
var $input = ns.$(this);
var value = H5P.trim($input.val());
var property = i ? 'height' : 'width';
var propertyTranslated = ns.t('core', property);
if ((that.field.optional === undefined || !that.field.optional) && !value.length) {
that.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': propertyTranslated})));
return false;
}
else if (!value.match(new RegExp('^[0-9]+$'))) {
that.$errors.append(ns.createError(ns.t('core', 'onlyNumbers', {':property': propertyTranslated})));
return false;
}
value = parseInt(value);
if (that.max !== undefined && value > that.max[property]) {
that.$errors.append(ns.createError(ns.t('core', 'exceedsMax', {':property': propertyTranslated, ':max': that.max[property]})));
return false;
}
size[property] = value;
});
return ns.checkErrors(this.$errors, this.$inputs, size);
};
/**
* Remove this item.
*/
ns.Dimensions.prototype.remove = function () {
this.$item.remove();
};
// Tell the editor what widget we are.
ns.widgets.dimensions = ns.Dimensions;
PK m|KP'G scripts/h5peditor-number.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Create a number picker field for the form.
*
* @param {mixed} parent
* @param {Object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Number}
*/
ns.Number = function (parent, field, params, setValue) {
this.field = field;
this.value = params;
this.setValue = setValue;
};
/**
* Append field to wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.Number.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$errors = this.$item.find('.h5p-errors');
var $inputs = this.$item.find('input');
if ($inputs.length === 1) {
this.$input = $inputs;
}
else {
this.$range = $inputs.filter(':first');
this.$input = this.$range.next();
}
this.$input.change(function () {
// Validate
var value = that.validate();
if (value !== false) {
// Set param
that.value = value;
that.setValue(that.field, value);
if (that.$range !== undefined) {
that.$range.val(value);
}
if (value !== undefined && that.field.unit) {
that.$input.val(value + ' ' + that.field.unit);
}
}
});
if (this.$range !== undefined) {
if (this.$range.attr('type') === 'range') {
this.$range.change(function () {
that.$input.val(that.$range.val()).change();
});
// Add some styles for IE.
if (H5PEditor.isIE) {
this.$range.css('margin-top', 0);
this.$input.css('margin-top', '7px');
}
}
else {
this.$range.remove();
}
}
};
/**
* Create HTML for the field.
*/
ns.Number.prototype.createHtml = function () {
var input = ns.createText((this.field.unit && this.value !== undefined ? (this.value + ' ' + this.field.unit) : this.value), 15);
/* TODO: Add back in when FF gets support for input:range....
*if (this.field.min !== undefined && this.field.max !== undefined && this.field.step !== undefined) {
input = '
' + input;
}
*/
return ns.createFieldMarkup(this.field, input);
};
/**
* Validate the current text field.
*/
ns.Number.prototype.validate = function () {
var that = this;
var value = H5P.trim(this.$input.val());
var decimals = this.field.decimals !== undefined && this.field.decimals;
if (this.field.unit) {
value = value.replace(new RegExp(' *' + this.field.unit + '$'), '');
}
// Clear errors before showing new ones
this.$errors.html('');
// Determine property name
var propertyName = (that.field.label === 0 ? ns.t('core', 'numberField') : that.field.label);
if (!value.length) {
if (that.field.optional === true) {
// Field is optional and does not have a value, nothing more to validate
this.$input.removeClass('error');
return;
}
// Field must have a value
this.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': ns.t('core', 'numberField')})));
}
else if (decimals && !value.match(new RegExp('^-?[0-9]+(.|,)[0-9]{1,}$'))) {
this.$errors.append(ns.createError(ns.t('core', 'onlyNumbers', {':property': propertyName})));
}
else if (!decimals && !value.match(new RegExp('^-?[0-9]+$'))) {
this.$errors.append(ns.createError(ns.t('core', 'onlyNumbers', {':property': propertyName})));
}
else {
if (decimals) {
value = parseFloat(value.replace(',', '.'));
}
else {
value = parseInt(value);
}
if (this.field.max !== undefined && value > this.field.max) {
this.$errors.append(ns.createError(ns.t('core', 'exceedsMax', {':property': propertyName, ':max': this.field.max})));
}
else if (this.field.min !== undefined && value < this.field.min) {
this.$errors.append(ns.createError(ns.t('core', 'belowMin', {':property': propertyName, ':min': this.field.min})));
}
else if (this.field.step !== undefined && value % this.field.step) {
this.$errors.append(ns.createError(ns.t('core', 'outOfStep', {':property': propertyName, ':step': this.field.step})));
}
}
this.$input.toggleClass('error', this.$errors.html().length > 0);
return ns.checkErrors(this.$errors, this.$input, value);
};
/**
* Remove this item.
*/
ns.Number.prototype.remove = function () {
this.$item.remove();
};
// Tell the editor what widget we are.
ns.widgets.number = ns.Number;
PK m|KA[ [ " scripts/h5peditor-file-uploader.jsnu W+A H5PEditor.FileUploader = (function ($, EventDispatcher) {
var nextIframe;
/**
* File Upload API for H5P
*
* @class H5PEditor.FileUploader
* @extends H5P.EventDispatcher
* @param {Object} field Required for validating the uploaded file
*/
function FileUploader(field) {
var self = this;
// Initialize event inheritance
EventDispatcher.call(self);
var isUploadingData;
/**
* Trigger uploading start.
*
* @private
* @param {string} [data] Optional for uploading string data (URI)
* @return {boolean} false if the iframe is unavailable and the caller should try again later
*/
var upload = function (data, files) {
if (!nextIframe.isReady()) {
return false; // Iframe isn't loaded. The caller should try again later
}
isUploadingData = (data !== undefined && data !== null) || (files !== undefined);
// Add event listeners
nextIframe.on('upload', function (event) {
self.trigger(event);
});
nextIframe.on('uploadComplete', function (event) {
self.trigger(event);
});
// Update field
nextIframe.setField(field, data, files);
return true;
};
/**
* Prepare an iframe and triggers the opening of the file selector
* @return {boolean} false if the iframe is unavailable and the caller should try again later
*/
self.openFileSelector = function () {
return upload();
};
/**
* Prepare an iframe and trigger upload of the given data.
*
* @param {string} data
* @return {boolean} false if the iframe is unavailable and the caller should try again later
*/
self.uploadData = function (data) {
if (data === undefined) {
throw('Missing data.');
}
return upload(data);
};
self.uploadFiles = function (files) {
return upload(null, files);
};
/**
* Makes it possible to check if it is data or a file being uploaded.
*
* @return {boolean}
*/
self.isUploadingData = function () {
return isUploadingData;
};
if (!nextIframe) {
// We must always have an iframe available for the next upload
nextIframe = new Iframe();
}
}
// Extends the event dispatcher
FileUploader.prototype = Object.create(EventDispatcher.prototype);
FileUploader.prototype.constructor = FileUploader;
/**
* Iframe for file uploading. Only available for the FileUploader class.
* Iframes are discarded after the upload is completed.
*
* @private
* @class Iframe
* @extends H5P.EventDispatcher
*/
function Iframe() {
var self = this;
// Initialize event inheritance
EventDispatcher.call(self);
var ready = false;
var $iframe, $form, $file, $data, $field;
/**
* @private
*/
var upload = function () {
// Iframe isn't really bound to a field until the upload starts
ready = false;
// Trigger upload event and submit upload form
self.trigger('upload');
$form.submit();
// This iframe is used, we must add another for the next upload
nextIframe = new Iframe();
};
/**
* Create and insert iframe into the DOM.
*
* @private
*/
var insertIframe = function () {
$iframe = $('
', {
css: {
position: 'absolute',
width: '1px',
height: '1px',
top: '-1px',
border: 0,
overflow: 'hidden'
},
one: {
load: function () {
ready = true;
}
},
appendTo: 'body'
});
};
/**
* Create and add upload form to the iframe.
*
* @private
*/
var insertForm = function () {
// Create upload form
$form = $('
', {
method: 'post',
enctype: 'multipart/form-data',
action: H5PEditor.getAjaxUrl('files')
});
// Create input fields
$file = $('
', {
type: 'file',
name: 'file',
on: {
change: upload
},
appendTo: $form
});
$data = $('
', {
type: 'hidden',
name: 'dataURI',
appendTo: $form
});
$field = $('
', {
type: 'hidden',
name: 'field',
appendTo: $form
});
$('
', {
type: 'hidden',
name: 'contentId',
value: H5PEditor.contentId ? H5PEditor.contentId : 0,
appendTo: $form
});
// Add form to iframe
var $body = $iframe.contents().find('body');
$form.appendTo($body);
// Add event handler for processing results
$iframe.on('load', processResponse);
};
/**
* Handler for processing server response when upload form is submitted.
*
* @private
*/
var processResponse = function () {
// Upload complete, get response text
var $body = $iframe.contents().find('body');
var response = $body.text();
// Clean up all our DOM elements
$iframe.remove();
// Try to parse repsonse
if (response) {
var result;
var uploadComplete = {
error: null,
data: null
};
try {
result = JSON.parse(response);
}
catch (err) {
H5P.error(err);
// Add error data to event object
uploadComplete.error = H5PEditor.t('core', 'fileToLarge');
}
if (result !== undefined) {
if (result.error !== undefined) {
uploadComplete.error = result.error;
}
if (result.success === false) {
uploadComplete.error = (result.message ? result.message : H5PEditor.t('core', 'unknownFileUploadError'));
}
}
if (uploadComplete.error === null) {
// No problems, add response data to event object
uploadComplete.data = result;
}
// Allow the widget to process the result
self.trigger('uploadComplete', uploadComplete);
}
};
/**
* Prepare the upload form for the given field.
* Opens the file selector or if data is provided, submits the form
* straight away.
*
* @param {Object} field
* @param {string} [data] Optional URI
*/
self.setField = function (field, data, files) {
// Determine allowed file mimes
var mimes;
if (field.mimes) {
mimes = field.mimes.join(',');
}
else if (field.type === 'image') {
mimes = 'image/jpeg,image/png,image/gif';
}
else if (field.type === 'audio') {
mimes = 'audio/mpeg,audio/x-wav,audio/ogg';
}
else if (field.type === 'video') {
mimes = 'video/mp4,video/webm,video/ogg';
}
$file.attr('accept', mimes);
// Set field
$field.val(JSON.stringify(field));
if (files !== undefined) {
$file.prop('files', files);
} else if (data !== undefined) {
// Upload given data
$data.val(data);
upload();
}
else {
// Trigger file selector
$file.click();
}
};
/**
* Indicates if this iframe is ready to be used
*/
self.isReady = function () {
if (!ready) {
return false;
}
if (!$form) {
// Insert form if not present
insertForm();
}
else {
// If present clear any event handlers (was used by another field)
self.off('upload');
self.off('uploadComplete');
}
return true;
};
// Always insert iframe on construct
insertIframe();
// The iframe must be loaded before the click event that sets the field,
// async clicking won't work for security reasons in the browser.
}
// Extends the event dispatcher
Iframe.prototype = Object.create(EventDispatcher.prototype);
Iframe.prototype.constructor = Iframe;
return FileUploader;
})(H5P.jQuery, H5P.EventDispatcher);
PK m|K^T% T% scripts/h5peditor-list-editor.jsnu W+A /** @namespace H5PEditor */
var H5PEditor = H5PEditor || {};
H5PEditor.ListEditor = (function ($) {
/**
* Draws the list.
*
* @class
* @param {List} list
*/
function ListEditor(list) {
var self = this;
var entity = list.getEntity();
// Create list html
var $list = $('
', {
'class': 'h5p-ul'
});
// Create add button
var $button = ns.createButton(list.getImportance(), H5PEditor.t('core', 'addEntity', {':entity': entity}), function () {
list.addItem();
}, true);
// Used when dragging items around
var adjustX, adjustY, marginTop, formOffset;
/**
* @private
* @param {jQuery} $item
* @param {jQuery} $placeholder
* @param {Number} x
* @param {Number} y
*/
var moveItem = function ($item, $placeholder, x, y) {
var currentIndex;
// Adjust so the mouse is placed on top of the icon.
x = x - adjustX;
y = y - adjustY;
$item.css({
top: y - marginTop - formOffset.top,
left: x - formOffset.left
});
// Try to move up.
var $prev = $item.prev().prev();
if ($prev.length && y < $prev.offset().top + ($prev.height() / 2)) {
$prev.insertAfter($item);
currentIndex = $item.index();
list.moveItem(currentIndex, currentIndex - 1);
return;
}
// Try to move down.
var $next = $item.next();
if ($next.length && y + $item.height() > $next.offset().top + ($next.height() / 2)) {
$next.insertBefore($placeholder);
currentIndex = $item.index() - 2;
list.moveItem(currentIndex, currentIndex + 1);
}
};
/**
* Adds UI items to the widget.
*
* @public
* @param {Object} item
*/
self.addItem = function (item) {
var $placeholder, mouseDownAt;
var $item = $('
', {
'class' : 'h5p-li',
});
// Create confirmation dialog for removing list item
var confirmRemovalDialog = new H5P.ConfirmationDialog({
dialogText: H5PEditor.t('core', 'confirmRemoval', {':type': entity})
}).appendTo(document.body);
// Remove list item on confirmation
confirmRemovalDialog.on('confirmed', function () {
list.removeItem($item.index());
$item.remove();
});
/**
* Mouse move callback
*
* @private
* @param {Object} event
*/
var move = function (event) {
if (mouseDownAt) {
// Have not started moving yet
if (! (event.pageX > mouseDownAt.x + 5 || event.pageX < mouseDownAt.x - 5 ||
event.pageY > mouseDownAt.y + 5 || event.pageY < mouseDownAt.y - 5) ) {
return; // Not ready to start moving
}
// Prevent wysiwyg becoming unresponsive
H5PEditor.Html.removeWysiwyg();
// Prepare to start moving
mouseDownAt = null;
var offset = $item.offset();
adjustX = event.pageX - offset.left;
adjustY = event.pageY - offset.top;
marginTop = parseInt($item.css('marginTop'));
formOffset = $list.offsetParent().offset();
// TODO: Couldn't formOffset and margin be added?
var width = $item.width();
var height = $item.height();
$item.addClass('moving').css({
width: width,
height: height
});
$placeholder = $('
', {
'class': 'placeholder h5p-li',
css: {
width: width,
height: height
}
}).insertBefore($item);
}
moveItem($item, $placeholder, event.pageX, event.pageY);
};
/**
* Mouse button release callback
*
* @private
*/
var up = function (event) {
// Stop listening for mouse move events
H5P.$window
.unbind('mousemove', move)
.unbind('mouseup', up);
// Enable text select again
H5P.$body
.css({
'-moz-user-select': '',
'-webkit-user-select': '',
'user-select': '',
'-ms-user-select': ''
})
.attr('unselectable', 'off')
[0].onselectstart = H5P.$body[0].ondragstart = null;
if (!mouseDownAt) {
// Not your regular click, we have been moving
$item.removeClass('moving').css({
width: 'auto',
height: 'auto'
});
$placeholder.remove();
if (item instanceof H5PEditor.Group) {
// Avoid groups expand/collapse toggling
item.preventToggle = true;
}
}
};
/**
* Mouse button down callback
*
* @private
*/
var down = function (event) {
if (event.which !== 1) {
return; // Only allow left mouse button
}
mouseDownAt = {
x: event.pageX,
y: event.pageY
};
// Start listening for mouse move events
H5P.$window
.mousemove(move)
.mouseup(up);
// Prevent text select
H5P.$body
.css({
'-moz-user-select': 'none',
'-webkit-user-select': 'none',
'user-select': 'none',
'-ms-user-select': 'none'
})
.attr('unselectable', 'on')
[0].onselectstart = H5P.$body[0].ondragstart = function () {
return false;
};
};
/**
* Order current list item up
*
* @private
*/
var moveItemUp = function () {
var $prev = $item.prev();
if (!$prev.length) {
return; // Cannot move item further up
}
// Prevent wysiwyg becoming unresponsive
H5PEditor.Html.removeWysiwyg();
var currentIndex = $item.index();
$prev.insertAfter($item);
list.moveItem(currentIndex, currentIndex - 1);
};
/**
* Order current ist item down
*
* @private
*/
var moveItemDown = function () {
var $next = $item.next();
if (!$next.length) {
return; // Cannot move item further down
}
// Prevent wysiwyg becoming unresponsive
H5PEditor.Html.removeWysiwyg();
var currentIndex = $item.index();
$next.insertBefore($item);
list.moveItem(currentIndex, currentIndex + 1);
};
// List item title bar
var $titleBar = $('
', {
'class': 'list-item-title-bar',
appendTo: $item
});
// Container for list actions
var $listActions = $('
', {
class: 'list-actions',
appendTo: $titleBar
});
// Append order button
var $orderGroup = $('
', {
class : 'order-group',
appendTo: $listActions
});
H5PEditor.createButton('order-up', H5PEditor.t('core', 'orderItemUp'), moveItemUp).appendTo($orderGroup);
H5PEditor.createButton('order-down', H5PEditor.t('core', 'orderItemDown'), moveItemDown).appendTo($orderGroup);
H5PEditor.createButton('remove', H5PEditor.t('core', 'removeItem'), function () {
confirmRemovalDialog.show($(this).offset().top);
}).appendTo($listActions);
// Append new field item to content wrapper
if (item instanceof H5PEditor.Group) {
// Append to item
item.appendTo($item);
$item.addClass('listgroup');
$titleBar.addClass(list.getImportance());
// Move label
$item.children('.field').children('.title').appendTo($titleBar).addClass('h5peditor-label');
// Handle expand and collapse
item.on('expanded', function () {
$item.addClass('expanded').removeClass('collapsed');
});
item.on('collapsed', function () {
$item.removeClass('expanded').addClass('collapsed');
});
}
else {
// Append content wrapper
var $content = $('
', {
'class' : 'content'
}).appendTo($item);
// Add importance to items not in groups
$titleBar.addClass(list.getImportance());
// Append field
item.appendTo($content);
if (item.field.label !== 0) {
// Try to find and move the label to the title bar
$content.children('.field').find('.h5peditor-label:first').removeClass('h5peditor-required').appendTo($titleBar);
}
}
// Append item to list
$item.appendTo($list);
if (item instanceof H5PEditor.Group) {
// Good UX: automatically expand groups if not explicitly disabled by semantics
item.expand();
}
$titleBar.children('.h5peditor-label').mousedown(down);
};
/**
* Determine if child is a text field
*
* @param {Object} child
* @returns {boolean} True if child is a text field
*/
self.isTextField = function (child) {
var widget = ns.getWidgetName(child.field);
return widget === 'html' || widget === 'text';
};
/**
* Puts this widget at the end of the given container.
*
* @public
* @param {jQuery} $container
*/
self.appendTo = function ($container) {
$list.appendTo($container);
$button.appendTo($container);
};
/**
* Remove this widget from the editor DOM.
*
* @public
*/
self.remove = function () {
$list.remove();
$button.remove();
};
}
return ListEditor;
})(H5P.jQuery);
PK m|K scripts/h5peditor-group.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Create a group of fields.
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Group}
*/
ns.Group = function (parent, field, params, setValue) {
// Support for events
H5P.EventDispatcher.call(this);
if (field.label === undefined) {
field.label = field.name;
}
else if (field.label === 0) {
field.label = '';
}
this.parent = parent;
this.passReadies = true;
this.params = params;
this.setValue = setValue;
this.library = parent.library + '/' + field.name;
if (field.deprecated !== undefined && field.deprecated) {
this.field = H5P.cloneObject(field, true);
var empties = 0;
for (var i = 0; i < this.field.fields.length; i++) {
var f = this.field.fields[i];
if (params !== undefined && params[f.name] === '') {
delete params[f.name];
}
if (params === undefined || params[f.name] === undefined) {
f.widget = 'none';
empties++;
}
}
if (i === empties) {
this.field.fields = [];
}
}
else {
this.field = field;
}
if (this.field.optional === true) {
// If this field is optional, make sure child fields are as well
for (var j = 0; j < this.field.fields.length; j++) {
this.field.fields[j].optional = true;
}
}
};
// Extends the event dispatcher
ns.Group.prototype = Object.create(H5P.EventDispatcher.prototype);
ns.Group.prototype.constructor = ns.Group;
/**
* Append group to its wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.Group.prototype.appendTo = function ($wrapper) {
var that = this;
if (this.field.fields.length === 0) {
// No fields or all are deprecated
this.setValue(this.field);
return;
}
// Add fieldset wrapper for group
this.$group = ns.$('
', {
'class': 'field group ' + H5PEditor.createImportance(this.field.importance) + ' field-name-' + this.field.name,
appendTo: $wrapper
});
// Add title expand/collapse button
this.$title = ns.$('
', {
'class': 'title',
title: ns.t('core', 'expandCollapse'),
role: 'button',
tabIndex: 0,
on: {
click: function () {
that.toggle();
},
keypress: function (event) {
if ((event.charCode || event.keyCode) === 32) {
that.toggle();
event.preventDefault();
}
}
},
appendTo: this.$group
});
// Add content container
var $content = ns.$('
', {
'class': 'content',
appendTo: this.$group
});
if (this.hasSingleChild() && !this.isSubContent()) {
$content.addClass('h5peditor-single');
this.children = [];
var field = this.field.fields[0];
var widget = field.widget === undefined ? field.type : field.widget;
this.children[0] = new ns.widgets[widget](this, field, this.params, function (field, value) {
that.setValue(that.field, value);
});
this.children[0].appendTo($content);
}
else {
if (this.params === undefined) {
this.params = {};
this.setValue(this.field, this.params);
}
this.params = this.initSubContent(this.params);
ns.processSemanticsChunk(this.field.fields, this.params, $content, this);
}
// Set summary
this.findSummary();
// Check if group should be expanded.
// Default is to be collapsed unless explicity defined in semantics by optional attribute expanded
if (this.field.expanded === true) {
this.expand();
}
};
/**
* Return whether this group is Sub Content
*
* @private
* @return {boolean}
*/
ns.Group.prototype.hasSingleChild = function () {
return this.field.fields.length === 1;
};
/**
* Add generated 'subContentId' attribute, if group is "sub content (library-like embedded structure)"
*
* @param {object} params
*
* @private
* @return {object}
*/
ns.Group.prototype.initSubContent = function (params) {
// If group contains library-like sub content that needs UUIDs
if(this.isSubContent()){
params['subContentId'] = params['subContentId'] || H5P.createUUID();
}
return params;
};
/**
* Return whether this group is Sub Content
*
* @private
* @return {boolean}
*/
ns.Group.prototype.isSubContent = function () {
return this.field.isSubContent === true;
};
/**
* Toggle expand/collapse for the given group.
*/
ns.Group.prototype.toggle = function () {
if (this.preventToggle) {
this.preventToggle = false;
return;
}
if (this.$group.hasClass('expanded')) {
this.collapse();
}
else {
this.expand();
}
};
/**
* Expand the given group.
*/
ns.Group.prototype.expand = function () {
this.$group.addClass('expanded');
this.trigger('expanded');
};
/**
* Collapse the given group (if valid)
*/
ns.Group.prototype.collapse = function () {
// Do not collapse before valid!
var valid = true;
for (var i = 0; i < this.children.length; i++) {
if (this.children[i].validate() === false) {
valid = false;
}
}
if (valid) {
this.$group.removeClass('expanded');
this.trigger('collapsed');
}
};
/**
* Find summary to display in group header.
*/
ns.Group.prototype.findSummary = function () {
var that = this;
var summary;
for (var j = 0; j < this.children.length; j++) {
var child = this.children[j];
if (child.field === undefined) {
continue;
}
var params = (that.hasSingleChild() && !that.isSubContent()) ? this.params : this.params[child.field.name];
var widget = ns.getWidgetName(child.field);
if (widget === 'text' || widget === 'html') {
if (params !== undefined && params !== '') {
summary = params.replace(/(<([^>]+)>)/ig, "");
}
child.$input.change(function () {
var params = (that.hasSingleChild() && !that.isSubContent()) ? that.params : that.params[child.field.name];
if (params !== undefined && params !== '') {
that.setSummary(params.replace(/(<([^>]+)>)/ig, ""));
}
});
break;
}
else if (widget === 'library') {
if (params !== undefined) {
summary = child.$select.children(':selected').text();
}
child.change(function (library) {
that.setSummary(library.title);
});
break;
}
}
this.setSummary(summary);
};
/**
* Set the given group summary.
*
* @param {string} summary
* @returns {undefined}
*/
ns.Group.prototype.setSummary = function (summary) {
var summaryText;
// Parse html
var summaryTextNode = ns.$.parseHTML(summary);
if (summaryTextNode !== null) {
summaryText = summaryTextNode[0].nodeValue;
}
// Make it possible for parent to monitor summary changes
this.trigger('summary', summaryText);
if (summaryText !== undefined) {
summaryText = this.field.label + ': ' + (summaryText.length > 48 ? summaryText.substr(0, 45) + '...' : summaryText);
}
else {
summaryText = this.field.label;
}
this.$title.text(summaryText);
};
/**
* Validate all children.
*/
ns.Group.prototype.validate = function () {
var valid = true;
if (this.children !== undefined) {
for (var i = 0; i < this.children.length; i++) {
if (this.children[i].validate() === false) {
valid = false;
}
}
}
return valid;
};
/**
* Allows ancestors and widgets to do stuff with our children.
*
* @public
* @param {Function} task
*/
ns.Group.prototype.forEachChild = function (task) {
for (var i = 0; i < this.children.length; i++) {
task(this.children[i], i);
}
};
/**
* Collect functions to execute once the tree is complete.
*
* @param {function} ready
* @returns {undefined}
*/
ns.Group.prototype.ready = function (ready) {
this.parent.ready(ready);
};
/**
* Remove this item.
*/
ns.Group.prototype.remove = function () {
if (this.$group !== undefined) {
ns.removeChildren(this.children);
this.$group.remove();
}
};
/**
* Get a copy of the fields semantics used by this group.
* @return {Array}
*/
ns.Group.prototype.getFields = function () {
return H5PEditor.$.extend(true, [], this.field.fields);
};
// Tell the editor what widget we are.
ns.widgets.group = ns.Group;
PK m|KT8 o o scripts/h5peditor-file.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Adds a file upload field to the form.
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.File}
*/
ns.File = function (parent, field, params, setValue) {
var self = this;
// Initialize inheritance
ns.FileUploader.call(self, field);
this.parent = parent;
this.field = field;
this.params = params;
this.setValue = setValue;
this.library = parent.library + '/' + field.name;
if (params !== undefined) {
this.copyright = params.copyright;
}
this.changes = [];
this.passReadies = true;
parent.ready(function () {
self.passReadies = false;
});
// Create remove file dialog
this.confirmRemovalDialog = new H5P.ConfirmationDialog({
headerText: H5PEditor.t('core', 'removeFile'),
dialogText: H5PEditor.t('core', 'confirmRemoval', {':type': 'file'})
}).appendTo(document.body);
// Remove file on confirmation
this.confirmRemovalDialog.on('confirmed', function () {
delete self.params;
self.setValue(self.field);
self.addFile();
for (var i = 0; i < self.changes.length; i++) {
self.changes[i]();
}
});
// When uploading starts
self.on('upload', function () {
// Insert throbber
self.$file.html('
' + ns.t('core', 'uploading') + '
');
// Clear old error messages
self.$errors.html('');
});
// Handle upload complete
self.on('uploadComplete', function (event) {
var result = event.data;
try {
if (result.error) {
throw result.error;
}
self.params = self.params || {};
self.params.path = result.data.path;
self.params.mime = result.data.mime;
self.params.copyright = self.copyright;
// Make it possible for other widgets to process the result
self.trigger('fileUploaded', result.data);
self.setValue(self.field, self.params);
for (var i = 0; i < self.changes.length; i++) {
self.changes[i](self.params);
}
}
catch (error) {
self.$errors.append(ns.createError(error));
}
self.addFile();
});
};
ns.File.prototype = Object.create(ns.FileUploader.prototype);
ns.File.prototype.constructor = ns.File;
/**
* Append field to the given wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.File.prototype.appendTo = function ($wrapper) {
var self = this;
var fileHtml =
'
' +
'
' + ns.t('core', 'editCopyright') + '' +
'
';
var html = ns.createFieldMarkup(this.field, fileHtml);
var $container = ns.$(html).appendTo($wrapper);
this.$copyrightButton = $container.find('.h5p-copyright-button');
this.$file = $container.find('.file');
this.$errors = $container.find('.h5p-errors');
this.addFile();
var $dialog = $container.find('.h5p-editor-dialog');
$container.find('.h5p-copyright-button').add($dialog.find('.h5p-close')).click(function () {
$dialog.toggleClass('h5p-open');
return false;
});
ns.File.addCopyright(self, $dialog, function (field, value) {
if (self.params !== undefined) {
self.params.copyright = value;
}
self.copyright = value;
});
};
/**
* Help add copyright dialog to the given field
*
* @param {Object} field
* @param {function} setCopyright
*/
ns.File.addCopyright = function (field, $dialog, setCopyright) {
/**
* Help find object in list with the given property value.
*
* @param {Object[]} list of objects to search through
* @param {string} property to look for
* @param {string} value to match property value against
*/
var find = function (list, property, value) {
var properties = property.split('.');
for (var i = 0; i < list.length; i++) {
var objProp = list[i];
for (var j = 0; j < properties.length; j++) {
objProp = objProp[properties[j]];
}
if (objProp === value) {
return list[i];
}
}
}
// Re-map old licenses that has been moved
if (field.copyright) {
if (field.copyright.license === 'ODC PDDL') {
field.copyright.license = 'PD';
field.copyright.version = 'CC0 1.0';
}
else if (field.copyright.license === 'CC PDM') {
field.copyright.license = 'PD';
field.copyright.version = 'CC PDM';
}
}
var group = new H5PEditor.widgets.group(field, H5PEditor.copyrightSemantics, field.copyright, setCopyright);
group.appendTo($dialog);
group.expand();
group.$group.find('.title').remove();
field.children = [group];
// Locate license and version selectors
var licenseField = find(group.children, 'field.name', 'license');
var versionField = find(group.children, 'field.name', 'version');
versionField.field.optional = true; // Avoid any error messages
// Listen for changes to license
licenseField.changes.push(function (value) {
// Find versions for selected value
var option = find(licenseField.field.options, 'value', value);
var versions = option.versions;
versionField.$select.prop('disabled', versions === undefined);
if (versions === undefined) {
// If no versions add default
versions = [{
value: '-',
label: '-'
}];
}
// Find default selected version
var selected = (field.copyright.license === value &&
field.copyright.version ? field.copyright.version : versions[0].value);
// Update versions selector
versionField.$select.html(H5PEditor.Select.createOptionsHtml(versions, selected)).change();
});
// Trigger update straight away
licenseField.changes[licenseField.changes.length - 1](field.copyright.license);
};
/**
* Creates thumbnail HTML and actions.
*
* @returns {Boolean}
*/
ns.File.prototype.addFile = function () {
var that = this;
if (this.params === undefined) {
this.$file.html(
'
' +
'' + ns.t('core', 'add') + '
' +
''
).children('.add').click(function () {
that.openFileSelector();
return false;
});
this.$copyrightButton.addClass('hidden');
return;
}
var thumbnail;
if (this.field.type === 'image') {
thumbnail = {};
thumbnail.path = H5P.getPath(this.params.path, H5PEditor.contentId);
thumbnail.height = 100;
if (this.params.width !== undefined) {
thumbnail.width = thumbnail.height * (this.params.width / this.params.height);
}
}
else {
thumbnail = ns.fileIcon;
}
this.$file.html('
').children(':eq(0)').click(function () {
that.openFileSelector();
return false;
}).children('img').attr('src', thumbnail.path).end().next().click(function (e) {
that.confirmRemovalDialog.show(H5P.jQuery(this).offset().top);
return false;
});
that.$copyrightButton.removeClass('hidden');
};
/**
* Validate this item
*/
ns.File.prototype.validate = function () {
return true;
};
/**
* Remove this item.
*/
ns.File.prototype.remove = function () {
// TODO: Check what happens when removed during upload.
this.$file.parent().remove();
};
/**
* Collect functions to execute once the tree is complete.
*
* @param {function} ready
* @returns {undefined}
*/
ns.File.prototype.ready = function (ready) {
if (this.passReadies) {
this.parent.ready(ready);
}
else {
ready();
}
};
// Tell the editor what widget we are.
ns.widgets.file = ns.File;
PK m|K?XI
I
scripts/h5peditor-textarea.jsnu W+A // DEPRECATED: This widget will be removed and replaced with the HTML widget
var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Create a text field for the form.
*
* @param {mixed} parent
* @param {Object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Textarea}
*/
ns.Textarea = function (parent, field, params, setValue) {
this.parent = parent;
this.field = field;
this.value = params;
this.setValue = setValue;
};
/**
* Append field to wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.Textarea.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$input = this.$item.find('textarea');
this.$errors = this.$item.find('.h5p-errors');
ns.bindImportantDescriptionEvents(this, this.field.name, this.parent);
this.$input.change(function () {
// Validate
var value = that.validate();
if (value !== false) {
// Set param
that.setValue(that.field, ns.htmlspecialchars(value));
}
});
};
/**
* Create HTML for the text field.
*/
ns.Textarea.prototype.createHtml = function () {
var input = '
';
return ns.createFieldMarkup(this.field, ns.createImportantDescription(this.field.important) + input);
};
/**
* Validate the current text field.
*/
ns.Textarea.prototype.validate = function () {
var value = H5P.trim(this.$input.val());
if (this.$errors.html().length > 0) {
this.$input.addClass('error');
}
// Clear errors before showing new ones
this.$errors.html('');
if ((this.field.optional === undefined || !this.field.optional) && !value.length) {
this.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': ns.t('core', 'textField')})));
}
else if (value.length > this.field.maxLength) {
this.$errors.append(ns.createError(ns.t('core', 'tooLong', {':max': this.field.maxLength})));
}
else if (this.field.regexp !== undefined && !value.match(new RegExp(this.field.regexp.pattern, this.field.regexp.modifiers))) {
this.$errors.append(ns.createError(ns.t('core', 'invalidFormat')));
}
return ns.checkErrors(this.$errors, this.$input, value);
};
/**
* Remove this item.
*/
ns.Textarea.prototype.remove = function () {
this.$item.remove();
};
// Tell the editor what semantic field we are.
ns.widgets.textarea = ns.Textarea;
PK m|Kqϼ* * scripts/h5peditor-image-popup.jsnu W+A /*global H5PEditor, H5P, ns, Darkroom*/
H5PEditor.ImageEditingPopup = (function ($, EventDispatcher) {
var instanceCounter = 0;
var scriptsLoaded = false;
/**
* Popup for editing images
*
* @param {number} [ratio] Ratio that cropping must keep
* @constructor
*/
function ImageEditingPopup(ratio) {
EventDispatcher.call(this);
var self = this;
var uniqueId = instanceCounter;
var isShowing = false;
var isReset = false;
var topOffset = 0;
var maxWidth;
var maxHeight;
// Create elements
var background = document.createElement('div');
background.className = 'h5p-editing-image-popup-background hidden';
var popup = document.createElement('div');
popup.className = 'h5p-editing-image-popup';
background.appendChild(popup);
var header = document.createElement('div');
header.className = 'h5p-editing-image-header';
popup.appendChild(header);
var headerTitle = document.createElement('div');
headerTitle.className = 'h5p-editing-image-header-title';
headerTitle.textContent = 'Edit Image!';
header.appendChild(headerTitle);
var headerButtons = document.createElement('div');
headerButtons.className = 'h5p-editing-image-header-buttons';
header.appendChild(headerButtons);
var editingContainer = document.createElement('div');
editingContainer.className = 'h5p-editing-image-editing-container';
popup.appendChild(editingContainer);
var imageLoading = document.createElement('div');
imageLoading.className = 'h5p-editing-image-loading';
imageLoading.textContent = ns.t('core', 'loadingImageEditor');
popup.appendChild(imageLoading);
// Create editing image
var editingImage = new Image();
editingImage.className = 'h5p-editing-image hidden';
editingImage.id = 'h5p-editing-image-' + uniqueId;
editingContainer.appendChild(editingImage);
// Close popup on background click
background.addEventListener('click', function () {
this.hide();
}.bind(this));
// Prevent closing popup
popup.addEventListener('click', function (e) {
e.stopPropagation();
});
// Make sure each ImageEditingPopup instance has a unique ID
instanceCounter += 1;
/**
* Create header button
*
* @param {string} coreString Must be specified in core translations
* @param {string} className Unique button identifier that will be added to classname
* @param {function} clickEvent OnClick function
*/
var createButton = function (coreString, className, clickEvent) {
var button = document.createElement('button');
button.textContent = ns.t('core', coreString);
button.className = className;
button.addEventListener('click', clickEvent);
headerButtons.appendChild(button);
};
/**
* Set max width and height for image editing tool
*/
var setDarkroomDimensions = function () {
// Set max dimensions
var dims = ImageEditingPopup.staticDimensions;
maxWidth = H5P.$body.get(0).offsetWidth - dims.backgroundPaddingWidth -
dims.darkroomPadding;
// Only use 65% of screen height
var maxScreenHeight = screen.height * dims.maxScreenHeightPercentage;
// Calculate editor max height
var editorHeight = H5P.$body.get(0).offsetHeight -
dims.backgroundPaddingHeight - dims.popupHeaderHeight -
dims.darkroomToolbarHeight - dims.darkroomPadding;
// Use smallest of screen height and editor height,
// we don't want to overflow editor or screen
maxHeight = maxScreenHeight < editorHeight ? maxScreenHeight : editorHeight;
};
/**
* Create image editing tool from image.
*/
var createDarkroom = function () {
window.requestAnimationFrame(function () {
self.darkroom = new Darkroom('#h5p-editing-image-' + uniqueId, {
initialize: function () {
// Reset transformations
this.transformations = [];
H5P.$body.get(0).classList.add('h5p-editor-image-popup');
background.classList.remove('hidden');
imageLoading.classList.add('hidden');
self.trigger('initialized');
},
maxWidth: maxWidth,
maxHeight: maxHeight,
plugins: {
crop: {
ratio: ratio || null
},
save : false
}
});
});
};
/**
* Load a script dynamically
*
* @param {string} path Path to script
* @param {function} [callback]
*/
var loadScript = function (path, callback) {
$.ajax({
url: path,
dataType: 'script',
success: function () {
if (callback) {
callback();
}
},
async: true
});
};
/**
* Load scripts dynamically
*/
var loadScripts = function () {
loadScript(H5PEditor.basePath + 'libs/fabric.js', function () {
loadScript(H5PEditor.basePath + 'libs/darkroom.js', function () {
createDarkroom();
scriptsLoaded = true;
});
});
};
/**
* Grab canvas data and pass data to listeners.
*/
var saveImage = function () {
var isCropped = self.darkroom.plugins.crop.hasFocus();
var canvas = self.darkroom.canvas.getElement();
var convertData = function () {
var newImage = self.darkroom.canvas.toDataURL();
self.trigger('savedImage', newImage);
canvas.removeEventListener('crop:update', convertData, false);
};
// Check if image has changed
if (self.darkroom.transformations.length || isReset || isCropped) {
if (isCropped) {
//self.darkroom.plugins.crop.okButton.element.click();
self.darkroom.plugins.crop.cropCurrentZone();
canvas.addEventListener('crop:update', convertData, false);
} else {
convertData();
}
}
isReset = false;
};
/**
* Adjust popup offset.
* Make sure it is centered on top of offset.
*
* @param {Object} [offset] Offset that popup should center on.
* @param {number} [offset.top] Offset to top.
*/
this.adjustPopupOffset = function (offset) {
if (offset) {
topOffset = offset.top;
}
// Only use 65% of screen height
var maxScreenHeight = screen.height * 0.65;
// Calculate editor max height
var dims = ImageEditingPopup.staticDimensions;
var backgroundHeight = H5P.$body.get(0).offsetHeight - dims.backgroundPaddingHeight;
var popupHeightNoImage = dims.darkroomToolbarHeight + dims.popupHeaderHeight +
dims.darkroomPadding;
var editorHeight = backgroundHeight - popupHeightNoImage;
// Available editor height
var availableHeight = maxScreenHeight < editorHeight ? maxScreenHeight : editorHeight;
// Check if image is smaller than available height
var actualImageHeight;
if (editingImage.naturalHeight < availableHeight) {
actualImageHeight = editingImage.naturalHeight;
}
else {
actualImageHeight = availableHeight;
// We must check ratio as well
var imageRatio = editingImage.naturalHeight / editingImage.naturalWidth;
var maxActualImageHeight = maxWidth * imageRatio;
if (maxActualImageHeight < actualImageHeight) {
actualImageHeight = maxActualImageHeight;
}
}
var popupHeightWImage = actualImageHeight + popupHeightNoImage;
var offsetCentered = topOffset - (popupHeightWImage / 2) -
(dims.backgroundPaddingHeight / 2);
// Min offset is 0
offsetCentered = offsetCentered > 0 ? offsetCentered : 0;
// Check that popup does not overflow editor
if (popupHeightWImage + offsetCentered > backgroundHeight) {
var newOffset = backgroundHeight - popupHeightWImage;
offsetCentered = newOffset < 0 ? 0 : newOffset;
}
popup.style.top = offsetCentered + 'px';
};
/**
* Set new image in editing tool
*
* @param {string} imgSrc Source of new image
*/
this.setImage = function (imgSrc) {
// Set new image
var darkroom = popup.querySelector('.darkroom-container');
if (darkroom) {
darkroom.parentNode.removeChild(darkroom);
}
editingImage.src = imgSrc;
imageLoading.classList.remove('hidden');
editingImage.classList.add('hidden');
editingContainer.appendChild(editingImage);
createDarkroom();
};
/**
* Show popup
*
* @param {Object} [offset] Offset that popup should center on.
* @param {string} [imageSrc] Source of image that will be edited
*/
this.show = function (offset, imageSrc) {
H5P.$body.get(0).appendChild(background);
setDarkroomDimensions();
if (imageSrc) {
// Load image editing scripts dynamically
if (!scriptsLoaded) {
editingImage.src = imageSrc;
loadScripts();
}
else {
self.setImage(imageSrc);
}
if (offset) {
var imageLoaded = function () {
this.adjustPopupOffset(offset);
editingImage.removeEventListener('load', imageLoaded);
}.bind(this);
editingImage.addEventListener('load', imageLoaded);
}
}
else {
H5P.$body.get(0).classList.add('h5p-editor-image-popup');
background.classList.remove('hidden');
self.trigger('initialized');
}
isShowing = true;
};
/**
* Hide popup
*/
this.hide = function () {
isShowing = false;
H5P.$body.get(0).classList.remove('h5p-editor-image-popup');
background.classList.add('hidden');
H5P.$body.get(0).removeChild(background);
};
/**
* Toggle popup visibility
*/
this.toggle = function () {
if (isShowing) {
this.hide();
} else {
this.show();
}
};
// Create header buttons
createButton('resetToOriginalLabel', 'h5p-editing-image-reset-button h5p-remove', function () {
self.trigger('resetImage');
isReset = true;
});
createButton('cancelLabel', 'h5p-editing-image-cancel-button', function () {
self.trigger('canceled');
self.hide();
});
createButton('saveLabel', 'h5p-editing-image-save-button h5p-done', function () {
saveImage();
self.hide();
});
}
ImageEditingPopup.prototype = Object.create(EventDispatcher.prototype);
ImageEditingPopup.prototype.constructor = ImageEditingPopup;
ImageEditingPopup.staticDimensions = {
backgroundPaddingWidth: 32,
backgroundPaddingHeight: 96,
darkroomPadding: 64,
darkroomToolbarHeight: 40,
maxScreenHeightPercentage: 0.65,
popupHeaderHeight: 59
};
return ImageEditingPopup;
}(H5P.jQuery, H5P.EventDispatcher));
PK m|KwJ scripts/h5peditor-coordinates.jsnu W+A var H5PEditor = H5PEditor || {};
var ns = H5PEditor;
/**
* Creates a coordinates picker for the form.
*
* @param {mixed} parent
* @param {object} field
* @param {mixed} params
* @param {function} setValue
* @returns {ns.Coordinates}
*/
ns.Coordinates = function (parent, field, params, setValue) {
var that = this;
this.parent = parent;
this.field = H5P.cloneObject(field, true); // TODO: Cloning is a quick fix, make sure this field doesn't change semantics!
// Find image field to get max size from.
// TODO: Use followField?
this.findImageField('max', function (field) {
if (field instanceof ns.File) {
if (field.params !== undefined) {
that.setMax(field.params.width, field.params.height);
}
field.changes.push(function (file) {
if (file === undefined) {
return;
}
// TODO: This callback should be removed when this item is removed.
that.setMax(file.params.width, file.params.height);
});
}
else if (field instanceof ns.Dimensions) {
if (field.params !== undefined) {
that.setMax(field.params.width, field.params.height);
}
field.changes.push(function (width, height) {
// TODO: This callback should be removed when this item is removed.
that.setMax(width, height);
});
}
});
this.params = params;
this.setValue = setValue;
};
/**
* Set max coordinates.
*
* @param {string} x
* @param {string} y
* @returns {undefined}
*/
ns.Coordinates.prototype.setMax = function (x, y) {
this.field.max = {
x: parseInt(x),
y: parseInt(y)
};
if (this.params !== undefined) {
this.$errors.html('');
this.validate();
}
};
/**
* Find the image field for the given property and then run the callback.
*
* @param {string} property
* @param {function} callback
* @returns {unresolved}
*/
ns.Coordinates.prototype.findImageField = function (property, callback) {
var that = this;
var str = 'string';
if (typeof this.field[property] !== str) {
return;
}
// Find field when tree is ready.
this.parent.ready(function () {
if (typeof that.field[property] !== str) {
if (that.field[property] !== undefined) {
callback(that.field[property]);
}
return; // We've already found this field before.
}
var path = that.field[property];
that.field[property] = ns.findField(that.field[property], that.parent);
if (!that.field[property]) {
throw ns.t('core', 'unknownFieldPath', {':path': path});
}
if (that.field[property].field.type !== 'image' && that.field[property].field.widget !== 'dimensions') {
throw ns.t('core', 'notImageOrDimensionsField', {':path': path});
}
callback(that.field[property]);
});
};
/**
* Append the field to the wrapper.
*
* @param {jQuery} $wrapper
* @returns {undefined}
*/
ns.Coordinates.prototype.appendTo = function ($wrapper) {
var that = this;
this.$item = ns.$(this.createHtml()).appendTo($wrapper);
this.$inputs = this.$item.find('input');
this.$errors = this.$item.children('.h5p-errors');
this.$inputs.change(function () {
// Validate
var value = that.validate();
if (value) {
// Set param
that.params = value;
that.setValue(that.field, value);
}
}).click(function () {
return false;
}).click(function () {
return false;
});
};
/**
* Create HTML for the coordinates picker.
*/
ns.Coordinates.prototype.createHtml = function () {
var input = ns.createText(this.params !== undefined ? this.params.x : undefined, 15, 'X') + ' , ' + ns.createText(this.params !== undefined ? this.params.y : undefined, 15, 'Y');
return ns.createFieldMarkup(this.field, input);
};
/**
* Validate the current values.
*/
ns.Coordinates.prototype.validate = function () {
var that = this;
var coordinates = {};
this.$inputs.each(function (i) {
var $input = ns.$(this);
var value = H5P.trim($input.val());
var property = i ? 'y' : 'x';
if (that.field.optional && !value.length) {
return true;
}
if ((that.field.optional === undefined || !that.field.optional) && !value.length) {
that.$errors.append(ns.createError(ns.t('core', 'requiredProperty', {':property': property})));
return false;
}
if (value.length && !value.match(new RegExp('^[0-9]+$'))) {
that.$errors.append(ns.createError(ns.t('core', 'onlyNumbers', {':property': property})));
return false;
}
value = parseInt(value);
if (that.field.max !== undefined && value > that.field.max[property]) {
that.$errors.append(ns.createError(ns.t('core', 'exceedsMax', {':property': property, ':max': that.field.max[property]})));
return false;
}
coordinates[property] = value;
});
return ns.checkErrors(this.$errors, this.$inputs, coordinates);
};
/**
* Remove this item.
*/
ns.Coordinates.prototype.remove = function () {
this.$item.remove();
};
// Tell the editor what widget we are.
ns.widgets.coordinates = ns.Coordinates;
PK m|K|, , scripts/h5p-hub-client.jsnu W+A !function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},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=20)}([function(e,t,n){"use strict";e.exports=n(23)},function(e,t,n){"use strict";"function"==typeof Symbol&&Symbol.iterator;e.exports=n(34)()},function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var o=function(){function e(e,t){for(var n=0;n
-1?t:e}function h(e,t){t=t||{};var n=t.body;if(e instanceof h){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new a(e.headers)),this.method=e.method,this.mode=e.mode,n||null==e._bodyInit||(n=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||"omit",!t.headers&&this.headers||(this.headers=new a(t.headers)),this.method=p(t.method||this.method||"GET"),this.mode=t.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&n)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(n)}function y(e){var t=new FormData;return e.trim().split("&").forEach(function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),o=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(o))}}),t}function m(e){var t=new a;return e.replace(/\r?\n[\t ]+/," ").split(/\r?\n/).forEach(function(e){var n=e.split(":"),r=n.shift().trim();if(r){var o=n.join(":").trim();t.append(r,o)}}),t}function b(e,t){t||(t={}),this.type="default",this.status="status"in t?t.status:200,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new a(t.headers),this.url=t.url||"",this._initBody(e)}if(!t.fetch){var v={searchParams:"URLSearchParams"in t,iterable:"Symbol"in t&&"iterator"in Symbol,blob:"FileReader"in t&&"Blob"in t&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in t,arrayBuffer:"ArrayBuffer"in t};if(v.arrayBuffer)var g=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],w=function(e){return e&&DataView.prototype.isPrototypeOf(e)},C=ArrayBuffer.isView||function(e){return e&&g.indexOf(Object.prototype.toString.call(e))>-1};a.prototype.append=function(e,t){e=n(e),t=r(t);var o=this.map[e];this.map[e]=o?o+","+t:t},a.prototype.delete=function(e){delete this.map[n(e)]},a.prototype.get=function(e){return e=n(e),this.has(e)?this.map[e]:null},a.prototype.has=function(e){return this.map.hasOwnProperty(n(e))},a.prototype.set=function(e,t){this.map[n(e)]=r(t)},a.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},a.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),o(e)},a.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),o(e)},a.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),o(e)},v.iterable&&(a.prototype[Symbol.iterator]=a.prototype.entries);var E=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];h.prototype.clone=function(){return new h(this,{body:this._bodyInit})},d.call(h.prototype),d.call(b.prototype),b.prototype.clone=function(){return new b(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new a(this.headers),url:this.url})},b.error=function(){var e=new b(null,{status:0,statusText:""});return e.type="error",e};var T=[301,302,303,307,308];b.redirect=function(e,t){if(-1===T.indexOf(t))throw new RangeError("Invalid status code");return new b(null,{status:t,headers:{location:e}})},t.Headers=a,t.Request=h,t.Response=b,t.fetch=function(t,n){return new e(function(e,r){var o=new h(t,n),a=new XMLHttpRequest;a.onload=function(){var t={status:a.status,statusText:a.statusText,headers:m(a.getAllResponseHeaders()||"")};t.url="responseURL"in a?a.responseURL:t.headers.get("X-Request-URL");var n="response"in a?a.response:a.responseText;e(new b(n,t))},a.onerror=function(){r(new TypeError("Network request failed"))},a.ontimeout=function(){r(new TypeError("Network request failed"))},a.open(o.method,o.url,!0),"include"===o.credentials&&(a.withCredentials=!0),"responseType"in a&&v.blob&&(a.responseType="blob"),o.headers.forEach(function(e,t){a.setRequestHeader(t,e)}),a.send(void 0===o._bodyInit?null:o._bodyInit)})},t.fetch.polyfill=!0}}("undefined"!=typeof self?self:void 0)}).call(t,n(37))},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var l=function(){function e(e,t){for(var n=0;ne.h5pMajorVersion||t.major===e.h5pMajorVersion&&t.minor>=e.h5pMinorVersion;return!e.isUpToDate&&e.installed&&e.canInstall&&n}Object.defineProperty(t,"__esModule",{value:!0}),t.default=r},function(e,t,n){"use strict";function r(e){return e.offsetWidth<=0&&e.offsetHeight<=0||"none"===e.style.display}function o(e){for(var t=e;t&&t!==document.body;){if(r(t))return!1;t=t.parentNode}return!0}function a(e,t){var n=e.nodeName.toLowerCase();return(u.test(n)&&!e.disabled||("a"===n?e.href||t:t))&&o(e)}function i(e){var t=e.getAttribute("tabindex");null===t&&(t=void 0);var n=isNaN(t);return(n||t>=0)&&a(e,!n)}function l(e){return[].slice.call(e.querySelectorAll("*"),0).filter(i)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=l;/*!
* Adapted from jQuery UI core
*
* http://jqueryui.com
*
* Copyright 2014 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/category/ui-core/
*/
var u=/input|select|textarea|button|object/;e.exports=t.default},function(e,t,n){"use strict";function r(e,t){if(!e||!e.length)throw new Error("react-modal: No elements were found for selector "+t+".")}function o(e){var t=e;if("string"==typeof t){var n=document.querySelectorAll(t);r(n,t),t="length"in n?n[0]:n}return f=t||f}function a(){return!(!document||!document.body)&&(o(document.body),!0)}function i(e){if(!e&&!f&&!a())throw new Error(["react-modal: Cannot fallback to `document.body`, because it is not","ready or available. If you are doing server-side rendering, use this","function to defined an element. `Modal.setAppElement(el)` to make","this accessible"].join(" "))}function l(e){i(e),(e||f).setAttribute("aria-hidden","true")}function u(e){i(e),(e||f).removeAttribute("aria-hidden")}function s(){f=null}function c(){f=document.body}Object.defineProperty(t,"__esModule",{value:!0}),t.assertNodeList=r,t.setElement=o,t.tryForceFallback=a,t.validateElement=i,t.hide=l,t.show=u,t.documentNotReadyOrSSRTesting=s,t.resetForTesting=c;var f=null},function(e,t,n){"use strict";function r(){return l}function o(e){return l[e]||(l[e]=0),l[e]+=1,e}function a(e){return l[e]&&(l[e]-=1),e}function i(){return Object.keys(l).reduce(function(e,t){return e+l[t]},0)}Object.defineProperty(t,"__esModule",{value:!0}),t.get=r,t.add=o,t.remove=a,t.totalCount=i;var l={}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.canUseDOM=void 0;var r=n(63),o=function(e){return e&&e.__esModule?e:{default:e}}(r),a=o.default,i=a.canUseDOM?window.HTMLElement:{};t.canUseDOM=a.canUseDOM;t.default=i},function(e,t){(function(t){e.exports=t}).call(t,{})},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var l=Object.assign||function(e){for(var t=1;tj.length&&j.push(e)}function p(e,t,n,o){var a=void 0===e?"undefined":v(e);if("undefined"!==a&&"boolean"!==a||(e=null),null===e||"string"===a||"number"===a||"object"===a&&e.$$typeof===I||"object"===a&&e.$$typeof===N)return n(o,e,""===t?"."+h(e,0):t),1;var i=0;if(t=""===t?".":t+":",Array.isArray(e))for(var l=0;lthis.eventPool.length&&this.eventPool.push(e)}function z(e){e.eventPool=[],e.getPooled=H,e.release=B}function V(e,t,n,r){return F.call(this,e,t,n,r)}function q(e,t,n,r){return F.call(this,e,t,n,r)}function W(e,t){switch(e){case"topKeyUp":return-1!==pr.indexOf(t.keyCode);case"topKeyDown":return 229!==t.keyCode;case"topKeyPress":case"topMouseDown":case"topBlur":return!0;default:return!1}}function K(e){return e=e.detail,"object"===(void 0===e?"undefined":vn(e))&&"data"in e?e.data:null}function G(e,t){switch(e){case"topCompositionEnd":return K(t);case"topKeyPress":return 32!==t.which?null:(Tr=!0,Cr);case"topTextInput":return e=t.data,e===Cr&&Tr?null:e;default:return null}}function Y(e,t){if(Sr)return"topCompositionEnd"===e||!hr&&W(e,t)?(e=L(),cr._root=null,cr._startText=null,cr._fallbackText=null,Sr=!1,e):null;switch(e){case"topPaste":return null;case"topKeyPress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1zr.length&&zr.push(e)}}}function je(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n["ms"+e]="MS"+t,n["O"+e]="o"+t.toLowerCase(),n}function Re(e){if(Gr[e])return Gr[e];if(!Kr[e])return e;var t,n=Kr[e];for(t in n)if(n.hasOwnProperty(t)&&t in Yr)return Gr[e]=n[t];return""}function De(e){return Object.prototype.hasOwnProperty.call(e,Xr)||(e[Xr]=$r++,Zr[e[Xr]]={}),Zr[e[Xr]]}function Ae(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function Le(e,t){var n=Ae(e);e=0;for(var r;n;){if(3===n.nodeType){if(r=e+n.textContent.length,e<=t&&r>=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Ae(n)}}function Ue(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&"text"===e.type||"textarea"===t||"true"===e.contentEditable)}function Fe(e,t){if(oo||null==to||to!==Sn())return null;var n=to;return"selectionStart"in n&&Ue(n)?n={start:n.selectionStart,end:n.selectionEnd}:window.getSelection?(n=window.getSelection(),n={anchorNode:n.anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset}):n=void 0,ro&&_n(ro,n)?null:(ro=n,e=F.getPooled(eo.select,no,e,t),e.type="select",e.target=to,R(e),e)}function He(e,t,n,r){return F.call(this,e,t,n,r)}function Be(e,t,n,r){return F.call(this,e,t,n,r)}function ze(e,t,n,r){return F.call(this,e,t,n,r)}function Ve(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,32<=e||13===e?e:0}function qe(e,t,n,r){return F.call(this,e,t,n,r)}function We(e,t,n,r){return F.call(this,e,t,n,r)}function Ke(e,t,n,r){return F.call(this,e,t,n,r)}function Ge(e,t,n,r){return F.call(this,e,t,n,r)}function Ye(e,t,n,r){return F.call(this,e,t,n,r)}function Qe(e){0>po||(e.current=fo[po],fo[po]=null,po--)}function Ze(e,t){po++,fo[po]=e.current,e.current=t}function $e(e){return Je(e)?wo:vo.current}function Xe(e,t){var n=e.type.contextTypes;if(!n)return kn;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,a={};for(o in n)a[o]=t[o];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=a),a}function Je(e){return 2===e.tag&&null!=e.type.childContextTypes}function et(e){Je(e)&&(Qe(go,e),Qe(vo,e))}function tt(e,t,n){null!=vo.cursor&&r("168"),Ze(vo,t,e),Ze(go,n,e)}function nt(e,t){var n=e.stateNode,o=e.type.childContextTypes;if("function"!=typeof n.getChildContext)return t;n=n.getChildContext();for(var a in n)a in o||r("108",Ce(e)||"Unknown",a);return Cn({},t,n)}function rt(e){if(!Je(e))return!1;var t=e.stateNode;return t=t&&t.__reactInternalMemoizedMergedChildContext||kn,wo=vo.current,Ze(vo,t,e),Ze(go,go.current,e),!0}function ot(e,t){var n=e.stateNode;if(n||r("169"),t){var o=nt(e,wo);n.__reactInternalMemoizedMergedChildContext=o,Qe(go,e),Qe(vo,e),Ze(vo,o,e)}else Qe(go,e);Ze(go,t,e)}function at(e,t,n){this.tag=e,this.key=t,this.stateNode=this.type=null,this.sibling=this.child=this.return=null,this.index=0,this.memoizedState=this.updateQueue=this.memoizedProps=this.pendingProps=this.ref=null,this.internalContextTag=n,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.expirationTime=0,this.alternate=null}function it(e,t,n){var r=e.alternate;return null===r?(r=new at(e.tag,e.key,e.internalContextTag),r.type=e.type,r.stateNode=e.stateNode,r.alternate=e,e.alternate=r):(r.effectTag=0,r.nextEffect=null,r.firstEffect=null,r.lastEffect=null),r.expirationTime=n,r.pendingProps=t,r.child=e.child,r.memoizedProps=e.memoizedProps,r.memoizedState=e.memoizedState,r.updateQueue=e.updateQueue,r.sibling=e.sibling,r.index=e.index,r.ref=e.ref,r}function lt(e,t,n){var o=void 0,a=e.type,i=e.key;return"function"==typeof a?(o=a.prototype&&a.prototype.isReactComponent?new at(2,i,t):new at(0,i,t),o.type=a,o.pendingProps=e.props):"string"==typeof a?(o=new at(5,i,t),o.type=a,o.pendingProps=e.props):"object"===(void 0===a?"undefined":vn(a))&&null!==a&&"number"==typeof a.tag?(o=a,o.pendingProps=e.props):r("130",null==a?a:void 0===a?"undefined":vn(a),""),o.expirationTime=n,o}function ut(e,t,n,r){return t=new at(10,r,t),t.pendingProps=e,t.expirationTime=n,t}function st(e,t,n){return t=new at(6,null,t),t.pendingProps=e,t.expirationTime=n,t}function ct(e,t,n){return t=new at(7,e.key,t),t.type=e.handler,t.pendingProps=e,t.expirationTime=n,t}function ft(e,t,n){return e=new at(9,null,t),e.expirationTime=n,e}function dt(e,t,n){return t=new at(4,e.key,t),t.pendingProps=e.children||[],t.expirationTime=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function pt(e){return function(t){try{return e(t)}catch(e){}}}function ht(e){if("undefined"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__)return!1;var t=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(t.isDisabled||!t.supportsFiber)return!0;try{var n=t.inject(e);Co=pt(function(e){return t.onCommitFiberRoot(n,e)}),Eo=pt(function(e){return t.onCommitFiberUnmount(n,e)})}catch(e){}return!0}function yt(e){"function"==typeof Co&&Co(e)}function mt(e){"function"==typeof Eo&&Eo(e)}function bt(e){return{baseState:e,expirationTime:0,first:null,last:null,callbackList:null,hasForceUpdate:!1,isInitialized:!1}}function vt(e,t){null===e.last?e.first=e.last=t:(e.last.next=t,e.last=t),(0===e.expirationTime||e.expirationTime>t.expirationTime)&&(e.expirationTime=t.expirationTime)}function gt(e,t){var n=e.alternate,r=e.updateQueue;null===r&&(r=e.updateQueue=bt(null)),null!==n?null===(e=n.updateQueue)&&(e=n.updateQueue=bt(null)):e=null,e=e!==r?e:null,null===e?vt(r,t):null===r.last||null===e.last?(vt(r,t),vt(e,t)):(vt(r,t),e.last=t)}function wt(e,t,n,r){return e=e.partialState,"function"==typeof e?e.call(t,n,r):e}function Ct(e,t,n,r,o,a){null!==e&&e.updateQueue===n&&(n=t.updateQueue={baseState:n.baseState,expirationTime:n.expirationTime,first:n.first,last:n.last,isInitialized:n.isInitialized,callbackList:null,hasForceUpdate:!1}),n.expirationTime=0,n.isInitialized?e=n.baseState:(e=n.baseState=t.memoizedState,n.isInitialized=!0);for(var i=!0,l=n.first,u=!1;null!==l;){var s=l.expirationTime;if(s>a){var c=n.expirationTime;(0===c||c>s)&&(n.expirationTime=s),u||(u=!0,n.baseState=e)}else u||(n.first=l.next,null===n.first&&(n.last=null)),l.isReplace?(e=wt(l,r,e,o),i=!0):(s=wt(l,r,e,o))&&(e=i?Cn({},e,s):Cn(e,s),i=!1),l.isForced&&(n.hasForceUpdate=!0),null!==l.callback&&(s=n.callbackList,null===s&&(s=n.callbackList=[]),s.push(l));l=l.next}return null!==n.callbackList?t.effectTag|=32:null!==n.first||n.hasForceUpdate||(t.updateQueue=null),u||(n.baseState=e),e}function Et(e,t){var n=e.callbackList;if(null!==n)for(e.callbackList=null,e=0;ed?(p=f,f=null):p=f.sibling;var h=m(e,f,i[d],u);if(null===h){null===f&&(f=p);break}t&&f&&null===h.alternate&&n(e,f),r=l(h,r,d),null===c?s=h:c.sibling=h,c=h,f=p}if(d===i.length)return o(e,f),s;if(null===f){for(;dp?(h=d,d=null):h=d.sibling;var g=m(e,d,v.value,s);if(null===g){d||(d=h);break}t&&d&&null===g.alternate&&n(e,d),i=l(g,i,p),null===f?c=g:f.sibling=g,f=g,d=h}if(v.done)return o(e,d),c;if(null===d){for(;!v.done;p++,v=u.next())null!==(v=y(e,v.value,s))&&(i=l(v,i,p),null===f?c=v:f.sibling=v,f=v);return c}for(d=a(e,d);!v.done;p++,v=u.next())null!==(v=b(d,e,p,v.value,s))&&(t&&null!==v.alternate&&d.delete(null===v.key?p:v.key),i=l(v,i,p),null===f?c=v:f.sibling=v,f=v);return t&&d.forEach(function(t){return n(e,t)}),c}return function(e,t,a,l){var s="object"===(void 0===a?"undefined":vn(a))&&null!==a;if(s)switch(a.$$typeof){case ho:e:{var c=a.key;for(s=t;null!==s;){if(s.key===c){if(10===s.tag?a.type===bo:s.type===a.type){o(e,s.sibling),t=i(s,a.type===bo?a.props.children:a.props,l),t.ref=Ot(s,a),t.return=e,e=t;break e}o(e,s);break}n(e,s),s=s.sibling}a.type===bo?(a=ut(a.props.children,e.internalContextTag,l,a.key),a.return=e,e=a):(l=lt(a,e.internalContextTag,l),l.ref=Ot(t,a),l.return=e,e=l)}return u(e);case yo:e:{for(s=a.key;null!==t;){if(t.key===s){if(7===t.tag){o(e,t.sibling),a=i(t,a,l),a.return=e,e=a;break e}o(e,t);break}n(e,t),t=t.sibling}a=ct(a,e.internalContextTag,l),a.return=e,e=a}return u(e);case mo:e:{if(null!==t){if(9===t.tag){o(e,t.sibling),t=i(t,null,l),t.type=a.value,t.return=e,e=t;break e}o(e,t)}t=ft(a,e.internalContextTag,l),t.type=a.value,t.return=e,e=t}return u(e);case To:e:{for(s=a.key;null!==t;){if(t.key===s){if(4===t.tag&&t.stateNode.containerInfo===a.containerInfo&&t.stateNode.implementation===a.implementation){o(e,t.sibling),a=i(t,a.children||[],l),a.return=e,e=a;break e}o(e,t);break}n(e,t),t=t.sibling}a=dt(a,e.internalContextTag,l),a.return=e,e=a}return u(e)}if("string"==typeof a||"number"==typeof a)return a=""+a,null!==t&&6===t.tag?(o(e,t.sibling),a=i(t,a,l)):(o(e,t),a=st(a,e.internalContextTag,l)),a.return=e,e=a,u(e);if(So(a))return v(e,t,a,l);if(_t(a))return g(e,t,a,l);if(s&&xt(e,a),void 0===a)switch(e.tag){case 2:case 1:a=e.type,r("152",a.displayName||a.name||"Component")}return o(e,t)}}function Pt(e,t,n,o,a){function i(e,t,n){l(e,t,n,t.expirationTime)}function l(e,t,n,r){t.child=null===e?ko(t,t.child,n,r):e.child===t.child?Oo(t,t.child,n,r):xo(t,t.child,n,r)}function u(e,t){var n=t.ref;null===n||e&&e.ref===n||(t.effectTag|=128)}function s(e,t,n,r){if(u(e,t),!n)return r&&ot(t,!1),f(e,t);n=t.stateNode,Br.current=t;var o=n.render();return t.effectTag|=1,i(e,t,o),t.memoizedState=n.state,t.memoizedProps=n.props,r&&ot(t,!0),t.child}function c(e){var t=e.stateNode;t.pendingContext?tt(e,t.pendingContext,t.pendingContext!==t.context):t.context&&tt(e,t.context,!1),b(e,t.containerInfo)}function f(e,t){if(null!==e&&t.child!==e.child&&r("153"),null!==t.child){e=t.child;var n=it(e,e.pendingProps,e.expirationTime);for(t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,n=n.sibling=it(e,e.pendingProps,e.expirationTime),n.return=t;n.sibling=null}return t.child}function d(e,t){switch(t.tag){case 3:c(t);break;case 2:rt(t);break;case 4:b(t,t.stateNode.containerInfo)}return null}var p=e.shouldSetTextContent,h=e.useSyncScheduling,y=e.shouldDeprioritizeSubtree,m=t.pushHostContext,b=t.pushHostContainer,v=n.enterHydrationState,g=n.resetHydrationState,w=n.tryToClaimNextHydratableInstance;e=Tt(o,a,function(e,t){e.memoizedProps=t},function(e,t){e.memoizedState=t});var C=e.adoptClassInstance,E=e.constructClassInstance,T=e.mountClassInstance,S=e.updateClassInstance;return{beginWork:function(e,t,n){if(0===t.expirationTime||t.expirationTime>n)return d(e,t);switch(t.tag){case 0:null!==e&&r("155");var o=t.type,a=t.pendingProps,l=$e(t);return l=Xe(t,l),o=o(a,l),t.effectTag|=1,"object"===(void 0===o?"undefined":vn(o))&&null!==o&&"function"==typeof o.render?(t.tag=2,a=rt(t),C(t,o),T(t,n),t=s(e,t,!0,a)):(t.tag=1,i(e,t,o),t.memoizedProps=a,t=t.child),t;case 1:e:{if(a=t.type,n=t.pendingProps,o=t.memoizedProps,go.current)null===n&&(n=o);else if(null===n||o===n){t=f(e,t);break e}o=$e(t),o=Xe(t,o),a=a(n,o),t.effectTag|=1,i(e,t,a),t.memoizedProps=n,t=t.child}return t;case 2:return a=rt(t),o=void 0,null===e?t.stateNode?r("153"):(E(t,t.pendingProps),T(t,n),o=!0):o=S(e,t,n),s(e,t,o,a);case 3:return c(t),a=t.updateQueue,null!==a?(o=t.memoizedState,a=Ct(e,t,a,null,null,n),o===a?(g(),t=f(e,t)):(o=a.element,l=t.stateNode,(null===e||null===e.child)&&l.hydrate&&v(t)?(t.effectTag|=2,t.child=ko(t,t.child,o,n)):(g(),i(e,t,o)),t.memoizedState=a,t=t.child)):(g(),t=f(e,t)),t;case 5:m(t),null===e&&w(t),a=t.type;var _=t.memoizedProps;return o=t.pendingProps,null===o&&null===(o=_)&&r("154"),l=null!==e?e.memoizedProps:null,go.current||null!==o&&_!==o?(_=o.children,p(a,o)?_=null:l&&p(a,l)&&(t.effectTag|=16),u(e,t),2147483647!==n&&!h&&y(a,o)?(t.expirationTime=2147483647,t=null):(i(e,t,_),t.memoizedProps=o,t=t.child)):t=f(e,t),t;case 6:return null===e&&w(t),e=t.pendingProps,null===e&&(e=t.memoizedProps),t.memoizedProps=e,null;case 8:t.tag=7;case 7:return a=t.pendingProps,go.current?null===a&&null===(a=e&&e.memoizedProps)&&r("154"):null!==a&&t.memoizedProps!==a||(a=t.memoizedProps),o=a.children,t.stateNode=null===e?ko(t,t.stateNode,o,n):e.child===t.child?Oo(t,t.stateNode,o,n):xo(t,t.stateNode,o,n),t.memoizedProps=a,t.stateNode;case 9:return null;case 4:e:{if(b(t,t.stateNode.containerInfo),a=t.pendingProps,go.current)null===a&&null==(a=e&&e.memoizedProps)&&r("154");else if(null===a||t.memoizedProps===a){t=f(e,t);break e}null===e?t.child=xo(t,t.child,a,n):i(e,t,a),t.memoizedProps=a,t=t.child}return t;case 10:e:{if(n=t.pendingProps,go.current)null===n&&(n=t.memoizedProps);else if(null===n||t.memoizedProps===n){t=f(e,t);break e}i(e,t,n),t.memoizedProps=n,t=t.child}return t;default:r("156")}},beginFailedWork:function(e,t,n){switch(t.tag){case 2:rt(t);break;case 3:c(t);break;default:r("157")}return t.effectTag|=64,null===e?t.child=null:t.child!==e.child&&(t.child=e.child),0===t.expirationTime||t.expirationTime>n?d(e,t):(t.firstEffect=null,t.lastEffect=null,l(e,t,null,n),2===t.tag&&(e=t.stateNode,t.memoizedProps=e.props,t.memoizedState=e.state),t.child)}}}function It(e,t,n){function o(e){e.effectTag|=4}var a=e.createInstance,i=e.createTextInstance,l=e.appendInitialChild,u=e.finalizeInitialChildren,s=e.prepareUpdate,c=e.persistence,f=t.getRootHostContainer,d=t.popHostContext,p=t.getHostContext,h=t.popHostContainer,y=n.prepareToHydrateHostInstance,m=n.prepareToHydrateHostTextInstance,b=n.popHydrationState,v=void 0,g=void 0,w=void 0;return e.mutation?(v=function(){},g=function(e,t,n){(t.updateQueue=n)&&o(t)},w=function(e,t,n,r){n!==r&&o(t)}):r(c?"235":"236"),{completeWork:function(e,t,n){var c=t.pendingProps;switch(null===c?c=t.memoizedProps:2147483647===t.expirationTime&&2147483647!==n||(t.pendingProps=null),t.tag){case 1:return null;case 2:return et(t),null;case 3:return h(t),Qe(go,t),Qe(vo,t),c=t.stateNode,c.pendingContext&&(c.context=c.pendingContext,c.pendingContext=null),null!==e&&null!==e.child||(b(t),t.effectTag&=-3),v(t),null;case 5:d(t),n=f();var C=t.type;if(null!==e&&null!=t.stateNode){var E=e.memoizedProps,T=t.stateNode,S=p();T=s(T,C,E,c,n,S),g(e,t,T,C,E,c,n),e.ref!==t.ref&&(t.effectTag|=128)}else{if(!c)return null===t.stateNode&&r("166"),null;if(e=p(),b(t))y(t,n,e)&&o(t);else{e=a(C,c,n,e,t);e:for(E=t.child;null!==E;){if(5===E.tag||6===E.tag)l(e,E.stateNode);else if(4!==E.tag&&null!==E.child){E.child.return=E,E=E.child;continue}if(E===t)break;for(;null===E.sibling;){if(null===E.return||E.return===t)break e;E=E.return}E.sibling.return=E.return,E=E.sibling}u(e,C,c,n)&&o(t),t.stateNode=e}null!==t.ref&&(t.effectTag|=128)}return null;case 6:if(e&&null!=t.stateNode)w(e,t,e.memoizedProps,c);else{if("string"!=typeof c)return null===t.stateNode&&r("166"),null;e=f(),n=p(),b(t)?m(t)&&o(t):t.stateNode=i(c,e,n,t)}return null;case 7:(c=t.memoizedProps)||r("165"),t.tag=8,C=[];e:for((E=t.stateNode)&&(E.return=t);null!==E;){if(5===E.tag||6===E.tag||4===E.tag)r("247");else if(9===E.tag)C.push(E.type);else if(null!==E.child){E.child.return=E,E=E.child;continue}for(;null===E.sibling;){if(null===E.return||E.return===t)break e;E=E.return}E.sibling.return=E.return,E=E.sibling}return E=c.handler,c=E(c.props,C),t.child=Oo(t,null!==e?e.child:null,c,n),t.child;case 8:return t.tag=7,null;case 9:case 10:return null;case 4:return h(t),v(t),null;case 0:r("167");default:r("156")}}}}function Nt(e,t){function n(e){var n=e.ref;if(null!==n)try{n(null)}catch(n){t(e,n)}}function o(e){switch("function"==typeof mt&&mt(e),e.tag){case 2:n(e);var r=e.stateNode;if("function"==typeof r.componentWillUnmount)try{r.props=e.memoizedProps,r.state=e.memoizedState,r.componentWillUnmount()}catch(n){t(e,n)}break;case 5:n(e);break;case 7:a(e.stateNode);break;case 4:s&&l(e)}}function a(e){for(var t=e;;)if(o(t),null===t.child||s&&4===t.tag){if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return;t=t.return}t.sibling.return=t.return,t=t.sibling}else t.child.return=t,t=t.child}function i(e){return 5===e.tag||3===e.tag||4===e.tag}function l(e){for(var t=e,n=!1,i=void 0,l=void 0;;){if(!n){n=t.return;e:for(;;){switch(null===n&&r("160"),n.tag){case 5:i=n.stateNode,l=!1;break e;case 3:case 4:i=n.stateNode.containerInfo,l=!0;break e}n=n.return}n=!0}if(5===t.tag||6===t.tag)a(t),l?g(i,t.stateNode):v(i,t.stateNode);else if(4===t.tag?i=t.stateNode.containerInfo:o(t),null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return;t=t.return,4===t.tag&&(n=!1)}t.sibling.return=t.return,t=t.sibling}}var u=e.getPublicInstance,s=e.mutation;e=e.persistence,s||r(e?"235":"236");var c=s.commitMount,f=s.commitUpdate,d=s.resetTextContent,p=s.commitTextUpdate,h=s.appendChild,y=s.appendChildToContainer,m=s.insertBefore,b=s.insertInContainerBefore,v=s.removeChild,g=s.removeChildFromContainer;return{commitResetTextContent:function(e){d(e.stateNode)},commitPlacement:function(e){e:{for(var t=e.return;null!==t;){if(i(t)){var n=t;break e}t=t.return}r("160"),n=void 0}var o=t=void 0;switch(n.tag){case 5:t=n.stateNode,o=!1;break;case 3:case 4:t=n.stateNode.containerInfo,o=!0;break;default:r("161")}16&n.effectTag&&(d(t),n.effectTag&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||i(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag;){if(2&n.effectTag)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.effectTag)){n=n.stateNode;break e}}for(var a=e;;){if(5===a.tag||6===a.tag)n?o?b(t,a.stateNode,n):m(t,a.stateNode,n):o?y(t,a.stateNode):h(t,a.stateNode);else if(4!==a.tag&&null!==a.child){a.child.return=a,a=a.child;continue}if(a===e)break;for(;null===a.sibling;){if(null===a.return||a.return===e)return;a=a.return}a.sibling.return=a.return,a=a.sibling}},commitDeletion:function(e){l(e),e.return=null,e.child=null,e.alternate&&(e.alternate.child=null,e.alternate.return=null)},commitWork:function(e,t){switch(t.tag){case 2:break;case 5:var n=t.stateNode;if(null!=n){var o=t.memoizedProps;e=null!==e?e.memoizedProps:o;var a=t.type,i=t.updateQueue;t.updateQueue=null,null!==i&&f(n,i,a,e,o,t)}break;case 6:null===t.stateNode&&r("162"),n=t.memoizedProps,p(t.stateNode,null!==e?e.memoizedProps:n,n);break;case 3:break;default:r("163")}},commitLifeCycles:function(e,t){switch(t.tag){case 2:var n=t.stateNode;if(4&t.effectTag)if(null===e)n.props=t.memoizedProps,n.state=t.memoizedState,n.componentDidMount();else{var o=e.memoizedProps;e=e.memoizedState,n.props=t.memoizedProps,n.state=t.memoizedState,n.componentDidUpdate(o,e)}t=t.updateQueue,null!==t&&Et(t,n);break;case 3:n=t.updateQueue,null!==n&&Et(n,null!==t.child?t.child.stateNode:null);break;case 5:n=t.stateNode,null===e&&4&t.effectTag&&c(n,t.type,t.memoizedProps,t);break;case 6:case 4:break;default:r("163")}},commitAttachRef:function(e){var t=e.ref;if(null!==t){var n=e.stateNode;switch(e.tag){case 5:t(u(n));break;default:t(n)}}},commitDetachRef:function(e){null!==(e=e.ref)&&e(null)}}}function Mt(e){function t(e){return e===Po&&r("174"),e}var n=e.getChildHostContext,o=e.getRootHostContext,a={current:Po},i={current:Po},l={current:Po};return{getHostContext:function(){return t(a.current)},getRootHostContainer:function(){return t(l.current)},popHostContainer:function(e){Qe(a,e),Qe(i,e),Qe(l,e)},popHostContext:function(e){i.current===e&&(Qe(a,e),Qe(i,e))},pushHostContainer:function(e,t){Ze(l,t,e),t=o(t),Ze(i,e,e),Ze(a,t,e)},pushHostContext:function(e){var r=t(l.current),o=t(a.current);r=n(o,e.type,r),o!==r&&(Ze(i,e,e),Ze(a,r,e))},resetHostContainer:function(){a.current=Po,l.current=Po}}}function jt(e){function t(e,t){var n=new at(5,null,0);n.type="DELETED",n.stateNode=t,n.return=e,n.effectTag=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function n(e,t){switch(e.tag){case 5:return null!==(t=i(t,e.type,e.pendingProps))&&(e.stateNode=t,!0);case 6:return null!==(t=l(t,e.pendingProps))&&(e.stateNode=t,!0);default:return!1}}function o(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag;)e=e.return;d=e}var a=e.shouldSetTextContent;if(!(e=e.hydration))return{enterHydrationState:function(){return!1},resetHydrationState:function(){},tryToClaimNextHydratableInstance:function(){},prepareToHydrateHostInstance:function(){r("175")},prepareToHydrateHostTextInstance:function(){r("176")},popHydrationState:function(){return!1}};var i=e.canHydrateInstance,l=e.canHydrateTextInstance,u=e.getNextHydratableSibling,s=e.getFirstHydratableChild,c=e.hydrateInstance,f=e.hydrateTextInstance,d=null,p=null,h=!1;return{enterHydrationState:function(e){return p=s(e.stateNode.containerInfo),d=e,h=!0},resetHydrationState:function(){p=d=null,h=!1},tryToClaimNextHydratableInstance:function(e){if(h){var r=p;if(r){if(!n(e,r)){if(!(r=u(r))||!n(e,r))return e.effectTag|=2,h=!1,void(d=e);t(d,p)}d=e,p=s(r)}else e.effectTag|=2,h=!1,d=e}},prepareToHydrateHostInstance:function(e,t,n){return t=c(e.stateNode,e.type,e.memoizedProps,t,n,e),e.updateQueue=t,null!==t},prepareToHydrateHostTextInstance:function(e){return f(e.stateNode,e.memoizedProps,e)},popHydrationState:function(e){if(e!==d)return!1;if(!h)return o(e),h=!0,!1;var n=e.type;if(5!==e.tag||"head"!==n&&"body"!==n&&!a(n,e.memoizedProps))for(n=p;n;)t(e,n),n=u(n);return o(e),p=d?u(e.stateNode):null,!0}}}function Rt(e){function t(e){re=G=!0;var t=e.stateNode;if(t.current===e&&r("177"),t.isReadyForCommit=!1,Br.current=null,1i.expirationTime)&&(a=i.expirationTime),i=i.sibling;o.expirationTime=a}if(null!==t)return t;if(null!==n&&(null===n.firstEffect&&(n.firstEffect=e.firstEffect),null!==e.lastEffect&&(null!==n.lastEffect&&(n.lastEffect.nextEffect=e.firstEffect),n.lastEffect=e.lastEffect),1e))if(Z<=W)for(;null!==Y;)Y=s(Y)?a(Y):o(Y);else for(;null!==Y&&!C();)Y=s(Y)?a(Y):o(Y)}else if(!(0===Z||Z>e))if(Z<=W)for(;null!==Y;)Y=o(Y);else for(;null!==Y&&!C();)Y=o(Y)}function l(e,t){if(G&&r("243"),G=!0,e.isReadyForCommit=!1,e!==Q||t!==Z||null===Y){for(;-1t)&&(e.expirationTime=t),null!==e.alternate&&(0===e.alternate.expirationTime||e.alternate.expirationTime>t)&&(e.alternate.expirationTime=t),null===e.return){if(3!==e.tag)break;var n=e.stateNode;!G&&n===Q&&t<=Z&&(Y=Q=null,Z=0);var o=t;if(ve>be&&r("185"),null===n.nextScheduledRoot)n.remainingExpirationTime=o,null===ie?(ae=ie=n,n.nextScheduledRoot=n):(ie=ie.nextScheduledRoot=n,ie.nextScheduledRoot=ae);else{var a=n.remainingExpirationTime;(0===a||oge)&&(fe=!0)}function E(e){null===se&&r("246"),se.remainingExpirationTime=0,de||(de=!0,pe=e)}var T=Mt(e),S=jt(e),_=T.popHostContainer,O=T.popHostContext,x=T.resetHostContainer,k=Pt(e,T,S,p,d),P=k.beginWork,I=k.beginFailedWork,N=It(e,T,S).completeWork;T=Nt(e,u);var M=T.commitResetTextContent,j=T.commitPlacement,R=T.commitDeletion,D=T.commitWork,A=T.commitLifeCycles,L=T.commitAttachRef,U=T.commitDetachRef,F=e.now,H=e.scheduleDeferredCallback,B=e.useSyncScheduling,z=e.prepareForCommit,V=e.resetAfterCommit,q=F(),W=2,K=0,G=!1,Y=null,Q=null,Z=0,$=null,X=null,J=null,ee=null,te=null,ne=!1,re=!1,oe=!1,ae=null,ie=null,le=!1,ue=!1,se=null,ce=0,fe=!1,de=!1,pe=null,he=null,ye=!1,me=!1,be=1e3,ve=0,ge=1;return{computeAsyncExpiration:f,computeExpirationForFiber:d,scheduleWork:p,batchedUpdates:function(e,t){var n=ye;ye=!0;try{return e(t)}finally{(ye=n)||ue||g(1,null)}},unbatchedUpdates:function(e){if(ye&&!me){me=!0;try{return e()}finally{me=!1}}return e()},flushSync:function(e){var t=ye;ye=!0;try{e:{var n=K;K=1;try{var o=e();break e}finally{K=n}o=void 0}return o}finally{ye=t,ue&&r("187"),g(1,null)}},deferredUpdates:function(e){var t=K;K=f();try{return e()}finally{K=t}}}}function Dt(e){function t(e){return e=Oe(e),null===e?null:e.stateNode}var n=e.getPublicInstance;e=Rt(e);var o=e.computeAsyncExpiration,a=e.computeExpirationForFiber,i=e.scheduleWork;return{createContainer:function(e,t){var n=new at(3,null,0);return e={current:n,containerInfo:e,pendingChildren:null,remainingExpirationTime:0,isReadyForCommit:!1,finishedWork:null,context:null,pendingContext:null,hydrate:t,nextScheduledRoot:null},n.stateNode=e},updateContainer:function(e,t,n,l){var u=t.current;if(n){n=n._reactInternalFiber;var s;e:{for(2===Ee(n)&&2===n.tag||r("170"),s=n;3!==s.tag;){if(Je(s)){s=s.stateNode.__reactInternalMemoizedMergedChildContext;break e}(s=s.return)||r("171")}s=s.stateNode.context}n=Je(n)?nt(n,s):s}else n=kn;null===t.context?t.context=n:t.pendingContext=n,t=l,t=void 0===t?null:t,l=null!=e&&null!=e.type&&null!=e.type.prototype&&!0===e.type.prototype.unstable_isAsyncReactComponent?o():a(u),gt(u,{expirationTime:l,partialState:{element:e},callback:t,isReplace:!1,isForced:!1,nextCallback:null,next:null}),i(u,l)},batchedUpdates:e.batchedUpdates,unbatchedUpdates:e.unbatchedUpdates,deferredUpdates:e.deferredUpdates,flushSync:e.flushSync,getPublicRootInstance:function(e){if(e=e.current,!e.child)return null;switch(e.child.tag){case 5:return n(e.child.stateNode);default:return e.child.stateNode}},findHostInstance:t,findHostInstanceWithNoPortals:function(e){return e=xe(e),null===e?null:e.stateNode},injectIntoDevTools:function(e){var n=e.findFiberByHostInstance;return ht(Cn({},e,{findHostInstanceByFiber:function(e){return t(e)},findFiberByHostInstance:function(e){return n?n(e):null}}))}}}function At(e){return!!Go.hasOwnProperty(e)||!Ko.hasOwnProperty(e)&&(Wo.test(e)?Go[e]=!0:(Ko[e]=!0,!1))}function Lt(e,t,n){var r=i(t);if(r&&a(t,n)){var o=r.mutationMethod;o?o(e,n):null==n||r.hasBooleanValue&&!n||r.hasNumericValue&&isNaN(n)||r.hasPositiveNumericValue&&1>n||r.hasOverloadedBooleanValue&&!1===n?Ft(e,t):r.mustUseProperty?e[r.propertyName]=n:(t=r.attributeName,(o=r.attributeNamespace)?e.setAttributeNS(o,t,""+n):r.hasBooleanValue||r.hasOverloadedBooleanValue&&!0===n?e.setAttribute(t,""):e.setAttribute(t,""+n))}else Ut(e,t,a(t,n)?n:null)}function Ut(e,t,n){At(t)&&(null==n?e.removeAttribute(t):e.setAttribute(t,""+n))}function Ft(e,t){var n=i(t);n?(t=n.mutationMethod)?t(e,void 0):n.mustUseProperty?e[n.propertyName]=!n.hasBooleanValue&&"":e.removeAttribute(n.attributeName):e.removeAttribute(t)}function Ht(e,t){var n=t.value,r=t.checked;return Cn({type:void 0,step:void 0,min:void 0,max:void 0},t,{defaultChecked:void 0,defaultValue:void 0,value:null!=n?n:e._wrapperState.initialValue,checked:null!=r?r:e._wrapperState.initialChecked})}function Bt(e,t){var n=t.defaultValue;e._wrapperState={initialChecked:null!=t.checked?t.checked:t.defaultChecked,initialValue:null!=t.value?t.value:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function zt(e,t){var n=t.checked;null!=n&&Lt(e,"checked",n||!1),n=t.value,null!=n?0===n&&""===e.value?e.value="0":"number"===t.type?(t=parseFloat(e.value)||0,(n!=t||n==t&&e.value!=n)&&(e.value=""+n)):e.value!==""+n&&(e.value=""+n):(null==t.value&&null!=t.defaultValue&&e.defaultValue!==""+t.defaultValue&&(e.defaultValue=""+t.defaultValue),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked))}function Vt(e,t){switch(t.type){case"submit":case"reset":break;case"color":case"date":case"datetime":case"datetime-local":case"month":case"time":case"week":e.value="",e.value=e.defaultValue;break;default:e.value=e.value}t=e.name,""!==t&&(e.name=""),e.defaultChecked=!e.defaultChecked,e.defaultChecked=!e.defaultChecked,""!==t&&(e.name=t)}function qt(e){var t="";return gn.Children.forEach(e,function(e){null==e||"string"!=typeof e&&"number"!=typeof e||(t+=e)}),t}function Wt(e,t){return e=Cn({children:void 0},t),(t=qt(t.children))&&(e.children=t),e}function Kt(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o=t.length||r("93"),t=t[0]),n=""+t),null==n&&(n=""),o=n),e._wrapperState={initialValue:""+o}}function Zt(e,t){var n=t.value;null!=n&&(n=""+n,n!==e.value&&(e.value=n),null==t.defaultValue&&(e.defaultValue=n)),null!=t.defaultValue&&(e.defaultValue=t.defaultValue)}function $t(e){var t=e.textContent;t===e._wrapperState.initialValue&&(e.value=t)}function Xt(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function Jt(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?Xt(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}function en(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}function tn(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),o=n,a=t[n];o=null==a||"boolean"==typeof a||""===a?"":r||"number"!=typeof a||0===a||Jo.hasOwnProperty(o)&&Jo[o]?(""+a).trim():a+"px","float"===n&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}function nn(e,t,n){t&&(ta[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML)&&r("137",e,n()),null!=t.dangerouslySetInnerHTML&&(null!=t.children&&r("60"),"object"===vn(t.dangerouslySetInnerHTML)&&"__html"in t.dangerouslySetInnerHTML||r("61")),null!=t.style&&"object"!==vn(t.style)&&r("62",n()))}function rn(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function on(e,t){e=9===e.nodeType||11===e.nodeType?e:e.ownerDocument;var n=De(e);t=Zn[t];for(var r=0;r<\/script>",e=e.removeChild(e.firstChild)):e="string"==typeof t.is?n.createElement(e,{is:t.is}):n.createElement(e):e=n.createElementNS(r,e),e}function ln(e,t){return(9===t.nodeType?t:t.ownerDocument).createTextNode(e)}function un(e,t,n,r){var o=rn(t,n);switch(t){case"iframe":case"object":Ie("topLoad","load",e);var a=n;break;case"video":case"audio":for(a in oa)oa.hasOwnProperty(a)&&Ie(a,oa[a],e);a=n;break;case"source":Ie("topError","error",e),a=n;break;case"img":case"image":Ie("topError","error",e),Ie("topLoad","load",e),a=n;break;case"form":Ie("topReset","reset",e),Ie("topSubmit","submit",e),a=n;break;case"details":Ie("topToggle","toggle",e),a=n;break;case"input":Bt(e,n),a=Ht(e,n),Ie("topInvalid","invalid",e),on(r,"onChange");break;case"option":a=Wt(e,n);break;case"select":Gt(e,n),a=Cn({},n,{value:void 0}),Ie("topInvalid","invalid",e),on(r,"onChange");break;case"textarea":Qt(e,n),a=Yt(e,n),Ie("topInvalid","invalid",e),on(r,"onChange");break;default:a=n}nn(t,a,ra);var i,l=a;for(i in l)if(l.hasOwnProperty(i)){var u=l[i];"style"===i?tn(e,u,ra):"dangerouslySetInnerHTML"===i?null!=(u=u?u.__html:void 0)&&Zo(e,u):"children"===i?"string"==typeof u?("textarea"!==t||""!==u)&&Xo(e,u):"number"==typeof u&&Xo(e,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(Qn.hasOwnProperty(i)?null!=u&&on(r,i):o?Ut(e,i,u):null!=u&&Lt(e,i,u))}switch(t){case"input":ae(e),Vt(e,n);break;case"textarea":ae(e),$t(e,n);break;case"option":null!=n.value&&e.setAttribute("value",n.value);break;case"select":e.multiple=!!n.multiple,t=n.value,null!=t?Kt(e,!!n.multiple,t,!1):null!=n.defaultValue&&Kt(e,!!n.multiple,n.defaultValue,!0);break;default:"function"==typeof a.onClick&&(e.onclick=En)}}function sn(e,t,n,r,o){var a=null;switch(t){case"input":n=Ht(e,n),r=Ht(e,r),a=[];break;case"option":n=Wt(e,n),r=Wt(e,r),a=[];break;case"select":n=Cn({},n,{value:void 0}),r=Cn({},r,{value:void 0}),a=[];break;case"textarea":n=Yt(e,n),r=Yt(e,r),a=[];break;default:"function"!=typeof n.onClick&&"function"==typeof r.onClick&&(e.onclick=En)}nn(t,r,ra);var i,l;e=null;for(i in n)if(!r.hasOwnProperty(i)&&n.hasOwnProperty(i)&&null!=n[i])if("style"===i)for(l in t=n[i])t.hasOwnProperty(l)&&(e||(e={}),e[l]="");else"dangerouslySetInnerHTML"!==i&&"children"!==i&&"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(Qn.hasOwnProperty(i)?a||(a=[]):(a=a||[]).push(i,null));for(i in r){var u=r[i];if(t=null!=n?n[i]:void 0,r.hasOwnProperty(i)&&u!==t&&(null!=u||null!=t))if("style"===i)if(t){for(l in t)!t.hasOwnProperty(l)||u&&u.hasOwnProperty(l)||(e||(e={}),e[l]="");for(l in u)u.hasOwnProperty(l)&&t[l]!==u[l]&&(e||(e={}),e[l]=u[l])}else e||(a||(a=[]),a.push(i,e)),e=u;else"dangerouslySetInnerHTML"===i?(u=u?u.__html:void 0,t=t?t.__html:void 0,null!=u&&t!==u&&(a=a||[]).push(i,""+u)):"children"===i?t===u||"string"!=typeof u&&"number"!=typeof u||(a=a||[]).push(i,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&(Qn.hasOwnProperty(i)?(null!=u&&on(o,i),a||t===u||(a=[])):(a=a||[]).push(i,u))}return e&&(a=a||[]).push("style",e),a}function cn(e,t,n,r,o){rn(n,r),r=rn(n,o);for(var a=0;a=u.hasBooleanValue+u.hasNumericValue+u.hasOverloadedBooleanValue||r("50",l),i.hasOwnProperty(l)&&(u.attributeName=i[l]),a.hasOwnProperty(l)&&(u.attributeNamespace=a[l]),e.hasOwnProperty(l)&&(u.mutationMethod=e[l]),Nn[l]=u}}},Nn={},Mn=In,jn=Mn.MUST_USE_PROPERTY,Rn=Mn.HAS_BOOLEAN_VALUE,Dn=Mn.HAS_NUMERIC_VALUE,An=Mn.HAS_POSITIVE_NUMERIC_VALUE,Ln=Mn.HAS_OVERLOADED_BOOLEAN_VALUE,Un=Mn.HAS_STRING_BOOLEAN_VALUE,Fn={Properties:{allowFullScreen:Rn,async:Rn,autoFocus:Rn,autoPlay:Rn,capture:Ln,checked:jn|Rn,cols:An,contentEditable:Un,controls:Rn,default:Rn,defer:Rn,disabled:Rn,download:Ln,draggable:Un,formNoValidate:Rn,hidden:Rn,loop:Rn,multiple:jn|Rn,muted:jn|Rn,noValidate:Rn,open:Rn,playsInline:Rn,readOnly:Rn,required:Rn,reversed:Rn,rows:An,rowSpan:Dn,scoped:Rn,seamless:Rn,selected:jn|Rn,size:An,start:Dn,span:An,spellCheck:Un,style:0,tabIndex:0,itemScope:Rn,acceptCharset:0,className:0,htmlFor:0,httpEquiv:0,value:Un},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMMutationMethods:{value:function(e,t){if(null==t)return e.removeAttribute("value");"number"!==e.type||!1===e.hasAttribute("value")?e.setAttribute("value",""+t):e.validity&&!e.validity.badInput&&e.ownerDocument.activeElement!==e&&e.setAttribute("value",""+t)}}},Hn=Mn.HAS_STRING_BOOLEAN_VALUE,Bn={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"},zn={Properties:{autoReverse:Hn,externalResourcesRequired:Hn,preserveAlpha:Hn},DOMAttributeNames:{autoReverse:"autoReverse",externalResourcesRequired:"externalResourcesRequired",preserveAlpha:"preserveAlpha"},DOMAttributeNamespaces:{xlinkActuate:Bn.xlink,xlinkArcrole:Bn.xlink,xlinkHref:Bn.xlink,xlinkRole:Bn.xlink,xlinkShow:Bn.xlink,xlinkTitle:Bn.xlink,xlinkType:Bn.xlink,xmlBase:Bn.xml,xmlLang:Bn.xml,xmlSpace:Bn.xml}},Vn=/[\-\:]([a-z])/g;"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode x-height xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xmlns:xlink xml:lang xml:space".split(" ").forEach(function(e){var t=e.replace(Vn,l);zn.Properties[t]=0,zn.DOMAttributeNames[t]=e}),Mn.injectDOMPropertyConfig(Fn),Mn.injectDOMPropertyConfig(zn);var qn={_caughtError:null,_hasCaughtError:!1,_rethrowError:null,_hasRethrowError:!1,injection:{injectErrorUtils:function(e){"function"!=typeof e.invokeGuardedCallback&&r("197"),u=e.invokeGuardedCallback}},invokeGuardedCallback:function(e,t,n,r,o,a,i,l,s){u.apply(qn,arguments)},invokeGuardedCallbackAndCatchFirstError:function(e,t,n,r,o,a,i,l,u){if(qn.invokeGuardedCallback.apply(this,arguments),qn.hasCaughtError()){var s=qn.clearCaughtError();qn._hasRethrowError||(qn._hasRethrowError=!0,qn._rethrowError=s)}},rethrowCaughtError:function(){return s.apply(qn,arguments)},hasCaughtError:function(){return qn._hasCaughtError},clearCaughtError:function(){if(qn._hasCaughtError){var e=qn._caughtError;return qn._caughtError=null,qn._hasCaughtError=!1,e}r("198")}},Wn=null,Kn={},Gn=[],Yn={},Qn={},Zn={},$n=Object.freeze({plugins:Gn,eventNameDispatchConfigs:Yn,registrationNameModules:Qn,registrationNameDependencies:Zn,possibleRegistrationNames:null,injectEventPluginOrder:d,injectEventPluginsByName:p}),Xn=null,Jn=null,er=null,tr=null,nr={injectEventPluginOrder:d,injectEventPluginsByName:p},rr=Object.freeze({injection:nr,getListener:w,extractEvents:C,enqueueEvents:E,processEventQueue:T}),or=Math.random().toString(36).slice(2),ar="__reactInternalInstance$"+or,ir="__reactEventHandlers$"+or,lr=Object.freeze({precacheFiberNode:function(e,t){t[ar]=e},getClosestInstanceFromNode:S,getInstanceFromNode:function(e){return e=e[ar],!e||5!==e.tag&&6!==e.tag?null:e},getNodeFromInstance:_,getFiberCurrentPropsFromNode:O,updateFiberProps:function(e,t){e[ir]=t}}),ur=Object.freeze({accumulateTwoPhaseDispatches:R,accumulateTwoPhaseDispatchesSkipTarget:function(e){m(e,N)},accumulateEnterLeaveDispatches:D,accumulateDirectDispatches:function(e){m(e,j)}}),sr=null,cr={_root:null,_startText:null,_fallbackText:null},fr="dispatchConfig _targetInst nativeEvent isDefaultPrevented isPropagationStopped _dispatchListeners _dispatchInstances".split(" "),dr={type:null,target:null,currentTarget:En.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null};Cn(F.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=En.thatReturnsTrue)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=En.thatReturnsTrue)},persist:function(){this.isPersistent=En.thatReturnsTrue},isPersistent:En.thatReturnsFalse,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;for(t=0;t=parseInt(br.version(),10))}var vr,gr=mr,wr=wn.canUseDOM&&(!hr||yr&&8=yr),Cr=String.fromCharCode(32),Er={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["topCompositionEnd","topKeyPress","topTextInput","topPaste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:"topBlur topCompositionEnd topKeyDown topKeyPress topKeyUp topMouseDown".split(" ")},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:"topBlur topCompositionStart topKeyDown topKeyPress topKeyUp topMouseDown".split(" ")},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:"topBlur topCompositionUpdate topKeyDown topKeyPress topKeyUp topMouseDown".split(" ")}},Tr=!1,Sr=!1,_r={eventTypes:Er,extractEvents:function(e,t,n,r){var o;if(hr)e:{switch(e){case"topCompositionStart":var a=Er.compositionStart;break e;case"topCompositionEnd":a=Er.compositionEnd;break e;case"topCompositionUpdate":a=Er.compositionUpdate;break e}a=void 0}else Sr?W(e,n)&&(a=Er.compositionEnd):"topKeyDown"===e&&229===n.keyCode&&(a=Er.compositionStart);return a?(wr&&(Sr||a!==Er.compositionStart?a===Er.compositionEnd&&Sr&&(o=L()):(cr._root=r,cr._startText=U(),Sr=!0)),a=V.getPooled(a,t,n,r),o?a.data=o:null!==(o=K(n))&&(a.data=o),R(a),o=a):o=null,(e=gr?G(e,n):Y(e,n))?(t=q.getPooled(Er.beforeInput,t,n,r),t.data=e,R(t)):t=null,[o,t]}},Or=null,xr=null,kr=null,Pr={injectFiberControlledHostComponent:function(e){Or=e}},Ir=Object.freeze({injection:Pr,enqueueStateRestore:Z,restoreStateIfNeeded:$}),Nr=!1,Mr={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};wn.canUseDOM&&(vr=document.implementation&&document.implementation.hasFeature&&!0!==document.implementation.hasFeature("",""));var jr={change:{phasedRegistrationNames:{bubbled:"onChange",captured:"onChangeCapture"},dependencies:"topBlur topChange topClick topFocus topInput topKeyDown topKeyUp topSelectionChange".split(" ")}},Rr=null,Dr=null,Ar=!1;wn.canUseDOM&&(Ar=ne("input")&&(!document.documentMode||9=document.documentMode,eo={select:{phasedRegistrationNames:{bubbled:"onSelect",captured:"onSelectCapture"},dependencies:"topBlur topContextMenu topFocus topKeyDown topKeyUp topMouseDown topMouseUp topSelectionChange".split(" ")}},to=null,no=null,ro=null,oo=!1,ao={eventTypes:eo,extractEvents:function(e,t,n,r){var o,a=r.window===r?r.document:9===r.nodeType?r:r.ownerDocument;if(!(o=!a)){e:{a=De(a),o=Zn.onSelect;for(var i=0;it&&(t=8),zo=t"+t+"",t=Qo.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}}),$o=/["'&<>]/;wn.canUseDOM&&("textContent"in document.documentElement||(en=function(e,t){if(3===e.nodeType)e.nodeValue=t;else{if("boolean"==typeof t||"number"==typeof t)t=""+t;else{t=""+t;var n=$o.exec(t);if(n){var r,o="",a=0;for(r=n.index;rr&&(o=r,r=e,e=o),o=Le(n,e);var a=Le(n,r);if(o&&a&&(1!==t.rangeCount||t.anchorNode!==o.node||t.anchorOffset!==o.offset||t.focusNode!==a.node||t.focusOffset!==a.offset)){var i=document.createRange();i.setStart(o.node,o.offset),t.removeAllRanges(),e>r?(t.addRange(i),t.extend(a.node,a.offset)):(i.setEnd(a.node,a.offset),t.addRange(i))}}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(xn(n),n=0;n1)for(var n=1;nn.list.scrollTop+n.list.clientHeight){var o=window.getComputedStyle(n.listElement);n.list.scrollTop=r-n.list.clientHeight+parseFloat(o.marginTop)+parseFloat(o.marginBottom)}},n}return i(t,e),l(t,[{key:"componentWillReceiveProps",value:function(e){e.contentTypes!==this.props.contentTypes&&this.setState({resetScroll:!0})}},{key:"componentDidUpdate",value:function(){if(this.state&&this.state.resetScroll)delete this.state.resetScroll,this.list.scrollTop=0;else if(this.props.focused&&this.choose&&this.choose.items)for(var e=this.props.focused.machineName.toLocaleLowerCase().replace(".","-"),t=0;t0?n.closeWithTimeout():n.closeWithoutTimeout()},n.focusContent=function(){return n.content&&!n.contentHasFocus()&&n.content.focus()},n.closeWithTimeout=function(){var e=Date.now()+n.props.closeTimeoutMS;n.setState({beforeClose:!0,closesAt:e},function(){n.closeTimer=setTimeout(n.closeWithoutTimeout,n.state.closesAt-Date.now())})},n.closeWithoutTimeout=function(){n.setState({beforeClose:!1,isOpen:!1,afterOpen:!1,closesAt:null},n.afterClose)},n.handleKeyDown=function(e){e.keyCode===P&&(0,g.default)(n.content,e),n.props.shouldCloseOnEsc&&e.keyCode===I&&(e.preventDefault(),n.requestClose(e))},n.handleOverlayOnClick=function(e){null===n.shouldClose&&(n.shouldClose=!0),n.shouldClose&&n.props.shouldCloseOnOverlayClick&&(n.ownerHandlesClose()?n.requestClose(e):n.focusContent()),n.shouldClose=null,n.moveFromContentToOverlay=null},n.handleOverlayOnMouseUp=function(){null===n.moveFromContentToOverlay&&(n.shouldClose=!1)},n.handleContentOnMouseUp=function(){n.shouldClose=!1},n.handleOverlayOnMouseDown=function(){n.moveFromContentToOverlay=!1},n.handleContentOnClick=function(){n.shouldClose=!1},n.handleContentOnMouseDown=function(){n.shouldClose=!1,n.moveFromContentToOverlay=!1},n.requestClose=function(e){return n.ownerHandlesClose()&&n.props.onRequestClose(e)},n.ownerHandlesClose=function(){return n.props.onRequestClose},n.shouldBeClosed=function(){return!n.state.isOpen&&!n.state.beforeClose},n.contentHasFocus=function(){return document.activeElement===n.content||n.content.contains(document.activeElement)},n.buildClassName=function(e,t){var r="object"===(void 0===t?"undefined":c(t))?t:{base:k[e],afterOpen:k[e]+"--after-open",beforeClose:k[e]+"--before-close"},o=r.base;return n.state.afterOpen&&(o=o+" "+r.afterOpen),n.state.beforeClose&&(o=o+" "+r.beforeClose),"string"==typeof t&&t?o+" "+t:o},n.ariaAttributes=function(e){return Object.keys(e).reduce(function(t,n){return t["aria-"+n]=e[n],t},{})},n.state={afterOpen:!1,beforeClose:!1},n.shouldClose=null,n.moveFromContentToOverlay=null,n}return l(t,e),f(t,[{key:"componentDidMount",value:function(){this.props.isOpen&&(this.setFocusAfterRender(!0),this.open())}},{key:"componentWillReceiveProps",value:function(e){!this.props.isOpen&&e.isOpen?(this.setFocusAfterRender(!0),this.open()):this.props.isOpen&&!e.isOpen&&this.close()}},{key:"componentDidUpdate",value:function(){this.focusAfterRender&&(this.focusContent(),this.setFocusAfterRender(!1))}},{key:"componentWillUnmount",value:function(){_.remove(this.props.bodyOpenClassName),this.beforeClose(),clearTimeout(this.closeTimer)}},{key:"beforeOpen",value:function(){var e=this.props,t=e.appElement,n=e.ariaHideApp,r=e.bodyOpenClassName;_.add(r),n&&C.hide(t)}},{key:"beforeClose",value:function(){var e=this.props,t=e.appElement;e.ariaHideApp&&T.totalCount()<1&&C.show(t)}},{key:"render",value:function(){var e=this.props,t=e.className,n=e.overlayClassName,r=e.defaultStyles,o=t?{}:r.content,a=n?{}:r.overlay;return this.shouldBeClosed()?null:p.default.createElement("div",{ref:this.setOverlayRef,className:this.buildClassName("overlay",n),style:s({},a,this.props.style.overlay),onClick:this.handleOverlayOnClick,onMouseDown:this.handleOverlayOnMouseDown,onMouseUp:this.handleOverlayOnMouseUp},p.default.createElement("div",s({ref:this.setContentRef,style:s({},o,this.props.style.content),className:this.buildClassName("content",t),tabIndex:"-1",onKeyDown:this.handleKeyDown,onMouseDown:this.handleContentOnMouseDown,onMouseUp:this.handleContentOnMouseUp,onClick:this.handleContentOnClick,role:this.props.role,"aria-label":this.props.contentLabel},this.ariaAttributes(this.props.aria||{})),this.props.children))}}]),t}(d.Component);N.defaultProps={style:{overlay:{},content:{}}},N.propTypes={isOpen:y.default.bool.isRequired,defaultStyles:y.default.shape({content:y.default.object,overlay:y.default.object}),style:y.default.shape({content:y.default.object,overlay:y.default.object}),className:y.default.oneOfType([y.default.string,y.default.object]),overlayClassName:y.default.oneOfType([y.default.string,y.default.object]),bodyOpenClassName:y.default.string,ariaHideApp:y.default.bool,appElement:y.default.instanceOf(x.default),onAfterOpen:y.default.func,onRequestClose:y.default.func,closeTimeoutMS:y.default.number,shouldFocusAfterRender:y.default.bool,shouldCloseOnOverlayClick:y.default.bool,shouldReturnFocusAfterClose:y.default.bool,role:y.default.string,contentLabel:y.default.string,aria:y.default.object,children:y.default.node,shouldCloseOnEsc:y.default.bool},t.default=N,e.exports=t.default},function(e,t,n){"use strict";function r(){h=!0}function o(){if(h){if(h=!1,!p)return;setTimeout(function(){if(!p.contains(document.activeElement)){((0,f.default)(p)[0]||p).focus()}},0)}}function a(){d.push(document.activeElement)}function i(){var e=null;try{return e=d.pop(),void e.focus()}catch(t){console.warn(["You tried to return focus to",e,"but it is not in the DOM anymore"].join(" "))}}function l(){d.length>0&&d.pop()}function u(e){p=e,window.addEventListener?(window.addEventListener("blur",r,!1),document.addEventListener("focus",o,!0)):(window.attachEvent("onBlur",r),document.attachEvent("onFocus",o))}function s(){p=null,window.addEventListener?(window.removeEventListener("blur",r),document.removeEventListener("focus",o)):(window.detachEvent("onBlur",r),document.detachEvent("onFocus",o))}Object.defineProperty(t,"__esModule",{value:!0}),t.handleBlur=r,t.handleFocus=o,t.markForFocusLater=a,t.returnFocus=i,t.popWithoutFocus=l,t.setupScopedFocus=u,t.teardownScopedFocus=s;var c=n(14),f=function(e){return e&&e.__esModule?e:{default:e}}(c),d=[],p=null,h=!1},function(e,t,n){"use strict";function r(e,t){var n=(0,a.default)(e);if(!n.length)return void t.preventDefault();var r=t.shiftKey,o=n[0],i=n[n.length-1];if(e!==document.activeElement){var l;if(i!==document.activeElement||r||(l=o),o===document.activeElement&&r&&(l=i),l)return t.preventDefault(),void l.focus();var u=/(\bChrome\b|\bSafari\b)\//.exec(navigator.userAgent);if(null!=u&&"Chrome"!=u[1]&&null==/\biPod\b|\biPad\b/g.exec(navigator.userAgent)){var s=n.indexOf(document.activeElement);s>-1&&(s+=r?-1:1),t.preventDefault(),n[s].focus()}}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var o=n(14),a=function(e){return e&&e.__esModule?e:{default:e}}(o);e.exports=t.default},function(e,t,n){"use strict";function r(e){e.split(" ").map(i.add).forEach(function(e){return document.body.classList.add(e)})}function o(e){var t=i.get();e.split(" ").map(i.remove).filter(function(e){return 0===t[e]}).forEach(function(e){return document.body.classList.remove(e)})}Object.defineProperty(t,"__esModule",{value:!0}),t.add=r,t.remove=o;var a=n(16),i=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}(a)},function(e,t,n){"use strict";var r,o="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};/*!
Copyright (c) 2015 Jed Watson.
Based on code that is Copyright 2013-2015, Facebook, Inc.
All rights reserved.
*/
!function(){var a=!("undefined"==typeof window||!window.document||!window.document.createElement),i={canUseDOM:a,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:a&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:a&&!!window.screen};"object"===o(n(18))&&n(18)?void 0!==(r=function(){return i}.call(t,n,t,e))&&(e.exports=r):void 0!==e&&e.exports?e.exports=i:window.ExecutionEnvironment=i}()},function(e,t){},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=n(0),a=r(o),i=n(1),l=r(i),u=n(2),s=r(u),c=n(66),f=r(c),d=n(68),p=r(d);n(70);var h=function(e){var t=e.id,n=e.attributes,r=e.onShowLicenseDetails;return a.default.createElement(f.default,null,a.default.createElement(p.default,{header:s.default.get("contentTypeLicensePanelTitle"),id:t,attributes:n,onShowLicenseDetails:r}))};h.propTypes={id:l.default.string,onShowLicenseDetails:l.default.func,attributes:l.default.shape({canHoldLiable:l.default.bool,useCommercially:l.default.bool,modifiable:l.default.bool,distributable:l.default.bool,sublicensable:l.default.bool,mustIncludeCopyright:l.default.bool,mustIncludeLicense:l.default.bool})},t.default=h},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var l=function(){function e(e,t){for(var n=0;n=0&&r=n.offset+n.imagesToShow&&(o=n.offset+1),{selected:r,focusOnRender:!0,offset:o}}})}},{key:"componentWillReceiveProps",value:function(e){this.setState({selected:e.selected||0,offset:0})}},{key:"componentDidUpdate",value:function(){this.state.focusOnRender&&(this.items[this.state.selected].focus(),this.scroller.scrollLeft=0,this.setState({focusOnRender:!1}))}},{key:"handleKeyDown",value:function(e,t){if(!e.defaultPrevented){var n=!1;switch(e.which){case 37:case 38:this.moveFocus(-1),n=!0;break;case 39:case 40:this.moveFocus(1),n=!0;break;case 32:case 13:this.handleImageSelected(t),n=!0}n&&(e.stopPropagation(),e.preventDefault())}}},{key:"render",value:function(){var e=this,t=this.props.images;if(!t||!t.length)return null;var n=this.state.imagesToShow,r=t.length,o={width:100/r+"%"},a=100*r/n,i={width:a+"%",marginLeft:"-"+this.state.offset*(a/r)+"%"};this.items=[];var l=t.map(function(t,n){return s.default.createElement("li",{key:n,style:o,tabIndex:n===e.state.selected?0:-1,onKeyDown:function(t){return e.handleKeyDown(t,n)},onClick:function(){return e.handleImageSelected(n)},ref:function(t){return t?e.items.push(t):void 0}},s.default.createElement("img",{src:t.url,alt:t.alt,className:e.props.onImageSelect?"selectable":""}))}),u=0===this.state.offset,c=this.state.imagesToShow+this.state.offset>=r,f=r>this.state.imagesToShow;return s.default.createElement("div",{className:"carousel",role:"region","aria-label":p.default.get("screenshots"),ref:function(t){return e.carousel=t},onKeyDown:this.handleGlobalKeyDown},f&&s.default.createElement(v,{type:"prev",label:p.default.get("previousImage"),onClick:this.previousSlide,disabled:u}),s.default.createElement("nav",{className:"scroller",ref:function(t){return e.scroller=t}},s.default.createElement("ul",{style:i,onTransitionEnd:h.stopPropagation},l)),f&&s.default.createElement(v,{type:"next",label:p.default.get("nextImage"),onClick:this.nextSlide,disabled:c}),this.props.showProgress&&s.default.createElement("div",{className:"progress",role:"alert"},p.default.get("imageLightBoxProgress").replace(":num",this.state.offset+1).replace(":total",r)))}}]),t}(s.default.Component),m=function(){var e=this;this.onWindowResized=function(){if(e.carousel){for(var t=e.carousel.offsetWidth,n=5,r=0;r=0)return{offset:t,selected:t}})},this.nextSlide=function(){e.setState(function(e,t){var n=e.offset+1;if(nthis.props.maxLength,n=t?e.substr(0,this.props.maxLength):e,r=t?e.substr(this.props.maxLength):"";return t&&!this.state.expanded&&(n+="…"),s.default.createElement("p",{className:"small"},s.default.createElement("span",{tabIndex:"-1"},n),t&&[s.default.createElement("span",{key:"part-two",tabIndex:"-1",className:this.state.expanded?"":"hidden"},r),s.default.createElement("a",{href:"#",key:"button",className:"link "+(this.state.expanded?"read-less":"read-more"),onClick:this.handleToggle,onKeyPress:this.handleKeyPress},f.default.get(this.state.expanded?"readLess":"readMore"))])}}]),t}(s.default.Component);t.default=d},function(e,t){},function(e,t){},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=n(0),a=r(o),i=n(1),l=r(i),u=n(3),s=r(u),c=n(2),f=r(c),d=function(e){var t=e.throbbing,n=e.details,r=e.onRetry,o=[f.default.get("noContentTypesAvailableDesc")];return n&&n.title&&(o.push(n.title),n.details&&(o=o.concat(n.details))),a.default.createElement(s.default,{severity:"error",title:f.default.get("noContentTypesAvailable"),message:o},a.default.createElement("button",{type:"button",className:"button button-primary retry-button",tabIndex:"0",onClick:r,disabled:t},f.default.get("tryAgain")))};d.propTypes={throbbing:l.default.bool,details:l.default.object,onRetry:l.default.func.isRequired},d.defaultProps={throbbing:!1},t.default=d},function(e,t,n){"use strict";function r(e,t,n){if(t){var r=e.libraries.map(function(e){return{contentType:e,score:u(t,e)}}).filter(function(t){return t.score>0&&!l(t.contentType,e.apiVersion)});return f(r)}var o=[a[n]];if("recently"===n)if(e.recentlyUsed&&e.recentlyUsed.length){for(var i=0;ie.h5pMajorVersion||t.major===e.h5pMajorVersion&&t.minor>=e.h5pMinorVersion);return e.restricted||!e.installed&&n},u=function(e,t){var n=e.split(" ").filter(function(e){return""!==e}),r=n.map(function(e){return s(e,t)});return r.indexOf(0)>-1?0:r.reduce(function(e,t){return e+t},0)},s=function(e,t){e=e.trim();for(var n=0;nn.contentType[r]?1*a:t.contentType[r]