Permalink
Browse files

Merge pull request #37 from Babibubebon/#32

fixed #32
  • Loading branch information...
2 parents b4ea535 + d3efe27 commit 358fe051bb31c0b209d7d82e18d26ccd59fa0f93 @dadaa dadaa committed Aug 27, 2015
View
3 editor/lib/js/eraser.js
@@ -75,7 +75,7 @@ ParaPara.EraseControls.prototype.mouseDown = function(evt) {
evt.preventDefault();
if (this.eraser)
return;
-
+ ParaPara.history.add("update", ParaPara.frames.getCurrentIndex());
this.eraser = new ParaPara.Eraser(this.frame, this.brushWidth);
this.eraseFromEvent(evt);
}
@@ -100,6 +100,7 @@ ParaPara.EraseControls.prototype.touchStart = function(evt) {
evt.preventDefault();
if (this.eraser)
return;
+ ParaPara.history.add("update", ParaPara.frames.getCurrentIndex());
this.currentTouch = evt.changedTouches[0].identifier;
this.eraser = new ParaPara.Eraser(this.frame, this.brushWidth);
this.eraseFromEvent(evt);
View
126 editor/lib/js/parapara.js
@@ -20,6 +20,7 @@ ParaPara.init = function(contentGroup) {
ParaPara.eraseControls = new ParaPara.EraseControls();
ParaPara.frames = new ParaPara.FrameList();
ParaPara.currentStyle = new ParaPara.Style();
+ ParaPara.history = new ParaPara.HistoryManager();
ParaPara.currentTool = null;
}
@@ -33,6 +34,7 @@ ParaPara.reset = function() {
ParaPara.appendFrame = function() {
var result = ParaPara.frames.appendFrame();
ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame());
+ ParaPara.history.add("insert", ParaPara.frames.getCurrentIndex());
return result;
}
@@ -43,6 +45,7 @@ ParaPara.selectFrame = function(index) {
}
ParaPara.deleteFrame = function(index) {
+ ParaPara.history.add("delete", index);
var result = ParaPara.frames.deleteFrame(index);
ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame());
return result;
@@ -159,6 +162,12 @@ ParaPara.notifyGraphicChanged = function() {
ParaPara.svgRoot.dispatchEvent(changeEvent);
}
+ParaPara.notifyHistoryChanged = function(history) {
+ var changeEvent = document.createEvent("CustomEvent");
+ changeEvent.initCustomEvent("changehistory", true, true, history);
+ ParaPara.svgRoot.dispatchEvent(changeEvent);
+}
+
// -------------------- Canvas event handling --------------------
ParaPara.DrawControls = function() {
@@ -210,6 +219,7 @@ ParaPara.DrawControls.prototype.mouseDown = function(evt) {
evt.preventDefault();
if (evt.button || this.linesInProgress.mouseLine)
return;
+ ParaPara.history.add("update", ParaPara.frames.getCurrentIndex());
var pt = this.getLocalCoords(evt.clientX, evt.clientY, this.frame);
this.linesInProgress.mouseLine =
new ParaPara.FreehandLine(pt.x, pt.y, this.frame);
@@ -234,6 +244,7 @@ ParaPara.DrawControls.prototype.mouseUp = function(evt) {
ParaPara.DrawControls.prototype.touchStart = function(evt) {
evt.preventDefault();
+ ParaPara.history.add("update", ParaPara.frames.getCurrentIndex());
for (var i = 0; i < evt.changedTouches.length; ++i) {
var touch = evt.changedTouches[i];
var pt = this.getLocalCoords(touch.clientX, touch.clientY, this.frame);
@@ -516,6 +527,34 @@ ParaPara.FrameList.prototype.appendFrame = function() {
this.currentFrame = g;
}
+ParaPara.FrameList.prototype.insertFrame = function(index, frame) {
+ if (index < 0 || index >= this.getFrameCount() + 1 ||
+ !this.currentFrame)
+ return;
+
+ var prevIndex = this.getCurrentIndex();
+ this.selectFrame(0);
+
+ var nextFrames = this.getOrMakeNextFrames();
+
+ if (index === 0) {
+ this.currentFrame.parentNode.replaceChild(frame, this.currentFrame);
+ nextFrames.insertBefore(this.currentFrame, nextFrames.firstChild);
+ this.currentFrame = frame;
+ } else {
+ if (!nextFrames.hasChildNodes()) {
+ nextFrames.appendChild(frame);
+ } else {
+ nextFrames.insertBefore(frame, nextFrames.childNodes[index - 1]);
+ }
+ }
+
+ // Now seek back to position
+ if (index <= prevIndex)
+ prevIndex++;
+ this.selectFrame(prevIndex);
+}
+
ParaPara.FrameList.prototype.selectFrame = function(index) {
if (index < 0 || index >= this.getFrameCount() ||
!this.currentFrame)
@@ -657,6 +696,13 @@ ParaPara.FrameList.prototype.getFrames = function() {
return this.scene.getElementsByClassName("frame");
}
+ParaPara.FrameList.prototype.getFrame = function(index) {
+ if (index < 0 || index >= this.getFrameCount())
+ return;
+
+ return this.getFrames()[index];
+}
+
// --------------- FrameList, internal helpers -------------
ParaPara.FrameList.prototype.getCurrentIndex = function() {
@@ -932,3 +978,83 @@ ParaPara.Utils.uuid = function() {
// we put them in syncbase timing specs like "abc\-def.end"
return UUID.generate().replace(/-/g,'');
}
+
+// -------------------- History --------------------
+ParaPara.HistoryManager = function() {
+ this.MAX_STACK_SIZE = 50;
+ this.undoStack = [];
+ this.redoStack = [];
+}
+
+ParaPara.HistoryManager.prototype.do = function(history) {
+ history.svg = history.svg.cloneNode(true);
+ var selectIndex = history.index;
+ switch (history.cmd) {
+ case "update":
+ ParaPara.frames.selectFrame(history.index);
+ ParaPara.editContent.replaceChild(history.svg, ParaPara.frames.getCurrentFrame());
+ ParaPara.frames.currentFrame = history.svg;
+ break;
+ case "insert":
+ ParaPara.frames.insertFrame(history.index, history.svg);
+ break;
+ case "delete":
+ ParaPara.frames.deleteFrame(history.index);
+ selectIndex = ParaPara.frames.getCurrentIndex();
+ break;
+ }
+ ParaPara.selectFrame(selectIndex);
+ ParaPara.notifyHistoryChanged(history);
+}
+
+ParaPara.HistoryManager.prototype.undo = function() {
+ if (this.undoStack.length === 0)
+ return;
+
+ var undo = this.undoStack.pop();
+ var cmd = undo.cmd;
+ switch (cmd) {
+ case "update":
+ // Store current frame
+ this.add("update", undo.index, false);
+ // Move stored frame from undoStack to redoStack
+ this.redoStack.push(this.undoStack.pop());
+ break;
+ case "insert":
+ cmd = "delete";
+ this.redoStack.push(undo);
+ break;
+ case "delete":
+ cmd = "insert";
+ this.redoStack.push(undo);
+ break;
+ }
+ this.do({ cmd: cmd, index: undo.index, svg: undo.svg });
+}
+
+ParaPara.HistoryManager.prototype.redo = function() {
+ if (this.redoStack.length === 0)
+ return;
+
+ var redo = this.redoStack.pop();
+ switch (redo.cmd) {
+ case "update":
+ this.add("update", redo.index, false);
+ break;
+ case "insert":
+ case "delete":
+ this.undoStack.push(redo);
+ break;
+ }
+ this.do(redo);
+}
+
+ParaPara.HistoryManager.prototype.add = function(cmd, index, resetRedoStack) {
+ if (this.undoStack.length >= this.MAX_STACK_SIZE) {
+ this.undoStack.shift();
+ }
+ this.undoStack.push({ cmd: cmd, index: index, svg: ParaPara.frames.getFrame(index).cloneNode(true) });
+ if (resetRedoStack !== false) {
+ this.redoStack = [];
+ }
+}
View
57 editor/public/img/filmstrip.svg
@@ -208,7 +208,7 @@
document.getElementById('plus-frame').removeAttribute('transform');
// Add a frame back
- addFrame(false);
+ document.addFrame(false);
};
// rAF polyfill from https://gist.github.com/1579671
@@ -239,7 +239,7 @@
window.cancelAnimationFrame = function(id) { clearTimeout(id); };
}());
- function addFrame(fireEvent) {
+ document.addFrame = function(fireEvent, index) {
if (typeof fireEvent === "undefined")
fireEvent = true;
@@ -255,7 +255,7 @@
var plusFrame = document.getElementById('plus-frame');
var plusFrameTransform = plusFrame.transform.baseVal.consolidate();
if (plusFrameTransform) {
- var xPos = plusFrameTransform.matrix.e;
+ var xPos = typeof index === "undefined" ? plusFrameTransform.matrix.e : index * 140;
var yPos = plusFrameTransform.matrix.f;
frame_g.setAttribute('transform', 'translate(' + xPos + ',' + yPos + ')');
}
@@ -294,9 +294,18 @@
document.getElementById('close-selection-region').cloneNode(true);
closeSelection.addEventListener('click', onClose, true);
frame_g.appendChild(closeSelection);
-
+
// Add the lot
- container.appendChild(frame_g);
+ if (typeof index === "undefined" || index >= container.childNodes.length) {
+ container.appendChild(frame_g);
+ } else {
+ container.insertBefore(frame_g, container.childNodes[index]);
+
+ // Shift frames after added frame
+ for (var i = index + 1; i < container.childNodes.length; i++) {
+ animTranslate(container.childNodes[i], 140, 0);
+ }
+ }
// Animate the frame so it appears to grow
var anim = createAnimBase(frame_g, "transform", "animateTransform");
@@ -327,7 +336,7 @@
// we just do things the less classy way on WebKit.
// Also, 'children' would be more accurate here, but WebKit doesn't seem to
// offer than on SVG elements at least.)
- var selectFn = function() { selectFrame(container.childNodes.length - 1); };
+ var selectFn = function() { document.selectFrame(container.childNodes.length - 1); };
if (typeof TimeEvent === "object") {
anim.addEventListener("end", selectFn);
} else {
@@ -468,15 +477,15 @@
var frameIndex = getChildIndex(evt.target.parentNode);
dispatchEvent('requestdelete',
{ index: frameIndex,
- callback: function() { removeFrame(frameIndex); } }
+ callback: function() { document.removeFrame(frameIndex); } }
);
// XXX In the future we should move this frame to the end, dim it, add
// a return icon (i.e. undo), append the frame with its index. On click it
// would be restored. On creating a new frame, it would be lost forever.
}
- function removeFrame(index) {
+ document.removeFrame = function(index) {
var container = document.getElementById('frame-container');
var frame = container.childNodes[index];
@@ -523,23 +532,23 @@
// If there are no frames left, add one back
if (container.childNodes.length === 0) {
- addFrame(false);
+ document.addFrame(false);
}
// If it was selected, choose the appropriate frame
if (wasSelected) {
var newIndex = Math.min(index, container.childNodes.length-1);
- selectFrame(newIndex);
+ document.selectFrame(newIndex);
}
}
function onSelect(evt) {
var frameIndex = getChildIndex(evt.target.parentNode);
- selectFrame(frameIndex);
+ document.selectFrame(frameIndex);
dispatchEvent("selectframe", { index: frameIndex });
}
- function selectFrame(index) {
+ document.selectFrame = function(index) {
var container = document.getElementById('frame-container');
// Clear any previous selection
@@ -600,19 +609,19 @@
}
function init() {
- var plusFrame = document.getElementById('plus-frame');
- plusFrame.addEventListener('click', addFrame, true);
- addFrame(false);
-
- if ('ontouchstart' in window) {
- window.addEventListener('touchstart', scrollStart, true);
- window.addEventListener('touchmove', scrollMove, true);
- window.addEventListener('touchend', scrollEnd, true);
- window.addEventListener('touchcancel', scrollEnd, true);
+ var plusFrame = document.getElementById("plus-frame");
+ plusFrame.addEventListener("click", document.addFrame, true);
+ document.addFrame(false);
+
+ if ("ontouchstart" in window) {
+ window.addEventListener("touchstart", scrollStart, true);
+ window.addEventListener("touchmove", scrollMove, true);
+ window.addEventListener("touchend", scrollEnd, true);
+ window.addEventListener("touchcancel", scrollEnd, true);
} else {
- window.addEventListener('mousedown', scrollStart, true);
- window.addEventListener('mousemove', scrollMove, true);
- window.addEventListener('mouseup', scrollEnd, true);
+ window.addEventListener("mousedown", scrollStart, true);
+ window.addEventListener("mousemove", scrollMove, true);
+ window.addEventListener("mouseup", scrollEnd, true);
}
}
init();
View
34 editor/public/js/editor-ui.js.php
@@ -64,6 +64,7 @@
EditorUI.initNavControls();
EditorUI.initAnimControls();
EditorUI.initSettingsMenu();
+ EditorUI.initKeyControls();
EditorUI.currentSpeed = EditorUI.INITIAL_SPEED_FPS;
@@ -629,6 +630,8 @@ function() {
EditorUI.requestDeleteFrame, false);
ParaPara.svgRoot.addEventListener("changegraphic",
EditorUI.updateThumbnails, false);
+ ParaPara.svgRoot.addEventListener("changehistory",
+ EditorUI.updateFrame, false);
}
EditorUI.appendFrame = function() {
@@ -667,6 +670,21 @@ function() {
filmstrip.contentDocument.updateFrame(currentFrame.index, currentFrame.svg);
}
+EditorUI.updateFrame = function(evt) {
+ var filmstrip = document.getElementById("filmstrip").contentDocument;
+ switch (evt.detail.cmd) {
+ case "insert":
+ filmstrip.addFrame(false, evt.detail.index);
+ case "update":
+ filmstrip.updateFrame(evt.detail.index, evt.detail.svg);
+ break;
+ case "delete":
+ filmstrip.removeFrame(evt.detail.index);
+ break;
+ }
+ filmstrip.selectFrame(evt.detail.index);
+}
+
// -------------- Nav controls -----------
EditorUI.initNavControls = function() {
@@ -1138,3 +1156,19 @@ function() { EditorUI.continueLongPress(callback); },
EditorUI._calcSupported = !!el.style.length;
return EditorUI._calcSupported;
};
+
+// -------------- Key controls -----------
+EditorUI.initKeyControls = function() {
+ document.addEventListener("keydown", EditorUI.onKeyDown, false);
+}
+
+EditorUI.onKeyDown = function(evt) {
+ if (evt.ctrlKey && (evt.key === "z" || evt.keyIdentifier === "U+005A" || evt.keyCode === 90)) {
+ // Ctrl + Z
+ ParaPara.history.undo();
+ }
+ if (evt.ctrlKey && (evt.key === "y" || evt.keyIdentifier === "U+0059" || evt.keyCode === 89)) {
+ // Ctrl + Y
+ ParaPara.history.redo();
+ }
+}
View
3,268 editor/public/js/parapara-dev.core.js
1,697 additions, 1,571 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
5 editor/public/js/parapara.core.js
@@ -1,3 +1,2 @@
-var ParaPara=ParaPara||{};ParaPara.SVG_NS="http://www.w3.org/2000/svg";ParaPara.XLINK_NS="http://www.w3.org/1999/xlink";ParaPara.init=function(a){console.assert(!a.hasChildNodes(),"Content group should be empty");ParaPara.contentGroup=a;ParaPara.svgRoot=ParaPara.contentGroup.ownerSVGElement;ParaPara.editContent=document.createElementNS(ParaPara.SVG_NS,"g");ParaPara.contentGroup.appendChild(ParaPara.editContent);ParaPara.drawControls=new ParaPara.DrawControls();ParaPara.eraseControls=new ParaPara.EraseControls();ParaPara.frames=new ParaPara.FrameList();ParaPara.currentStyle=new ParaPara.Style();ParaPara.currentTool=null};ParaPara.reset=function(){while(ParaPara.contentGroup.hasChildNodes()){ParaPara.contentGroup.removeChild(ParaPara.contentGroup.lastChild)}ParaPara.init(ParaPara.contentGroup)};ParaPara.appendFrame=function(){var a=ParaPara.frames.appendFrame();ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame());return a};ParaPara.selectFrame=function(b){var a=ParaPara.frames.selectFrame(b);ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame());return a};ParaPara.deleteFrame=function(b){var a=ParaPara.frames.deleteFrame(b);ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame());return a};ParaPara.getCurrentFrame=function(a){var b=ParaPara.frames.getCurrentFrame();var a=ParaPara.frames.getCurrentIndex();return{index:a,svg:b}};ParaPara.setDrawMode=function(){if(ParaPara.currentTool===ParaPara.drawControls){return false}if(ParaPara.currentTool){ParaPara.currentTool.disable()}ParaPara.drawControls.targetFrame(ParaPara.frames.getCurrentFrame());ParaPara.currentTool=ParaPara.drawControls;return true};ParaPara.setEraseMode=function(){if(ParaPara.currentTool===ParaPara.eraseControls){return false}if(ParaPara.currentTool){ParaPara.currentTool.disable()}ParaPara.eraseControls.targetFrame(ParaPara.frames.getCurrentFrame());ParaPara.currentTool=ParaPara.eraseControls;return true};ParaPara.animate=function(a){if(ParaPara.currentTool){ParaPara.currentTool.disable()}ParaPara.editContent.setAttribute("display","none");ParaPara.animator=new ParaPara.Animator(a,ParaPara.contentGroup);ParaPara.animator.makeAnimation();ParaPara.svgRoot.unpauseAnimations()};ParaPara.pauseAnimation=function(){if(ParaPara.animator){ParaPara.svgRoot.pauseAnimations()}};ParaPara.resumeAnimation=function(){if(ParaPara.animator){ParaPara.svgRoot.unpauseAnimations()}};ParaPara.removeAnimation=function(){if(ParaPara.animator){ParaPara.animator.removeAnimation();ParaPara.animator=null;ParaPara.svgRoot.unpauseAnimations()}ParaPara.editContent.removeAttribute("display");if(ParaPara.currentTool){ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame())}};ParaPara.getMode=function(){if(ParaPara.currentTool===ParaPara.drawControls){return"draw"}if(ParaPara.currentTool===ParaPara.eraseControls){return"erase"}if(ParaPara.animator){return"animate"}return"draw"};ParaPara.send=function(h,a,g,b){console.assert(ParaPara.animator,"No animator found");var e=ParaPara.animator.exportAnimation(b.title,b.author);if(!e){g("no-animation");return}var f={metadata:b};var d=new XMLSerializer();var c=d.serializeToString(e.doc);f.svg=c;f.metadata.groundOffset=e.groundOffset;f.metadata.width=e.width;f.metadata.height=e.height;ParaPara.postRequest(h,f,a,g)};ParaPara.sendEmail=function(c,d,b,a,f){var e={address:c,locale:b};ParaPara.postRequest(d,e,a,f)};ParaPara.fixPrecision=function(a){return a.toFixed(2)};ParaPara.notifyGraphicChanged=function(){var a=document.createEvent("CustomEvent");a.initCustomEvent("changegraphic",true,true,{});ParaPara.svgRoot.dispatchEvent(a)};ParaPara.DrawControls=function(){this.linesInProgress=new Object;this.frame=null;this.mouseDownHandler=this.mouseDown.bind(this);this.mouseMoveHandler=this.mouseMove.bind(this);this.mouseUpHandler=this.mouseUp.bind(this);this.touchStartHandler=this.touchStart.bind(this);this.touchMoveHandler=this.touchMove.bind(this);this.touchEndHandler=this.touchEnd.bind(this);this.touchCancelHandler=this.touchCancel.bind(this)};ParaPara.DrawControls.prototype.targetFrame=function(a){this.frame=a;ParaPara.svgRoot.addEventListener("mousedown",this.mouseDownHandler,false);ParaPara.svgRoot.addEventListener("mousemove",this.mouseMoveHandler,false);ParaPara.svgRoot.addEventListener("mouseup",this.mouseUpHandler,false);ParaPara.svgRoot.addEventListener("touchstart",this.touchStartHandler,false);ParaPara.svgRoot.addEventListener("touchmove",this.touchMoveHandler,false);ParaPara.svgRoot.addEventListener("touchend",this.touchEndHandler,false);ParaPara.svgRoot.addEventListener("touchcancel",this.touchCancelHandler,false)};ParaPara.DrawControls.prototype.disable=function(){ParaPara.svgRoot.removeEventListener("mousedown",this.mouseDownHandler,false);ParaPara.svgRoot.removeEventListener("mousemove",this.mouseMoveHandler,false);ParaPara.svgRoot.removeEventListener("mouseup",this.mouseUpHandler,false);ParaPara.svgRoot.removeEventListener("touchstart",this.touchStartHandler,false);ParaPara.svgRoot.removeEventListener("touchmove",this.touchMoveHandler,false);ParaPara.svgRoot.removeEventListener("touchend",this.touchEndHandler,false);ParaPara.svgRoot.removeEventListener("touchcancel",this.touchCancelHandler,false)};ParaPara.DrawControls.prototype.mouseDown=function(a){a.preventDefault();if(a.button||this.linesInProgress.mouseLine){return}var b=this.getLocalCoords(a.clientX,a.clientY,this.frame);this.linesInProgress.mouseLine=new ParaPara.FreehandLine(b.x,b.y,this.frame)};ParaPara.DrawControls.prototype.mouseMove=function(a){a.preventDefault();if(!this.linesInProgress.mouseLine){return}var b=this.getLocalCoords(a.clientX,a.clientY,this.frame);this.linesInProgress.mouseLine.addPoint(b.x,b.y)};ParaPara.DrawControls.prototype.mouseUp=function(a){a.preventDefault();if(!this.linesInProgress.mouseLine){return}this.linesInProgress.mouseLine.finishLine();delete this.linesInProgress.mouseLine;ParaPara.notifyGraphicChanged()};ParaPara.DrawControls.prototype.touchStart=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var d=a.changedTouches[b];var c=this.getLocalCoords(d.clientX,d.clientY,this.frame);this.linesInProgress[d.identifier]=new ParaPara.FreehandLine(c.x,c.y,this.frame)}};ParaPara.DrawControls.prototype.touchMove=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var d=a.changedTouches[b];var c=this.getLocalCoords(d.clientX,d.clientY,this.frame);console.assert(this.linesInProgress[d.identifier],"Unexpected touch event");this.linesInProgress[d.identifier].addPoint(c.x,c.y)}};ParaPara.DrawControls.prototype.touchEnd=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];console.assert(this.linesInProgress[c.identifier],"Unexpected touch event");this.linesInProgress[c.identifier].finishLine();delete this.linesInProgress[c.identifier]}ParaPara.notifyGraphicChanged()};ParaPara.DrawControls.prototype.touchCancel=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];console.assert(this.linesInProgress[c.identifier],"Unexpected touch event");this.linesInProgress[c.identifier].cancelLine();delete this.linesInProgress[c.identifier]}};ParaPara.DrawControls.prototype.getLocalCoords=function(a,e,b){var d=ParaPara.svgRoot.createSVGPoint();d.x=a;d.y=e;var c=b.parentNode.getScreenCTM();return d.matrixTransform(c.inverse())};ParaPara.FreehandLine=function(a,d,c){this.polyline=document.createElementNS(ParaPara.SVG_NS,"polyline");ParaPara.currentStyle.styleStroke(this.polyline);c.appendChild(this.polyline);var b=ParaPara.svgRoot.createSVGPoint();b.x=a;b.y=d;this.polyline.points.appendItem(b)};ParaPara.FreehandLine.prototype.addPoint=function(a,c){console.assert(this.polyline,"Adding point to finished/cancelled line?");var b=ParaPara.svgRoot.createSVGPoint();b.x=a;b.y=c;this.polyline.points.appendItem(b)};ParaPara.FreehandLine.prototype.finishLine=function(){console.assert(this.polyline,"Line already finished/cancelled?");var a=this.createPathFromPoints(this.polyline.points);this.polyline.parentNode.appendChild(a);this.polyline.parentNode.removeChild(this.polyline);this.polyline=null};ParaPara.FreehandLine.prototype.cancelLine=function(){console.assert(this.polyline,"Line already finished/cancelled?");this.polyline.parentNode.removeChild(this.polyline);this.polyline=null};ParaPara.FreehandLine.prototype.createPathFromPoints=function(a){if(a.numberOfItems==1){return this.createPoint(a)}var b=document.createElementNS(ParaPara.SVG_NS,"path");ParaPara.currentStyle.styleStroke(b);var g=ParaPara.fixPrecision;if(a.numberOfItems==2){var f=a.getItem(0);var e=a.getItem(1);var c="M"+[f.x,f.y].map(g).join(" ")+"L"+[e.x,e.y].map(g).join(" ");b.setAttribute("d",c)}else{a=this.prunePoints(a);var f=a[0];var c="M"+[f.x,f.y].map(g).join(" ")+"C"+this.smoothPoints(a).map(g).join(" ");b.setAttribute("d",c)}return b};ParaPara.FreehandLine.prototype.createPoint=function(a){console.assert(a.numberOfItems===1,"Expected only one point");var b=document.createElementNS(ParaPara.SVG_NS,"circle");b.setAttribute("r",ParaPara.currentStyle.strokeWidth/2);b.setAttribute("cx",a.getItem(0).x);b.setAttribute("cy",a.getItem(0).y);ParaPara.currentStyle.styleFill(b);return b};ParaPara.FreehandLine.prototype.prunePoints=function(e){var b=e.numberOfItems;var a=(b<20)?(b<10)?1:2:3;var c=[];for(var d=0;d<b-a;d+=a){var g=e.getItem(d);c.push({x:g.x,y:g.y})}var f=e.getItem(b-1);c.push({x:f.x,y:f.y});return c};ParaPara.FreehandLine.prototype.smoothPoints=function(k){var l=k[0];var a=[l.x,l.y];var h=k.length;for(var d=1;d<h;d++){var b=k[d-1];var o=k[d];var f=k[(d<h-1)?d+1:d];var e=Math.atan2(b.y-o.y,b.x-o.x);var c=Math.atan2(f.y-o.y,f.x-o.x);var m=(e+c)/2+Math.PI/2;var g=ParaPara.Geometry.lineLength(o.x,o.y,f.x,f.y)/3;if(e-c<0){m+=Math.PI}var j=Math.cos(m)*g;var n=Math.sin(m)*g;a[a.length]=o.x+j;a[a.length]=o.y+n;a[a.length]=o.x;a[a.length]=o.y;if(d<h-1){a[a.length]=o.x-j;a[a.length]=o.y-n}}return a};ParaPara.Style=function(){this.currentColor="black";this.strokeWidth=4;this._eraseWidth=4};ParaPara.Style.prototype.styleStroke=function(a){a.setAttribute("stroke",this.currentColor);a.setAttribute("stroke-width",this.strokeWidth);a.setAttribute("stroke-linecap","round");a.setAttribute("fill","none");a.setAttribute("pointer-events","none")};ParaPara.Style.prototype.styleFill=function(a){a.setAttribute("fill",this.currentColor);a.setAttribute("stroke","none");a.setAttribute("pointer-events","none")};ParaPara.Style.prototype.__defineSetter__("eraseWidth",function(a){this._eraseWidth=a;ParaPara.eraseControls.setBrushWidth(this._eraseWidth)});ParaPara.Style.prototype.__defineGetter__("eraseWidth",function(){return this._eraseWidth});ParaPara.FrameList=function(){this.currentFrame=null;this.scene=ParaPara.editContent;this.appendFrame()};ParaPara.FrameList.prototype.getCurrentFrame=function(){return this.currentFrame};ParaPara.FrameList.prototype.appendFrame=function(){this.selectFrame(this.getFrameCount()-1);var b=this.getPrevFrame();if(b){this.getOrMakeOldFrames().appendChild(b)}if(this.currentFrame){this.getOrMakePrevFrames().appendChild(this.currentFrame)}var a=document.createElementNS(ParaPara.SVG_NS,"g");a.setAttribute("class","frame");this.scene.appendChild(a);this.currentFrame=a};ParaPara.FrameList.prototype.selectFrame=function(c){if(c<0||c>=this.getFrameCount()||!this.currentFrame){return}var g=this.getCurrentIndex();if(c===g){return}if(c<g){var a=g-c;var b=this.getOrMakeNextFrames();b.insertBefore(this.currentFrame,b.firstChild);this.currentFrame=null;if(a>1){b.insertBefore(this.getPrevFrame(),b.firstChild)}else{var h=this.getPrevFrame();this.scene.insertBefore(h,this.getNextFrames());this.currentFrame=h}var e=this.getOldFrames();var d=this.getPrevFrames();while(a>0){if(!e||e.childNodes.length===0){break}var f=this.getOldFrames().lastChild;switch(a){case 1:d.appendChild(f);break;case 2:this.scene.insertBefore(f,b);this.currentFrame=f;break;default:b.insertBefore(f,b.firstChild);break}a--}if(e&&!e.hasChildNodes()){e.parentNode.removeChild(e)}if(d&&!d.hasChildNodes()){d.parentNode.removeChild(d)}}else{var a=c-g;var h=this.getPrevFrame();if(h){this.getOrMakeOldFrames().appendChild(h)}if(a>1){this.getOrMakeOldFrames().appendChild(this.currentFrame)}else{this.getOrMakePrevFrames().appendChild(this.currentFrame)}var b=this.getNextFrames();while(a>0){if(!b||b.childNodes.length===0){break}var f=this.getNextFrames().firstChild;switch(a){case 1:this.scene.insertBefore(f,b);this.currentFrame=f;break;case 2:this.getOrMakePrevFrames().appendChild(f);break;default:this.getOrMakeOldFrames().appendChild(f);break}a--}if(b&&!b.hasChildNodes()){b.parentNode.removeChild(b)}}};ParaPara.FrameList.prototype.deleteFrame=function(b){if(b<0||b>=this.getFrameCount()||!this.currentFrame){return}var c=this.getCurrentIndex();this.selectFrame(0);if(b===0){this.currentFrame.parentNode.removeChild(this.currentFrame);this.currentFrame=null;var a=this.getNextFrames();if(!a){this.appendFrame()}else{var d=a.firstChild;this.scene.insertBefore(d,a);this.currentFrame=d}}else{var a=this.getNextFrames();a.removeChild(a.childNodes[b-1])}var a=this.getNextFrames();if(a&&!a.hasChildNodes()){a.parentNode.removeChild(a)}this.selectFrame(Math.min(c,this.getFrameCount()-1))};ParaPara.FrameList.prototype.getFrames=function(){return this.scene.getElementsByClassName("frame")};ParaPara.FrameList.prototype.getCurrentIndex=function(){return this.getOldFrames()?this.getOldFrames().childNodes.length+1:this.getPrevFrame()?1:0};ParaPara.FrameList.prototype.getFrameCount=function(){return this.getFrames().length};ParaPara.FrameList.prototype.getPrevFrame=function(){var a=this.getPrevFrames();return a?a.lastChild:null};ParaPara.FrameList.prototype.getPrevFrames=function(){return this._getPrevFrames(false)};ParaPara.FrameList.prototype.getOrMakePrevFrames=function(){return this._getPrevFrames(true)};ParaPara.FrameList.prototype._getPrevFrames=function(a){return this._getOrMakeGroup(this.scene,true,"prevFrames",a)};ParaPara.FrameList.prototype.getOldFrames=function(){var a=this.getPrevFrames();if(!a){return null}return this._getOrMakeGroup(a,true,"oldFrames",false)};ParaPara.FrameList.prototype.getOrMakeOldFrames=function(){var a=this.getOrMakePrevFrames();return this._getOrMakeGroup(a,true,"oldFrames",true)};ParaPara.FrameList.prototype.getNextFrames=function(){return this._getNextFrames(false)};ParaPara.FrameList.prototype.getOrMakeNextFrames=function(){return this._getNextFrames(true)};ParaPara.FrameList.prototype._getNextFrames=function(a){return this._getOrMakeGroup(this.scene,false,"nextFrames",a)};ParaPara.FrameList.prototype._getOrMakeGroup=function(d,f,c,a){var b=f?d.firstChild:d.lastChild;if(b&&b.classList.contains(c)){return b}if(!a){return null}var e=document.createElementNS(ParaPara.SVG_NS,"g");e.setAttribute("class",c);return d.insertBefore(e,f?d.firstChild:null)};ParaPara.Animator=function(b,a){this.dur=1/b;this.animation=document.createElementNS(ParaPara.SVG_NS,"g");a.appendChild(this.animation)};ParaPara.Animator.prototype.makeAnimation=function(){var f=ParaPara.frames.getFrames();var e="";for(var a=0;a<f.length;++a){var d=f[a];if(!d.hasChildNodes()){continue}this.animation.appendChild(d.cloneNode(true))}f=this.animation.childNodes;if(f.length<2){return}for(var a=0;a<f.length;++a){var d=f[a];d.removeAttribute("class");d.setAttribute("visibility","hidden");var b=document.createElementNS(ParaPara.SVG_NS,"set");b.setAttribute("attributeName","visibility");b.setAttribute("to","visible");b.setAttribute("dur",this.dur+"s");var g="anim"+ParaPara.Utils.uuid();b.setAttribute("id",g);if(e){b.setAttribute("begin",e+".end")}d.appendChild(b);e=g}var c=f[0].getElementsByTagName("set")[0];c.setAttribute("begin","0; "+e+".end");ParaPara.svgRoot.setCurrentTime(0)};ParaPara.Animator.prototype.removeAnimation=function(){if(this.animation&&this.animation.parentNode){this.animation.parentNode.removeChild(this.animation)}this.animation=null};ParaPara.Animator.prototype.exportAnimation=function(o,g){var p=document.implementation.createDocument(ParaPara.SVG_NS,"svg",null);var k=p.documentElement;k.setAttribute("width","100%");k.setAttribute("height","100%");k.pauseAnimations();if(o){var f=p.createElementNS(ParaPara.SVG_NS,"title");f.appendChild(p.createTextNode(o));k.appendChild(f)}if(g){var c=p.createElementNS(ParaPara.SVG_NS,"desc");var m=g+"さんより";c.appendChild(p.createTextNode(m));k.appendChild(c)}var e=minY=Number.POSITIVE_INFINITY;var a=maxY=Number.NEGATIVE_INFINITY;var n=this.animation.childNodes;if(!n.length){return null}for(var j=0;j<n.length;++j){var d=n[j];console.assert(d.childNodes.length,"Empty frames should have already been dropped");var q=this.getDecoratedBbox(d);e=Math.floor(Math.min(e,q.x));a=Math.ceil(Math.max(a,q.x+q.width));minY=Math.floor(Math.min(minY,q.y));maxY=Math.ceil(Math.max(maxY,q.y+q.height));var b=p.importNode(d,true);b.removeAttribute("style");k.appendChild(b)}var h=ParaPara.svgRoot.getAttribute("viewBox");console.assert(h,"No parent viewBox");h=h.trim().split(" ").map(parseFloat);e=Math.max(e,h[0]);a=Math.min(a,h[0]+h[2]);minY=Math.max(minY,h[1]);maxY=Math.min(maxY,h[1]+h[3]);k.setAttribute("viewBox",[e,minY,a-e,maxY-minY].join(" "));var l=(h[3]-maxY)/(h[3]-h[1]);k.setAttribute("data-ground-offset",l.toFixed(3));return{doc:p,groundOffset:l,width:a-e,height:maxY-minY}};ParaPara.Animator.prototype.getDecoratedBbox=function(e){var d=e.getBBox();var c=0;var b=e.querySelectorAll("path");for(var a=0;a<b.length;a++){var f=parseInt(window.getComputedStyle(b[a]).strokeWidth);c=Math.max(c,f)}d.x-=c/2;d.y-=c/2;d.width+=c;d.height+=c;return d};ParaPara.Animator.prototype.setSpeed=function(d){this.dur=1/d;var a=this.animation.getElementsByTagName("set");for(var b=0;b<a.length;++b){var c=a[b];c.setAttribute("dur",this.dur+"s")}};ParaPara.Utils={};ParaPara.Utils.uuid=function(){return UUID.generate().replace(/-/g,"")};var ParaPara=ParaPara||{};ParaPara.SVG_NS=ParaPara.SVG_NS||"http://www.w3.org/2000/svg";ParaPara.XLINK_NS=ParaPara.XLINK_NS||"http://www.w3.org/1999/xlink";if(typeof ParaPara.fixPrecision!=="function"){ParaPara.fixPrecision=function(a){return a.toFixed(2)}}ParaPara.EraseControls=function(){this.eraser=null;this.currentTouch=null;this.frame=null;this.brushWidth=undefined;this.prevX=undefined;this.prevY=undefined;this.mouseDownHandler=this.mouseDown.bind(this);this.mouseMoveHandler=this.mouseMove.bind(this);this.mouseUpHandler=this.mouseUp.bind(this);this.touchStartHandler=this.touchStart.bind(this);this.touchMoveHandler=this.touchMove.bind(this);this.touchEndHandler=this.touchEnd.bind(this);this.touchCancelHandler=this.touchEnd.bind(this);if(ParaPara.erasePrecision===undefined){ParaPara.erasePrecision=1}};ParaPara.EraseControls.prototype.targetFrame=function(a){console.assert(!this.eraser,"Already erasing?");this.frame=a;this.brushWidth=10;ParaPara.svgRoot.addEventListener("mousedown",this.mouseDownHandler);ParaPara.svgRoot.addEventListener("mousemove",this.mouseMoveHandler);ParaPara.svgRoot.addEventListener("mouseup",this.mouseUpHandler);ParaPara.svgRoot.addEventListener("touchstart",this.touchStartHandler);ParaPara.svgRoot.addEventListener("touchmove",this.touchMoveHandler);ParaPara.svgRoot.addEventListener("touchend",this.touchEndHandler);ParaPara.svgRoot.addEventListener("touchcancel",this.touchCancelHandler);this.prevX=undefined;this.prevY=undefined};ParaPara.EraseControls.prototype.disable=function(){ParaPara.svgRoot.removeEventListener("mousedown",this.mouseDownHandler);ParaPara.svgRoot.removeEventListener("mousemove",this.mouseMoveHandler);ParaPara.svgRoot.removeEventListener("mouseup",this.mouseUpHandler);ParaPara.svgRoot.removeEventListener("touchstart",this.touchStartHandler);ParaPara.svgRoot.removeEventListener("touchmove",this.touchMoveHandler);ParaPara.svgRoot.removeEventListener("touchend",this.touchEndHandler);ParaPara.svgRoot.removeEventListener("touchcancel",this.touchCancelHandler)};ParaPara.EraseControls.prototype.setBrushWidth=function(a){this.brushWidth=a};ParaPara.EraseControls.prototype.mouseDown=function(a){a.preventDefault();if(this.eraser){return}this.eraser=new ParaPara.Eraser(this.frame,this.brushWidth);this.eraseFromEvent(a)};ParaPara.EraseControls.prototype.mouseMove=function(a){a.preventDefault();if(!this.eraser){return}this.eraseFromEvent(a)};ParaPara.EraseControls.prototype.mouseUp=function(a){a.preventDefault();if(!this.eraser){return}this.eraser=null;this.prevX=this.prevY=undefined;ParaPara.notifyGraphicChanged()};ParaPara.EraseControls.prototype.touchStart=function(a){a.preventDefault();if(this.eraser){return}this.currentTouch=a.changedTouches[0].identifier;this.eraser=new ParaPara.Eraser(this.frame,this.brushWidth);this.eraseFromEvent(a)};ParaPara.EraseControls.prototype.touchMove=function(a){a.preventDefault();if(!this.eraser){return}this.eraseFromEvent(a)};ParaPara.EraseControls.prototype.touchEnd=function(a){a.preventDefault();if(!this.eraser){return}for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];if(c.identifier==this.currentTouch){this.currentTouch=null;break}}if(this.currentTouch){return}this.eraser=null;this.prevX=this.prevY=undefined;ParaPara.notifyGraphicChanged()};ParaPara.EraseControls.prototype.eraseFromEvent=function(a){console.assert(this.eraser,"No eraser to use");var e=this.getCoordsFromEvent(a);if(!e){return}var c=[];var f=this.getLocalCoords(e[0],e[1],this.frame);c=this.getCandidateShapes(f.x,f.y);var d=[];for(var b=0;b<c.length;b++){d.push(c[b].id)}this.eraser.erase(f.x,f.y,c);this.prevX=f.x;this.prevY=f.y};ParaPara.EraseControls.prototype.getCoordsFromEvent=function(a){if(!a.changedTouches){return[a.clientX,a.clientY]}else{for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];if(c.identifier==this.currentTouch){return[c.clientX,c.clientY]}}}return null};ParaPara.EraseControls.prototype.getCandidateShapes=function(a,h){var b=this.frame.childNodes;var g=[];for(var d=b.length-1;d>=0;--d){var c=b[d];if(c.nodeType!=Node.ELEMENT_NODE){continue}var f=c.getBBox();f.x-=this.brushWidth/2;f.y-=this.brushWidth/2;f.width+=this.brushWidth;f.height+=this.brushWidth;var e=this.prevX?ParaPara.Geometry.lineIntersectsRect([this.prevX,this.prevY,a,h],f):ParaPara.Geometry.rectContainsPoint(f,[a,h]);if(e){g.push(c)}}return g};ParaPara.EraseControls.prototype.getLocalCoords=function(a,e,b){var d=ParaPara.svgRoot.createSVGPoint();d.x=a;d.y=e;var c=b.parentNode.getScreenCTM();return d.matrixTransform(c.inverse())};ParaPara.Eraser=function(b,a){this.prevX=undefined;this.prevY=undefined;this.brushWidth=a;this.currentScale=b.getScreenCTM().a};ParaPara.Eraser.prototype.erase=function(k,g,c){var f=new ParaPara.Brush(this.prevX?[this.prevX,this.prevY,k,g]:[k,g]);var h=this.brushWidth/this.currentScale;var d=c.length;for(var b=0;b<d;++b){var e=c[b];if(e.tagName=="path"){var j=parseFloat(window.getComputedStyle(e,null).getPropertyValue("stroke-width",null));var a=h+j;f.setWidth(a);this.cutPath(f,e)}else{if(e.tagName=="circle"){this.cutCircle(f,e)}else{console.assert(false,"Got unexpected shape type: "+e.tagName)}}}this.prevX=k;this.prevY=g};ParaPara.Eraser.prototype.cutPath=function(k,m){var b=m.pathSegList;var l=undefined;var c=false;var a=new Array();for(var g=0;g<b.numberOfItems;++g){var f=b.getItem(g);var e=this.getSegObject(f,l);var h=e.cut(k);if(h!=e){c=true}a=a.concat(h);l={x:f.x,y:f.y}}if(c){a=a.filter(ParaPara.Eraser.filterSuperfluousMoveTo);if(!a.length){m.parentNode.removeChild(m)}else{var j=a.join("");m.setAttribute("d",j)}}return c};ParaPara.Eraser.filterSuperfluousMoveTo=function(b,a,c){if(b.constructor!=ParaPara.MoveToSegment){return true}return a<c.length-1&&c[a+1].constructor!=ParaPara.MoveToSegment};ParaPara.Eraser.prototype.getSegObject=function(a,b){switch(a.pathSegType){case SVGPathSeg.PATHSEG_MOVETO_ABS:return new ParaPara.MoveToSegment([a.x,a.y]);case SVGPathSeg.PATHSEG_LINETO_ABS:return new ParaPara.LineToSegment([b.x,b.y,a.x,a.y]);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:return new ParaPara.CurveToSegment([b.x,b.y,a.x1,a.y1,a.x2,a.y2,a.x,a.y]);default:console.assert(false,"Unexpected path segment type: "+a.pathSegType);break}};ParaPara.Eraser.prototype.cutCircle=function(a,b){b.parentNode.removeChild(b)};ParaPara.Brush=function(a){console.assert(a instanceof Array&&a.length==2||a.length==4,"Unexpected brush dimensions");this.points=a;this.bbox=null;this.width=undefined;this.length=undefined;this.path=[];this.mx=null;this.angle=this.points.length==2?0:Math.atan2(this.points[3]-this.points[1],this.points[2]-this.points[0])};ParaPara.Brush.prototype.setWidth=function(c){if(this.width==c){return}this.width=c;if(this.points.length==2){var b=this.width/Math.SQRT2/2;this.path=[this.points[0]-b,this.points[1]-b,this.points[0]+b,this.points[1]-b,this.points[0]+b,this.points[1]+b,this.points[0]-b,this.points[1]+b];this.length=b*2}else{var e=Math.cos(this.angle-Math.PI/2)*this.width/2;var a=Math.sin(this.angle-Math.PI/2)*this.width/2;var d=Math.cos(this.angle)*this.width/2;var f=Math.sin(this.angle)*this.width/2;this.path=[];this.path.push(this.points[0]+e-d);this.path.push(this.points[1]+a-f);this.path.push(this.points[0]-e-d);this.path.push(this.points[1]-a-f);this.path.push(this.points[2]-e+d);this.path.push(this.points[3]-a+f);this.path.push(this.points[2]+e+d);this.path.push(this.points[3]+a+f);this.length=ParaPara.Geometry.lineLength(this.points[0],this.points[1],this.points[2],this.points[3])+this.width}this.bbox=null};ParaPara.Brush.prototype.getDimensions=function(a){if(this.points.length==2){return{width:this.length,length:this.length}}else{return{width:this.width,length:this.length}}};ParaPara.Brush.prototype.getBBox=function(b){if(this.bbox){return this.bbox}var a=Math.min(this.path[0],this.path[2],this.path[4],this.path[6]);var e=Math.min(this.path[1],this.path[3],this.path[5],this.path[7]);var d=Math.max(this.path[0],this.path[2],this.path[4],this.path[6]);var c=Math.max(this.path[1],this.path[3],this.path[5],this.path[7]);this.bbox={x:a,y:e,width:d-a,height:c-e};return this.bbox};ParaPara.Brush.prototype.getTransform=function(){if(this.mx){return this.mx}if(this.points.length==2){this.mx=ParaPara.svgRoot.createSVGMatrix();this.mx=this.mx.translate(-this.path[0],-this.path[1])}else{var a=this.angle*180/Math.PI;this.mx=ParaPara.svgRoot.createSVGMatrix();this.mx=this.mx.rotate(-a,0,0);this.mx=this.mx.translate(-this.path[0],-this.path[1])}return this.mx};ParaPara.Brush.prototype.transformPoint=function(a){var d=this.getTransform();if(!d){return a.slice()}var c=d.a*a[0]+d.c*a[1]+d.e;var b=d.b*a[0]+d.d*a[1]+d.f;return[c,b]};ParaPara.Brush.prototype.transformPoints=function(d){var e=this.getTransform();if(!e){return d.slice()}var b=[];for(var c=0;c<d.length;c+=2){var a=this.transformPoint(d.slice(c,c+2));b.push(a[0],a[1])}return b};ParaPara.Geometry={};ParaPara.Geometry.linesIntersect=function(n,m){var c=n[0];var k=n[1];var b=n[2];var i=n[3];var a=m[0];var h=m[1];var o=m[2];var g=m[3];var f=(c*i-k*b)*(a-o)-(c-b)*(a*g-h*o);var e=(c*i-k*b)*(h-g)-(k-i)*(a*g-h*o);var d=(c-b)*(h-g)-(k-i)*(a-o);if(d==0){return null}var l=f/d;var j=e/d;return[l,j]};ParaPara.Geometry.segmentsIntersect=function(b,a){var d=ParaPara.Geometry.isBetween;var c=ParaPara.Geometry.linesIntersect(b,a);return c&&d(c[0],b[0],b[2])&&d(c[0],a[0],a[2])&&d(c[1],b[1],b[3])&&d(c[1],a[1],a[3])?c:null};ParaPara.Geometry.lineIntersectsRect=function(b,d){var e=[d.x,d.y,d.x+d.width,d.y,d.x+d.width,d.y+d.height,d.x,d.y+d.height];if((b[0]>=e[0]&&b[0]<=e[4]&&b[1]>=e[1]&&b[1]<=e[5])||(b[2]>=e[0]&&b[2]<=e[4]&&b[3]>=e[1]&&b[3]<=e[5])){return true}for(var c=0;c<4;++c){var a=c<3?e.slice(c*2,c*2+4):e.slice(c*2,c*2+2).concat(e.slice(0,2));if(ParaPara.Geometry.segmentsIntersect(b,a)){return true}}return false};ParaPara.Geometry.intersectsWithZeroedRect=function(p,d,o){var n=[];var f=(p[3]-p[1])/(p[2]-p[0]);var g,c,e,a;if(p[0]<p[2]){g=Math.max(0,p[0]);c=Math.min(d,p[2])}else{g=Math.max(0,p[2]);c=Math.min(d,p[0])}if(g>=c){return n}if(p[1]<p[3]){e=Math.max(0,p[1]);a=Math.min(o,p[3])}else{e=Math.max(0,p[3]);a=Math.min(o,p[1])}if(e>=a){return n}var b=[0,d];for(var h=0;f!=Infinity&&h<b.length;++h){var l=b[h];var j=f*(l-p[0])+p[1];if(l>=g&&l<=c&&j>=e&&j<=a){n.push([l,j])}}var k=[0,o];for(var h=0;f!=0&&h<k.length;++h){var j=k[h];var l=1/f*(j-p[1])+p[0];if(l>=g&&l<=c&&j>=e&&j<=a){n.push([l,j])}}return n};ParaPara.Geometry.rectsIntersect=function(b,a){return !(b.x+b.width<=a.x||b.x>=a.x+a.width||b.y+b.height<=a.y||b.y>=a.y+a.height)};ParaPara.Geometry.rectContainsRect=function(b,a){return a.x>=b.x&&a.x+a.width<=b.x+b.width&&a.y>=b.y&&a.y+a.height<=b.y+b.height};ParaPara.Geometry.rectContainsLine=function(c,a){var b=ParaPara.Geometry.rectContainsPoint;return b(c,[a[0],a[1]])&&b(c,[a[2],a[3]])};ParaPara.Geometry.rectContainsPoint=function(b,a){return b.x<=a[0]&&a[0]<=b.x+b.width&&b.y<=a[1]&&a[1]<=b.y+b.height};ParaPara.Geometry.lineLength=function(b,d,a,c){return Math.sqrt((a-=b)*a+(c-=d)*c)};ParaPara.Geometry.isBetween=function(d,e,c){var f=0.000001;return d>=Math.min(e,c)-f&&d<=Math.max(e,c)+f};ParaPara.Geometry.prettyMuchEqual=function(d,c){var e=0.000001;return Math.abs(d-c)<e};ParaPara.MoveToSegment=function(a){console.assert(a instanceof Array&&a.length==2,"Unexpected segment length");this.point=a};ParaPara.MoveToSegment.prototype.cut=function(a){return this};ParaPara.MoveToSegment.prototype.toString=function(){return"M"+this.point.map(ParaPara.fixPrecision).join(" ")};ParaPara.LineToSegment=function(a){console.assert(a instanceof Array&&a.length==4,"Unexpected segment length");this.points=a};ParaPara.LineToSegment.prototype.cut=function(d){var c=ParaPara.MoveToSegment;var k=ParaPara.LineToSegment;var j=ParaPara.Geometry.prettyMuchEqual;var h=d.getBBox();if(!ParaPara.Geometry.lineIntersectsRect(this.points,h)){return this}var g=d.transformPoints(this.points);var e=d.getDimensions();var q={x:0,y:0,width:e.length,height:e.width};if(ParaPara.Geometry.rectContainsLine(q,g)){return new c(this.points.slice(2))}var u=[];for(var o=0;o<4;++o){var l=o<3?d.path.slice(o*2,o*2+4):d.path.slice(o*2,o*2+2).concat(d.path.slice(0,2));var m=ParaPara.Geometry.segmentsIntersect(this.points,l);if(m){if(u.length&&j(m[0],u[u.length-2])&&j(m[1],u[u.length-1])){continue}u.push(m[0],m[1]);if(u.length==4){break}}}if(!u.length){return this}if(u.length==4){var t,s;if(this.points[2]==this.points[0]){t=3;s=1}else{t=2;s=0}if((this.points[t]-this.points[s]<0)!=(u[t]-u[s]<0)){var r=u.slice(0,2);u[0]=u[2];u[1]=u[3];u[2]=r[0];u[3]=r[1]}}var p=g[0]>=0&&g[0]<=e.length&&g[1]>=0&&g[1]<=e.width;var f=[];var n=this.points.slice(0,2).concat(u,this.points.slice(2));for(var o=0;o<n.length-2;o+=2){if(p){f.push(new c(n.slice(o+2,o+4)))}else{f.push(new k(n.slice(o,o+4)))}p=!p}return f};ParaPara.LineToSegment.prototype.toString=function(){return"L"+this.points.slice(2).map(ParaPara.fixPrecision).join(" ")};ParaPara.CurveToSegment=function(a){console.assert(a instanceof Array&&a.length==8,"Unexpected segment length");this.points=a};ParaPara.CurveToSegment.prototype.cut=function(c){var a=ParaPara.MoveToSegment;var A=ParaPara.CurveToSegment;var y=ParaPara.Geometry.lineLength;var d=ParaPara.Geometry.segmentsIntersect;var n=c.getBBox();var F=this.getBBox();if(!ParaPara.Geometry.rectsIntersect(n,F)){return this}var e=new A(c.transformPoints(this.points));var f=c.getDimensions();var E={x:0,y:0,width:f.length,height:f.width};var x=y(this.points[0],this.points[1],this.points[6],this.points[7]);if(x<c.width*0.75){var l=[e.points[0],e.points[1],e.points[6],e.points[7]];return ParaPara.Geometry.intersectsWithZeroedRect(l,E)?new a(this.points.slice(6)):this}var q=e.getBBox();if(ParaPara.Geometry.rectContainsRect(E,q)){return new a(this.points.slice(6))}if(!ParaPara.Geometry.rectsIntersect(q,E)){return this}var k=1/ParaPara.erasePrecision;var p=e.getValue(0);var G=[];var b=p[0]>=0&&p[0]<=f.length&&p[1]>=0&&p[1]<=f.width;for(var o=k;o<=1;o+=k){var B=e.getValue(o);var m=ParaPara.Geometry.intersectsWithZeroedRect([p[0],p[1],B[0],B[1]],f.length,f.width);if(m.length){var s=y(p[0],p[1],B[0],B[1]);for(var z=0;z<m.length;++z){var r=m[z];if(r[0]==p[0]&&r[1]==p[1]){continue}var j=y(p[0],p[1],r[0],r[1])/s;var w=o-k+k*j;G.push(w)}}p=B}if(!G.length&&!b){return this}G.sort(function(t,i){return t-i});var D=b;var h=[];var C=this.points;var v=0;for(var z=0;z<G.length;++z){var o=G[z];var g=(o-v)/(1-v);var u=this.splitSegment(C,g);if(D){h.push(new a(u[0].slice(6)))}else{h.push(new A(u[0]))}C=u[1];D=!D;v=o}if(D){h.push(new a(C.slice(6)))}else{h.push(new A(C))}return h};ParaPara.CurveToSegment.prototype.splitSegment=function(g,e){var h=[g[0],g[1]];var f=[g[6],g[7]];var d=g;var a=[];for(var c=3;c>=1;--c){a=[];for(var b=0;b<c;++b){a.push(d[b*2]*(1-e)+d[b*2+2]*e);a.push(d[b*2+1]*(1-e)+d[b*2+3]*e)}h.push(a[0],a[1]);f.unshift(a[(c-1)*2],a[(c-1)*2+1]);d=a}return[h,f]};ParaPara.CurveToSegment.prototype.getValue=function(a){return[this.getX(a),this.getY(a)]};ParaPara.CurveToSegment.prototype.getX=function(a){return this.computeCubicBaseValue(a,this.points[0],this.points[2],this.points[4],this.points[6])};ParaPara.CurveToSegment.prototype.getY=function(a){return this.computeCubicBaseValue(a,this.points[1],this.points[3],this.points[5],this.points[7])};ParaPara.CurveToSegment.prototype.computeCubicBaseValue=function(h,f,e,j,i){var g=1-h;return g*g*g*f+3*g*g*h*e+3*g*h*h*j+h*h*h*i};ParaPara.CurveToSegment.prototype.getBBox=function(){var a=Math.min(this.points[0],this.points[2],this.points[4],this.points[6]);var d=Math.min(this.points[1],this.points[3],this.points[5],this.points[7]);var c=Math.max(this.points[0],this.points[2],this.points[4],this.points[6]);var b=Math.max(this.points[1],this.points[3],this.points[5],this.points[7]);return{x:a,y:d,width:c-a,height:b-d}};ParaPara.CurveToSegment.prototype.toString=function(){return"C"+this.points.slice(2).map(ParaPara.fixPrecision).join(" ")}
-/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
-;if(typeof document!=="undefined"&&!("classList" in document.createElement("a")&&"classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))){(function(j){var a="http://www.w3.org/2000/svg",p="classList",n="prototype",r=Object,f=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},c=Array[n].indexOf||function(u){var t=0,s=this.length;for(;t<s;t++){if(t in this&&this[t]===u){return t}}return -1},i=function(s,t){this.name=s;this.code=DOMException[s];this.message=t},e=function(t,s){if(s===""){throw new i("SYNTAX_ERR","An invalid or illegal string was specified")}if(/\s/.test(s)){throw new i("INVALID_CHARACTER_ERR","String contains an invalid character")}return c.call(t,s)},d=function(x){var v=typeof x.className.baseVal!=="undefined"?x.className.baseVal:x.className,w=f.call(v),u=w?w.split(/\s+/):[],t=0,s=u.length;for(;t<s;t++){this.push(u[t])}this._updateClassName=function(){typeof x.className.baseVal!=="undefined"?x.className.baseVal=this.toString():x.className=this.toString()}},o=d[n]=[],m=function(){return new d(this)},q=function(s){if(r.defineProperty){var u={get:m,enumerable:true,configurable:true};try{r.defineProperty(s[n],p,u)}catch(t){if(t.number===-2146823252){u.enumerable=false;r.defineProperty(s[n],p,u)}}}else{if(r[n].__defineGetter__){elemCtrl[n].__defineGetter__(p,m)}}},k=function(t,s){if(!("classList" in t.createElement("a"))){q(s.HTMLElement||s.Element)}if(!("classList" in t.createElementNS(a,"g"))){q(s.SVGElement)}},g=function(s){if(s.contentDocument&&s.contentDocument.readyState=="complete"){var t=s.contentWindow||s.contentDocument.defaultView;k(s.contentDocument,t)}},l=function(){var t=document.getElementsByTagName("object");for(var s=0;s<t.length;++s){g(t[s])}},b=function(){l();document.addEventListener("DOMNodeInserted",h,true)},h=function(s){g(s.srcElement);s.srcElement.addEventListener("load",l,true)};i[n]=Error[n];o.item=function(s){return this[s]||null};o.contains=function(s){s+="";return e(this,s)!==-1};o.add=function(s){s+="";if(e(this,s)===-1){this.push(s);this._updateClassName()}};o.remove=function(t){t+="";var s=e(this,t);if(s!==-1){this.splice(s,1);this._updateClassName()}};o.toggle=function(s){s+="";if(e(this,s)===-1){this.add(s)}else{this.remove(s)}};o.toString=function(){return this.join(" ")};k(document,j);if(document.readyState!="complete"){document.addEventListener("DOMContentLoaded",b,true);window.addEventListener("load",l,true)}else{b()}}(self))}var ParaPara=ParaPara||{};ParaPara.XHR_TIMEOUT=8000;ParaPara.postRequest=function(b,g,a,h){var c=JSON.stringify(g);var d=new XMLHttpRequest();d.open("POST",b,true);d.setRequestHeader("Content-Type","application/json");d.onreadystatechange=function(){if(d.readyState!=4){return}if(d.status==200||d.status==0){try{var i=JSON.parse(d.responseText);if(i.error_key){h(i.error_key,i.error_detail)}else{a(JSON.parse(d.responseText))}}catch(j){if(j instanceof SyntaxError){console.debug("Error sending to server, could not parse response: "+d.responseText);h("server-fail")}else{throw j}}}else{h("no-access")}};try{d.send(c)}catch(f){console.debug(f);h("send-fail");return}window.setTimeout(function(){if(d.readyState!=0&&d.readyState!=4){d.abort();h("timeout")}},ParaPara.XHR_TIMEOUT);ParaPara.abortRequest=function(){if(d.readyState!=0&&d.readyState!=4){d.abort()}}};ParaPara.abortRequest=function(){};if(!Function.prototype.bind){Function.prototype.bind=function(a){if(typeof this!=="function"){throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable")}var e=Array.prototype.slice.call(arguments,1),d=this,b=function(){},c=function(){return d.apply(this instanceof b?this:a||window,e.concat(Array.prototype.slice.call(arguments)))};b.prototype=this.prototype;c.prototype=new b();return c}}function UUID(){}UUID.generate=function(){var a=UUID._gri,b=UUID._ha;return b(a(32),8)+"-"+b(a(16),4)+"-"+b(16384|a(12),4)+"-"+b(32768|a(14),4)+"-"+b(a(48),12)};UUID._gri=function(a){if(a<0){return NaN}if(a<=30){return(0|Math.random()*(1<<a))}if(a<=53){return(0|Math.random()*(1<<30))+(0|Math.random()*(1<<a-30))*(1<<30)}return NaN};UUID._ha=function(a,c){var e=a.toString(16),b=c-e.length,d="0";for(;b>0;b>>>=1,d+=d){if(b&1){e=d+e}}return e};
+function UUID(){}Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d?this:a||window,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e});var ParaPara=ParaPara||{};ParaPara.SVG_NS=ParaPara.SVG_NS||"http://www.w3.org/2000/svg",ParaPara.XLINK_NS=ParaPara.XLINK_NS||"http://www.w3.org/1999/xlink","function"!=typeof ParaPara.fixPrecision&&(ParaPara.fixPrecision=function(a){return a.toFixed(2)}),ParaPara.EraseControls=function(){this.eraser=null,this.currentTouch=null,this.frame=null,this.brushWidth=void 0,this.prevX=void 0,this.prevY=void 0,this.mouseDownHandler=this.mouseDown.bind(this),this.mouseMoveHandler=this.mouseMove.bind(this),this.mouseUpHandler=this.mouseUp.bind(this),this.touchStartHandler=this.touchStart.bind(this),this.touchMoveHandler=this.touchMove.bind(this),this.touchEndHandler=this.touchEnd.bind(this),this.touchCancelHandler=this.touchEnd.bind(this),void 0===ParaPara.erasePrecision&&(ParaPara.erasePrecision=1)},ParaPara.EraseControls.prototype.targetFrame=function(a){console.assert(!this.eraser,"Already erasing?"),this.frame=a,this.brushWidth=10,ParaPara.svgRoot.addEventListener("mousedown",this.mouseDownHandler),ParaPara.svgRoot.addEventListener("mousemove",this.mouseMoveHandler),ParaPara.svgRoot.addEventListener("mouseup",this.mouseUpHandler),ParaPara.svgRoot.addEventListener("touchstart",this.touchStartHandler),ParaPara.svgRoot.addEventListener("touchmove",this.touchMoveHandler),ParaPara.svgRoot.addEventListener("touchend",this.touchEndHandler),ParaPara.svgRoot.addEventListener("touchcancel",this.touchCancelHandler),this.prevX=void 0,this.prevY=void 0},ParaPara.EraseControls.prototype.disable=function(){ParaPara.svgRoot.removeEventListener("mousedown",this.mouseDownHandler),ParaPara.svgRoot.removeEventListener("mousemove",this.mouseMoveHandler),ParaPara.svgRoot.removeEventListener("mouseup",this.mouseUpHandler),ParaPara.svgRoot.removeEventListener("touchstart",this.touchStartHandler),ParaPara.svgRoot.removeEventListener("touchmove",this.touchMoveHandler),ParaPara.svgRoot.removeEventListener("touchend",this.touchEndHandler),ParaPara.svgRoot.removeEventListener("touchcancel",this.touchCancelHandler)},ParaPara.EraseControls.prototype.setBrushWidth=function(a){this.brushWidth=a},ParaPara.EraseControls.prototype.mouseDown=function(a){a.preventDefault(),this.eraser||(ParaPara.history.add("update",ParaPara.frames.getCurrentIndex()),this.eraser=new ParaPara.Eraser(this.frame,this.brushWidth),this.eraseFromEvent(a))},ParaPara.EraseControls.prototype.mouseMove=function(a){a.preventDefault(),this.eraser&&this.eraseFromEvent(a)},ParaPara.EraseControls.prototype.mouseUp=function(a){a.preventDefault(),this.eraser&&(this.eraser=null,this.prevX=this.prevY=void 0,ParaPara.notifyGraphicChanged())},ParaPara.EraseControls.prototype.touchStart=function(a){a.preventDefault(),this.eraser||(ParaPara.history.add("update",ParaPara.frames.getCurrentIndex()),this.currentTouch=a.changedTouches[0].identifier,this.eraser=new ParaPara.Eraser(this.frame,this.brushWidth),this.eraseFromEvent(a))},ParaPara.EraseControls.prototype.touchMove=function(a){a.preventDefault(),this.eraser&&this.eraseFromEvent(a)},ParaPara.EraseControls.prototype.touchEnd=function(a){if(a.preventDefault(),this.eraser){for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];if(c.identifier==this.currentTouch){this.currentTouch=null;break}}this.currentTouch||(this.eraser=null,this.prevX=this.prevY=void 0,ParaPara.notifyGraphicChanged())}},ParaPara.EraseControls.prototype.eraseFromEvent=function(a){console.assert(this.eraser,"No eraser to use");var b=this.getCoordsFromEvent(a);if(b){var c=[],d=this.getLocalCoords(b[0],b[1],this.frame);c=this.getCandidateShapes(d.x,d.y);for(var e=[],f=0;f<c.length;f++)e.push(c[f].id);this.eraser.erase(d.x,d.y,c),this.prevX=d.x,this.prevY=d.y}},ParaPara.EraseControls.prototype.getCoordsFromEvent=function(a){if(!a.changedTouches)return[a.clientX,a.clientY];for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];if(c.identifier==this.currentTouch)return[c.clientX,c.clientY]}return null},ParaPara.EraseControls.prototype.getCandidateShapes=function(a,b){for(var c=this.frame.childNodes,d=[],e=c.length-1;e>=0;--e){var f=c[e];if(f.nodeType==Node.ELEMENT_NODE){var g=f.getBBox();g.x-=this.brushWidth/2,g.y-=this.brushWidth/2,g.width+=this.brushWidth,g.height+=this.brushWidth;var h=this.prevX?ParaPara.Geometry.lineIntersectsRect([this.prevX,this.prevY,a,b],g):ParaPara.Geometry.rectContainsPoint(g,[a,b]);h&&d.push(f)}}return d},ParaPara.EraseControls.prototype.getLocalCoords=function(a,b,c){var d=ParaPara.svgRoot.createSVGPoint();d.x=a,d.y=b;var e=c.parentNode.getScreenCTM();return d.matrixTransform(e.inverse())},ParaPara.Eraser=function(a,b){this.prevX=void 0,this.prevY=void 0,this.brushWidth=b,this.currentScale=a.getScreenCTM().a},ParaPara.Eraser.prototype.erase=function(a,b,c){for(var d=new ParaPara.Brush(this.prevX?[this.prevX,this.prevY,a,b]:[a,b]),e=this.brushWidth/this.currentScale,f=c.length,g=0;f>g;++g){var h=c[g];if("path"==h.tagName){var i=parseFloat(window.getComputedStyle(h,null).getPropertyValue("stroke-width",null)),j=e+i;d.setWidth(j),this.cutPath(d,h)}else"circle"==h.tagName?this.cutCircle(d,h):console.assert(!1,"Got unexpected shape type: "+h.tagName)}this.prevX=a,this.prevY=b},ParaPara.Eraser.prototype.cutPath=function(a,b){for(var c=b.pathSegList,d=void 0,e=!1,f=new Array,g=0;g<c.numberOfItems;++g){var h=c.getItem(g),i=this.getSegObject(h,d),j=i.cut(a);j!=i&&(e=!0),f=f.concat(j),d={x:h.x,y:h.y}}if(e)if(f=f.filter(ParaPara.Eraser.filterSuperfluousMoveTo),f.length){var k=f.join("");b.setAttribute("d",k)}else b.parentNode.removeChild(b);return e},ParaPara.Eraser.filterSuperfluousMoveTo=function(a,b,c){return a.constructor!=ParaPara.MoveToSegment?!0:b<c.length-1&&c[b+1].constructor!=ParaPara.MoveToSegment},ParaPara.Eraser.prototype.getSegObject=function(a,b){switch(a.pathSegType){case SVGPathSeg.PATHSEG_MOVETO_ABS:return new ParaPara.MoveToSegment([a.x,a.y]);case SVGPathSeg.PATHSEG_LINETO_ABS:return new ParaPara.LineToSegment([b.x,b.y,a.x,a.y]);case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:return new ParaPara.CurveToSegment([b.x,b.y,a.x1,a.y1,a.x2,a.y2,a.x,a.y]);default:console.assert(!1,"Unexpected path segment type: "+a.pathSegType)}},ParaPara.Eraser.prototype.cutCircle=function(a,b){b.parentNode.removeChild(b)},ParaPara.Brush=function(a){console.assert(a instanceof Array&&2==a.length||4==a.length,"Unexpected brush dimensions"),this.points=a,this.bbox=null,this.width=void 0,this.length=void 0,this.path=[],this.mx=null,this.angle=2==this.points.length?0:Math.atan2(this.points[3]-this.points[1],this.points[2]-this.points[0])},ParaPara.Brush.prototype.setWidth=function(a){if(this.width!=a){if(this.width=a,2==this.points.length){var b=this.width/Math.SQRT2/2;this.path=[this.points[0]-b,this.points[1]-b,this.points[0]+b,this.points[1]-b,this.points[0]+b,this.points[1]+b,this.points[0]-b,this.points[1]+b],this.length=2*b}else{var c=Math.cos(this.angle-Math.PI/2)*this.width/2,d=Math.sin(this.angle-Math.PI/2)*this.width/2,e=Math.cos(this.angle)*this.width/2,f=Math.sin(this.angle)*this.width/2;this.path=[],this.path.push(this.points[0]+c-e),this.path.push(this.points[1]+d-f),this.path.push(this.points[0]-c-e),this.path.push(this.points[1]-d-f),this.path.push(this.points[2]-c+e),this.path.push(this.points[3]-d+f),this.path.push(this.points[2]+c+e),this.path.push(this.points[3]+d+f),this.length=ParaPara.Geometry.lineLength(this.points[0],this.points[1],this.points[2],this.points[3])+this.width}this.bbox=null}},ParaPara.Brush.prototype.getDimensions=function(a){return 2==this.points.length?{width:this.length,length:this.length}:{width:this.width,length:this.length}},ParaPara.Brush.prototype.getBBox=function(a){if(this.bbox)return this.bbox;var b=Math.min(this.path[0],this.path[2],this.path[4],this.path[6]),c=Math.min(this.path[1],this.path[3],this.path[5],this.path[7]),d=Math.max(this.path[0],this.path[2],this.path[4],this.path[6]),e=Math.max(this.path[1],this.path[3],this.path[5],this.path[7]);return this.bbox={x:b,y:c,width:d-b,height:e-c},this.bbox},ParaPara.Brush.prototype.getTransform=function(){if(this.mx)return this.mx;if(2==this.points.length)this.mx=ParaPara.svgRoot.createSVGMatrix(),this.mx=this.mx.translate(-this.path[0],-this.path[1]);else{var a=180*this.angle/Math.PI;this.mx=ParaPara.svgRoot.createSVGMatrix(),this.mx=this.mx.rotate(-a,0,0),this.mx=this.mx.translate(-this.path[0],-this.path[1])}return this.mx},ParaPara.Brush.prototype.transformPoint=function(a){var b=this.getTransform();if(!b)return a.slice();var c=b.a*a[0]+b.c*a[1]+b.e,d=b.b*a[0]+b.d*a[1]+b.f;return[c,d]},ParaPara.Brush.prototype.transformPoints=function(a){var b=this.getTransform();if(!b)return a.slice();for(var c=[],d=0;d<a.length;d+=2){var e=this.transformPoint(a.slice(d,d+2));c.push(e[0],e[1])}return c},ParaPara.Geometry={},ParaPara.Geometry.linesIntersect=function(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=b[0],h=b[1],i=b[2],j=b[3],k=(c*f-d*e)*(g-i)-(c-e)*(g*j-h*i),l=(c*f-d*e)*(h-j)-(d-f)*(g*j-h*i),m=(c-e)*(h-j)-(d-f)*(g-i);if(0==m)return null;var n=k/m,o=l/m;return[n,o]},ParaPara.Geometry.segmentsIntersect=function(a,b){var c=ParaPara.Geometry.isBetween,d=ParaPara.Geometry.linesIntersect(a,b);return d&&c(d[0],a[0],a[2])&&c(d[0],b[0],b[2])&&c(d[1],a[1],a[3])&&c(d[1],b[1],b[3])?d:null},ParaPara.Geometry.lineIntersectsRect=function(a,b){var c=[b.x,b.y,b.x+b.width,b.y,b.x+b.width,b.y+b.height,b.x,b.y+b.height];if(a[0]>=c[0]&&a[0]<=c[4]&&a[1]>=c[1]&&a[1]<=c[5]||a[2]>=c[0]&&a[2]<=c[4]&&a[3]>=c[1]&&a[3]<=c[5])return!0;for(var d=0;4>d;++d){var e=3>d?c.slice(2*d,2*d+4):c.slice(2*d,2*d+2).concat(c.slice(0,2));if(ParaPara.Geometry.segmentsIntersect(a,e))return!0}return!1},ParaPara.Geometry.intersectsWithZeroedRect=function(a,b,c){var d,e,f,g,h=[],i=(a[3]-a[1])/(a[2]-a[0]);if(a[0]<a[2]?(d=Math.max(0,a[0]),e=Math.min(b,a[2])):(d=Math.max(0,a[2]),e=Math.min(b,a[0])),d>=e)return h;if(a[1]<a[3]?(f=Math.max(0,a[1]),g=Math.min(c,a[3])):(f=Math.max(0,a[3]),g=Math.min(c,a[1])),f>=g)return h;for(var j=[0,b],k=0;i!=1/0&&k<j.length;++k){var l=j[k],m=i*(l-a[0])+a[1];l>=d&&e>=l&&m>=f&&g>=m&&h.push([l,m])}for(var n=[0,c],k=0;0!=i&&k<n.length;++k){var m=n[k],l=1/i*(m-a[1])+a[0];l>=d&&e>=l&&m>=f&&g>=m&&h.push([l,m])}return h},ParaPara.Geometry.rectsIntersect=function(a,b){return!(a.x+a.width<=b.x||a.x>=b.x+b.width||a.y+a.height<=b.y||a.y>=b.y+b.height)},ParaPara.Geometry.rectContainsRect=function(a,b){return b.x>=a.x&&b.x+b.width<=a.x+a.width&&b.y>=a.y&&b.y+b.height<=a.y+a.height},ParaPara.Geometry.rectContainsLine=function(a,b){var c=ParaPara.Geometry.rectContainsPoint;return c(a,[b[0],b[1]])&&c(a,[b[2],b[3]])},ParaPara.Geometry.rectContainsPoint=function(a,b){return a.x<=b[0]&&b[0]<=a.x+a.width&&a.y<=b[1]&&b[1]<=a.y+a.height},ParaPara.Geometry.lineLength=function(a,b,c,d){return Math.sqrt((c-=a)*c+(d-=b)*d)},ParaPara.Geometry.isBetween=function(a,b,c){var d=1e-6;return a>=Math.min(b,c)-d&&a<=Math.max(b,c)+d},ParaPara.Geometry.prettyMuchEqual=function(a,b){var c=1e-6;return Math.abs(a-b)<c},ParaPara.MoveToSegment=function(a){console.assert(a instanceof Array&&2==a.length,"Unexpected segment length"),this.point=a},ParaPara.MoveToSegment.prototype.cut=function(a){return this},ParaPara.MoveToSegment.prototype.toString=function(){return"M"+this.point.map(ParaPara.fixPrecision).join(" ")},ParaPara.LineToSegment=function(a){console.assert(a instanceof Array&&4==a.length,"Unexpected segment length"),this.points=a},ParaPara.LineToSegment.prototype.cut=function(a){var b=ParaPara.MoveToSegment,c=ParaPara.LineToSegment,d=ParaPara.Geometry.prettyMuchEqual,e=a.getBBox();if(!ParaPara.Geometry.lineIntersectsRect(this.points,e))return this;var f=a.transformPoints(this.points),g=a.getDimensions(),h={x:0,y:0,width:g.length,height:g.width};if(ParaPara.Geometry.rectContainsLine(h,f))return new b(this.points.slice(2));for(var i=[],j=0;4>j;++j){var k=3>j?a.path.slice(2*j,2*j+4):a.path.slice(2*j,2*j+2).concat(a.path.slice(0,2)),l=ParaPara.Geometry.segmentsIntersect(this.points,k);if(l){if(i.length&&d(l[0],i[i.length-2])&&d(l[1],i[i.length-1]))continue;if(i.push(l[0],l[1]),4==i.length)break}}if(!i.length)return this;if(4==i.length){var m,n;if(this.points[2]==this.points[0]?(m=3,n=1):(m=2,n=0),this.points[m]-this.points[n]<0!=i[m]-i[n]<0){var o=i.slice(0,2);i[0]=i[2],i[1]=i[3],i[2]=o[0],i[3]=o[1]}}for(var p=f[0]>=0&&f[0]<=g.length&&f[1]>=0&&f[1]<=g.width,q=[],r=this.points.slice(0,2).concat(i,this.points.slice(2)),j=0;j<r.length-2;j+=2)p?q.push(new b(r.slice(j+2,j+4))):q.push(new c(r.slice(j,j+4))),p=!p;return q},ParaPara.LineToSegment.prototype.toString=function(){return"L"+this.points.slice(2).map(ParaPara.fixPrecision).join(" ")},ParaPara.CurveToSegment=function(a){console.assert(a instanceof Array&&8==a.length,"Unexpected segment length"),this.points=a},ParaPara.CurveToSegment.prototype.cut=function(a){var b=ParaPara.MoveToSegment,c=ParaPara.CurveToSegment,d=ParaPara.Geometry.lineLength,e=(ParaPara.Geometry.segmentsIntersect,a.getBBox()),f=this.getBBox();if(!ParaPara.Geometry.rectsIntersect(e,f))return this;var g=new c(a.transformPoints(this.points)),h=a.getDimensions(),i={x:0,y:0,width:h.length,height:h.width},j=d(this.points[0],this.points[1],this.points[6],this.points[7]);if(j<.75*a.width){var k=[g.points[0],g.points[1],g.points[6],g.points[7]];return ParaPara.Geometry.intersectsWithZeroedRect(k,i)?new b(this.points.slice(6)):this}var l=g.getBBox();if(ParaPara.Geometry.rectContainsRect(i,l))return new b(this.points.slice(6));if(!ParaPara.Geometry.rectsIntersect(l,i))return this;for(var m=1/ParaPara.erasePrecision,n=g.getValue(0),o=[],p=n[0]>=0&&n[0]<=h.length&&n[1]>=0&&n[1]<=h.width,q=m;1>=q;q+=m){var r=g.getValue(q),s=ParaPara.Geometry.intersectsWithZeroedRect([n[0],n[1],r[0],r[1]],h.length,h.width);if(s.length)for(var t=d(n[0],n[1],r[0],r[1]),u=0;u<s.length;++u){var v=s[u];if(v[0]!=n[0]||v[1]!=n[1]){var w=d(n[0],n[1],v[0],v[1])/t,x=q-m+m*w;o.push(x)}}n=r}if(!o.length&&!p)return this;o.sort(function(a,b){return a-b});for(var y=p,z=[],A=this.points,B=0,u=0;u<o.length;++u){var q=o[u],C=(q-B)/(1-B),D=this.splitSegment(A,C);y?z.push(new b(D[0].slice(6))):z.push(new c(D[0])),A=D[1],y=!y,B=q}return y?z.push(new b(A.slice(6))):z.push(new c(A)),z},ParaPara.CurveToSegment.prototype.splitSegment=function(a,b){for(var c=[a[0],a[1]],d=[a[6],a[7]],e=a,f=[],g=3;g>=1;--g){f=[];for(var h=0;g>h;++h)f.push(e[2*h]*(1-b)+e[2*h+2]*b),f.push(e[2*h+1]*(1-b)+e[2*h+3]*b);c.push(f[0],f[1]),d.unshift(f[2*(g-1)],f[2*(g-1)+1]),e=f}return[c,d]},ParaPara.CurveToSegment.prototype.getValue=function(a){return[this.getX(a),this.getY(a)]},ParaPara.CurveToSegment.prototype.getX=function(a){return this.computeCubicBaseValue(a,this.points[0],this.points[2],this.points[4],this.points[6])},ParaPara.CurveToSegment.prototype.getY=function(a){return this.computeCubicBaseValue(a,this.points[1],this.points[3],this.points[5],this.points[7])},ParaPara.CurveToSegment.prototype.computeCubicBaseValue=function(a,b,c,d,e){var f=1-a;return f*f*f*b+3*f*f*a*c+3*f*a*a*d+a*a*a*e},ParaPara.CurveToSegment.prototype.getBBox=function(){var a=Math.min(this.points[0],this.points[2],this.points[4],this.points[6]),b=Math.min(this.points[1],this.points[3],this.points[5],this.points[7]),c=Math.max(this.points[0],this.points[2],this.points[4],this.points[6]),d=Math.max(this.points[1],this.points[3],this.points[5],this.points[7]);return{x:a,y:b,width:c-a,height:d-b}},ParaPara.CurveToSegment.prototype.toString=function(){return"C"+this.points.slice(2).map(ParaPara.fixPrecision).join(" ")};var ParaPara=ParaPara||{};ParaPara.SVG_NS="http://www.w3.org/2000/svg",ParaPara.XLINK_NS="http://www.w3.org/1999/xlink",ParaPara.init=function(a){console.assert(!a.hasChildNodes(),"Content group should be empty"),ParaPara.contentGroup=a,ParaPara.svgRoot=ParaPara.contentGroup.ownerSVGElement,ParaPara.editContent=document.createElementNS(ParaPara.SVG_NS,"g"),ParaPara.contentGroup.appendChild(ParaPara.editContent),ParaPara.drawControls=new ParaPara.DrawControls,ParaPara.eraseControls=new ParaPara.EraseControls,ParaPara.frames=new ParaPara.FrameList,ParaPara.currentStyle=new ParaPara.Style,ParaPara.history=new ParaPara.HistoryManager,ParaPara.currentTool=null},ParaPara.reset=function(){for(;ParaPara.contentGroup.hasChildNodes();)ParaPara.contentGroup.removeChild(ParaPara.contentGroup.lastChild);ParaPara.init(ParaPara.contentGroup)},ParaPara.appendFrame=function(){var a=ParaPara.frames.appendFrame();return ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame()),ParaPara.history.add("insert",ParaPara.frames.getCurrentIndex()),a},ParaPara.selectFrame=function(a){var b=ParaPara.frames.selectFrame(a);return ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame()),b},ParaPara.deleteFrame=function(a){ParaPara.history.add("delete",a);var b=ParaPara.frames.deleteFrame(a);return ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame()),b},ParaPara.getCurrentFrame=function(a){var b=ParaPara.frames.getCurrentFrame(),a=ParaPara.frames.getCurrentIndex();return{index:a,svg:b}},ParaPara.setDrawMode=function(){return ParaPara.currentTool===ParaPara.drawControls?!1:(ParaPara.currentTool&&ParaPara.currentTool.disable(),ParaPara.drawControls.targetFrame(ParaPara.frames.getCurrentFrame()),ParaPara.currentTool=ParaPara.drawControls,!0)},ParaPara.setEraseMode=function(){return ParaPara.currentTool===ParaPara.eraseControls?!1:(ParaPara.currentTool&&ParaPara.currentTool.disable(),ParaPara.eraseControls.targetFrame(ParaPara.frames.getCurrentFrame()),ParaPara.currentTool=ParaPara.eraseControls,!0)},ParaPara.animate=function(a){ParaPara.currentTool&&ParaPara.currentTool.disable(),ParaPara.editContent.setAttribute("display","none"),ParaPara.animator=new ParaPara.Animator(a,ParaPara.contentGroup),ParaPara.animator.makeAnimation(),ParaPara.svgRoot.unpauseAnimations()},ParaPara.pauseAnimation=function(){ParaPara.animator&&ParaPara.svgRoot.pauseAnimations()},ParaPara.resumeAnimation=function(){ParaPara.animator&&ParaPara.svgRoot.unpauseAnimations()},ParaPara.removeAnimation=function(){ParaPara.animator&&(ParaPara.animator.removeAnimation(),ParaPara.animator=null,ParaPara.svgRoot.unpauseAnimations()),ParaPara.editContent.removeAttribute("display"),ParaPara.currentTool&&ParaPara.currentTool.targetFrame(ParaPara.frames.getCurrentFrame())},ParaPara.getMode=function(){return ParaPara.currentTool===ParaPara.drawControls?"draw":ParaPara.currentTool===ParaPara.eraseControls?"erase":ParaPara.animator?"animate":"draw"},ParaPara.send=function(a,b,c,d){console.assert(ParaPara.animator,"No animator found");var e=ParaPara.animator.exportAnimation(d.title,d.author);if(!e)return void c("no-animation");var f={metadata:d},g=new XMLSerializer,h=g.serializeToString(e.doc);f.svg=h,f.metadata.groundOffset=e.groundOffset,f.metadata.width=e.width,f.metadata.height=e.height,ParaPara.postRequest(a,f,b,c)},ParaPara.sendEmail=function(a,b,c,d,e){var f={address:a,locale:c};ParaPara.postRequest(b,f,d,e)},ParaPara.fixPrecision=function(a){return a.toFixed(2)},ParaPara.notifyGraphicChanged=function(){var a=document.createEvent("CustomEvent");a.initCustomEvent("changegraphic",!0,!0,{}),ParaPara.svgRoot.dispatchEvent(a)},ParaPara.notifyHistoryChanged=function(a){var b=document.createEvent("CustomEvent");b.initCustomEvent("changehistory",!0,!0,a),ParaPara.svgRoot.dispatchEvent(b)},ParaPara.DrawControls=function(){this.linesInProgress=new Object,this.frame=null,this.mouseDownHandler=this.mouseDown.bind(this),this.mouseMoveHandler=this.mouseMove.bind(this),this.mouseUpHandler=this.mouseUp.bind(this),this.touchStartHandler=this.touchStart.bind(this),this.touchMoveHandler=this.touchMove.bind(this),this.touchEndHandler=this.touchEnd.bind(this),this.touchCancelHandler=this.touchCancel.bind(this)},ParaPara.DrawControls.prototype.targetFrame=function(a){this.frame=a,ParaPara.svgRoot.addEventListener("mousedown",this.mouseDownHandler,!1),ParaPara.svgRoot.addEventListener("mousemove",this.mouseMoveHandler,!1),ParaPara.svgRoot.addEventListener("mouseup",this.mouseUpHandler,!1),ParaPara.svgRoot.addEventListener("touchstart",this.touchStartHandler,!1),ParaPara.svgRoot.addEventListener("touchmove",this.touchMoveHandler,!1),ParaPara.svgRoot.addEventListener("touchend",this.touchEndHandler,!1),ParaPara.svgRoot.addEventListener("touchcancel",this.touchCancelHandler,!1)},ParaPara.DrawControls.prototype.disable=function(){ParaPara.svgRoot.removeEventListener("mousedown",this.mouseDownHandler,!1),ParaPara.svgRoot.removeEventListener("mousemove",this.mouseMoveHandler,!1),ParaPara.svgRoot.removeEventListener("mouseup",this.mouseUpHandler,!1),ParaPara.svgRoot.removeEventListener("touchstart",this.touchStartHandler,!1),ParaPara.svgRoot.removeEventListener("touchmove",this.touchMoveHandler,!1),ParaPara.svgRoot.removeEventListener("touchend",this.touchEndHandler,!1),ParaPara.svgRoot.removeEventListener("touchcancel",this.touchCancelHandler,!1)},ParaPara.DrawControls.prototype.mouseDown=function(a){if(a.preventDefault(),!a.button&&!this.linesInProgress.mouseLine){ParaPara.history.add("update",ParaPara.frames.getCurrentIndex());var b=this.getLocalCoords(a.clientX,a.clientY,this.frame);this.linesInProgress.mouseLine=new ParaPara.FreehandLine(b.x,b.y,this.frame)}},ParaPara.DrawControls.prototype.mouseMove=function(a){if(a.preventDefault(),this.linesInProgress.mouseLine){var b=this.getLocalCoords(a.clientX,a.clientY,this.frame);this.linesInProgress.mouseLine.addPoint(b.x,b.y)}},ParaPara.DrawControls.prototype.mouseUp=function(a){a.preventDefault(),this.linesInProgress.mouseLine&&(this.linesInProgress.mouseLine.finishLine(),delete this.linesInProgress.mouseLine,ParaPara.notifyGraphicChanged())},ParaPara.DrawControls.prototype.touchStart=function(a){a.preventDefault(),ParaPara.history.add("update",ParaPara.frames.getCurrentIndex());for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b],d=this.getLocalCoords(c.clientX,c.clientY,this.frame);this.linesInProgress[c.identifier]=new ParaPara.FreehandLine(d.x,d.y,this.frame)}},ParaPara.DrawControls.prototype.touchMove=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b],d=this.getLocalCoords(c.clientX,c.clientY,this.frame);console.assert(this.linesInProgress[c.identifier],"Unexpected touch event"),this.linesInProgress[c.identifier].addPoint(d.x,d.y)}},ParaPara.DrawControls.prototype.touchEnd=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];console.assert(this.linesInProgress[c.identifier],"Unexpected touch event"),this.linesInProgress[c.identifier].finishLine(),delete this.linesInProgress[c.identifier]}ParaPara.notifyGraphicChanged()},ParaPara.DrawControls.prototype.touchCancel=function(a){a.preventDefault();for(var b=0;b<a.changedTouches.length;++b){var c=a.changedTouches[b];console.assert(this.linesInProgress[c.identifier],"Unexpected touch event"),this.linesInProgress[c.identifier].cancelLine(),delete this.linesInProgress[c.identifier]}},ParaPara.DrawControls.prototype.getLocalCoords=function(a,b,c){var d=ParaPara.svgRoot.createSVGPoint();d.x=a,d.y=b;var e=c.parentNode.getScreenCTM();return d.matrixTransform(e.inverse())},ParaPara.FreehandLine=function(a,b,c){this.polyline=document.createElementNS(ParaPara.SVG_NS,"polyline"),ParaPara.currentStyle.styleStroke(this.polyline),c.appendChild(this.polyline);var d=ParaPara.svgRoot.createSVGPoint();d.x=a,d.y=b,this.polyline.points.appendItem(d)},ParaPara.FreehandLine.prototype.addPoint=function(a,b){console.assert(this.polyline,"Adding point to finished/cancelled line?");var c=ParaPara.svgRoot.createSVGPoint();c.x=a,c.y=b,this.polyline.points.appendItem(c)},ParaPara.FreehandLine.prototype.finishLine=function(){console.assert(this.polyline,"Line already finished/cancelled?");var a=this.createPathFromPoints(this.polyline.points);this.polyline.parentNode.appendChild(a),this.polyline.parentNode.removeChild(this.polyline),this.polyline=null},ParaPara.FreehandLine.prototype.cancelLine=function(){console.assert(this.polyline,"Line already finished/cancelled?"),this.polyline.parentNode.removeChild(this.polyline),this.polyline=null},ParaPara.FreehandLine.prototype.createPathFromPoints=function(a){if(1==a.numberOfItems)return this.createPoint(a);var b=document.createElementNS(ParaPara.SVG_NS,"path");ParaPara.currentStyle.styleStroke(b);var c=ParaPara.fixPrecision;if(2==a.numberOfItems){var d=a.getItem(0),e=a.getItem(1),f="M"+[d.x,d.y].map(c).join(" ")+"L"+[e.x,e.y].map(c).join(" ");b.setAttribute("d",f)}else{a=this.prunePoints(a);var d=a[0],f="M"+[d.x,d.y].map(c).join(" ")+"C"+this.smoothPoints(a).map(c).join(" ");b.setAttribute("d",f)}return b},ParaPara.FreehandLine.prototype.createPoint=function(a){console.assert(1===a.numberOfItems,"Expected only one point");var b=document.createElementNS(ParaPara.SVG_NS,"circle");return b.setAttribute("r",ParaPara.currentStyle.strokeWidth/2),b.setAttribute("cx",a.getItem(0).x),b.setAttribute("cy",a.getItem(0).y),ParaPara.currentStyle.styleFill(b),b},ParaPara.FreehandLine.prototype.prunePoints=function(a){for(var b=a.numberOfItems,c=20>b?10>b?1:2:3,d=[],e=0;b-c>e;e+=c){var f=a.getItem(e);d.push({x:f.x,y:f.y})}var g=a.getItem(b-1);return d.push({x:g.x,y:g.y}),d},ParaPara.FreehandLine.prototype.smoothPoints=function(a){for(var b=a[0],c=[b.x,b.y],d=a.length,e=1;d>e;e++){var f=a[e-1],g=a[e],h=a[d-1>e?e+1:e],i=Math.atan2(f.y-g.y,f.x-g.x),j=Math.atan2(h.y-g.y,h.x-g.x),k=(i+j)/2+Math.PI/2,l=ParaPara.Geometry.lineLength(g.x,g.y,h.x,h.y)/3;0>i-j&&(k+=Math.PI);var m=Math.cos(k)*l,n=Math.sin(k)*l;c[c.length]=g.x+m,c[c.length]=g.y+n,c[c.length]=g.x,c[c.length]=g.y,d-1>e&&(c[c.length]=g.x-m,c[c.length]=g.y-n)}return c},ParaPara.Style=function(){this.currentColor="black",this.strokeWidth=4,this._eraseWidth=4},ParaPara.Style.prototype.styleStroke=function(a){a.setAttribute("stroke",this.currentColor),a.setAttribute("stroke-width",this.strokeWidth),a.setAttribute("stroke-linecap","round"),a.setAttribute("fill","none"),a.setAttribute("pointer-events","none")},ParaPara.Style.prototype.styleFill=function(a){a.setAttribute("fill",this.currentColor),a.setAttribute("stroke","none"),a.setAttribute("pointer-events","none")},ParaPara.Style.prototype.__defineSetter__("eraseWidth",function(a){this._eraseWidth=a,ParaPara.eraseControls.setBrushWidth(this._eraseWidth)}),ParaPara.Style.prototype.__defineGetter__("eraseWidth",function(){return this._eraseWidth}),ParaPara.FrameList=function(){this.currentFrame=null,this.scene=ParaPara.editContent,this.appendFrame()},ParaPara.FrameList.prototype.getCurrentFrame=function(){return this.currentFrame},ParaPara.FrameList.prototype.appendFrame=function(){this.selectFrame(this.getFrameCount()-1);var a=this.getPrevFrame();a&&this.getOrMakeOldFrames().appendChild(a),this.currentFrame&&this.getOrMakePrevFrames().appendChild(this.currentFrame);var b=document.createElementNS(ParaPara.SVG_NS,"g");b.setAttribute("class","frame"),this.scene.appendChild(b),this.currentFrame=b},ParaPara.FrameList.prototype.insertFrame=function(a,b){if(!(0>a||a>=this.getFrameCount()+1)&&this.currentFrame){var c=this.getCurrentIndex();this.selectFrame(0);var d=this.getOrMakeNextFrames();0===a?(this.currentFrame.parentNode.replaceChild(b,this.currentFrame),d.insertBefore(this.currentFrame,d.firstChild),this.currentFrame=b):d.hasChildNodes()?d.insertBefore(b,d.childNodes[a-1]):d.appendChild(b),c>=a&&c++,this.selectFrame(c)}},ParaPara.FrameList.prototype.selectFrame=function(a){if(!(0>a||a>=this.getFrameCount())&&this.currentFrame){var b=this.getCurrentIndex();if(a!==b)if(b>a){var c=b-a,d=this.getOrMakeNextFrames();if(d.insertBefore(this.currentFrame,d.firstChild),this.currentFrame=null,c>1)d.insertBefore(this.getPrevFrame(),d.firstChild);else{var e=this.getPrevFrame();this.scene.insertBefore(e,this.getNextFrames()),this.currentFrame=e}for(var f=this.getOldFrames(),g=this.getPrevFrames();c>0&&f&&0!==f.childNodes.length;){var h=this.getOldFrames().lastChild;switch(c){case 1:g.appendChild(h);break;case 2:this.scene.insertBefore(h,d),this.currentFrame=h;break;default:d.insertBefore(h,d.firstChild)}c--}f&&!f.hasChildNodes()&&f.parentNode.removeChild(f),g&&!g.hasChildNodes()&&g.parentNode.removeChild(g)}else{var c=a-b,e=this.getPrevFrame();e&&this.getOrMakeOldFrames().appendChild(e),c>1?this.getOrMakeOldFrames().appendChild(this.currentFrame):this.getOrMakePrevFrames().appendChild(this.currentFrame);for(var d=this.getNextFrames();c>0&&d&&0!==d.childNodes.length;){var h=this.getNextFrames().firstChild;switch(c){case 1:this.scene.insertBefore(h,d),this.currentFrame=h;break;case 2:this.getOrMakePrevFrames().appendChild(h);break;default:this.getOrMakeOldFrames().appendChild(h)}c--}d&&!d.hasChildNodes()&&d.parentNode.removeChild(d)}}},ParaPara.FrameList.prototype.deleteFrame=function(a){if(!(0>a||a>=this.getFrameCount())&&this.currentFrame){var b=this.getCurrentIndex();if(this.selectFrame(0),0===a){this.currentFrame.parentNode.removeChild(this.currentFrame),this.currentFrame=null;var c=this.getNextFrames();if(c){var d=c.firstChild;this.scene.insertBefore(d,c),this.currentFrame=d}else this.appendFrame()}else{var c=this.getNextFrames();c.removeChild(c.childNodes[a-1])}var c=this.getNextFrames();c&&!c.hasChildNodes()&&c.parentNode.removeChild(c),this.selectFrame(Math.min(b,this.getFrameCount()-1))}},ParaPara.FrameList.prototype.getFrames=function(){return this.scene.getElementsByClassName("frame")},ParaPara.FrameList.prototype.getFrame=function(a){return 0>a||a>=this.getFrameCount()?void 0:this.getFrames()[a]},ParaPara.FrameList.prototype.getCurrentIndex=function(){return this.getOldFrames()?this.getOldFrames().childNodes.length+1:this.getPrevFrame()?1:0},ParaPara.FrameList.prototype.getFrameCount=function(){return this.getFrames().length},ParaPara.FrameList.prototype.getPrevFrame=function(){var a=this.getPrevFrames();return a?a.lastChild:null},ParaPara.FrameList.prototype.getPrevFrames=function(){return this._getPrevFrames(!1)},ParaPara.FrameList.prototype.getOrMakePrevFrames=function(){return this._getPrevFrames(!0)},ParaPara.FrameList.prototype._getPrevFrames=function(a){return this._getOrMakeGroup(this.scene,!0,"prevFrames",a)},ParaPara.FrameList.prototype.getOldFrames=function(){var a=this.getPrevFrames();return a?this._getOrMakeGroup(a,!0,"oldFrames",!1):null},ParaPara.FrameList.prototype.getOrMakeOldFrames=function(){var a=this.getOrMakePrevFrames();return this._getOrMakeGroup(a,!0,"oldFrames",!0)},ParaPara.FrameList.prototype.getNextFrames=function(){return this._getNextFrames(!1)},ParaPara.FrameList.prototype.getOrMakeNextFrames=function(){return this._getNextFrames(!0)},ParaPara.FrameList.prototype._getNextFrames=function(a){return this._getOrMakeGroup(this.scene,!1,"nextFrames",a)},ParaPara.FrameList.prototype._getOrMakeGroup=function(a,b,c,d){var e=b?a.firstChild:a.lastChild;if(e&&e.classList.contains(c))return e;if(!d)return null;var f=document.createElementNS(ParaPara.SVG_NS,"g");return f.setAttribute("class",c),a.insertBefore(f,b?a.firstChild:null)},ParaPara.Animator=function(a,b){this.dur=1/a,this.animation=document.createElementNS(ParaPara.SVG_NS,"g"),b.appendChild(this.animation)},ParaPara.Animator.prototype.makeAnimation=function(){for(var a=ParaPara.frames.getFrames(),b="",c=0;c<a.length;++c){var d=a[c];d.hasChildNodes()&&this.animation.appendChild(d.cloneNode(!0))}if(a=this.animation.childNodes,!(a.length<2)){for(var c=0;c<a.length;++c){var d=a[c];d.removeAttribute("class"),d.setAttribute("visibility","hidden");var e=document.createElementNS(ParaPara.SVG_NS,"set");e.setAttribute("attributeName","visibility"),e.setAttribute("to","visible"),e.setAttribute("dur",this.dur+"s");var f="anim"+ParaPara.Utils.uuid();
+e.setAttribute("id",f),b&&e.setAttribute("begin",b+".end"),d.appendChild(e),b=f}var g=a[0].getElementsByTagName("set")[0];g.setAttribute("begin","0; "+b+".end"),ParaPara.svgRoot.setCurrentTime(0)}},ParaPara.Animator.prototype.removeAnimation=function(){this.animation&&this.animation.parentNode&&this.animation.parentNode.removeChild(this.animation),this.animation=null},ParaPara.Animator.prototype.exportAnimation=function(a,b){var c=document.implementation.createDocument(ParaPara.SVG_NS,"svg",null),d=c.documentElement;if(d.setAttribute("width","100%"),d.setAttribute("height","100%"),d.pauseAnimations(),a){var e=c.createElementNS(ParaPara.SVG_NS,"title");e.appendChild(c.createTextNode(a)),d.appendChild(e)}if(b){var f=c.createElementNS(ParaPara.SVG_NS,"desc"),g=b+"さんより";f.appendChild(c.createTextNode(g)),d.appendChild(f)}var h=minY=Number.POSITIVE_INFINITY,i=maxY=Number.NEGATIVE_INFINITY,j=this.animation.childNodes;if(!j.length)return null;for(var k=0;k<j.length;++k){var l=j[k];console.assert(l.childNodes.length,"Empty frames should have already been dropped");var m=this.getDecoratedBbox(l);h=Math.floor(Math.min(h,m.x)),i=Math.ceil(Math.max(i,m.x+m.width)),minY=Math.floor(Math.min(minY,m.y)),maxY=Math.ceil(Math.max(maxY,m.y+m.height));var n=c.importNode(l,!0);n.removeAttribute("style"),d.appendChild(n)}var o=ParaPara.svgRoot.getAttribute("viewBox");console.assert(o,"No parent viewBox"),o=o.trim().split(" ").map(parseFloat),h=Math.max(h,o[0]),i=Math.min(i,o[0]+o[2]),minY=Math.max(minY,o[1]),maxY=Math.min(maxY,o[1]+o[3]),d.setAttribute("viewBox",[h,minY,i-h,maxY-minY].join(" "));var p=(o[3]-maxY)/(o[3]-o[1]);return d.setAttribute("data-ground-offset",p.toFixed(3)),{doc:c,groundOffset:p,width:i-h,height:maxY-minY}},ParaPara.Animator.prototype.getDecoratedBbox=function(a){for(var b=a.getBBox(),c=0,d=a.querySelectorAll("path"),e=0;e<d.length;e++){var f=parseInt(window.getComputedStyle(d[e]).strokeWidth);c=Math.max(c,f)}return b.x-=c/2,b.y-=c/2,b.width+=c,b.height+=c,b},ParaPara.Animator.prototype.setSpeed=function(a){this.dur=1/a;for(var b=this.animation.getElementsByTagName("set"),c=0;c<b.length;++c){var d=b[c];d.setAttribute("dur",this.dur+"s")}},ParaPara.Utils={},ParaPara.Utils.uuid=function(){return UUID.generate().replace(/-/g,"")},ParaPara.HistoryManager=function(){this.MAX_STACK_SIZE=50,this.undoStack=[],this.redoStack=[]},ParaPara.HistoryManager.prototype["do"]=function(a){a.svg=a.svg.cloneNode(!0);var b=a.index;switch(a.cmd){case"update":ParaPara.frames.selectFrame(a.index),ParaPara.editContent.replaceChild(a.svg,ParaPara.frames.getCurrentFrame()),ParaPara.frames.currentFrame=a.svg;break;case"insert":ParaPara.frames.insertFrame(a.index,a.svg);break;case"delete":ParaPara.frames.deleteFrame(a.index),b=ParaPara.frames.getCurrentIndex()}ParaPara.selectFrame(b),ParaPara.notifyHistoryChanged(a)},ParaPara.HistoryManager.prototype.undo=function(){if(0!==this.undoStack.length){var a=this.undoStack.pop(),b=a.cmd;switch(b){case"update":this.add("update",a.index,!1),this.redoStack.push(this.undoStack.pop());break;case"insert":b="delete",this.redoStack.push(a);break;case"delete":b="insert",this.redoStack.push(a)}this["do"]({cmd:b,index:a.index,svg:a.svg})}},ParaPara.HistoryManager.prototype.redo=function(){if(0!==this.redoStack.length){var a=this.redoStack.pop();switch(a.cmd){case"update":this.add("update",a.index,!1);break;case"insert":case"delete":this.undoStack.push(a)}this["do"](a)}},ParaPara.HistoryManager.prototype.add=function(a,b,c){this.undoStack.length>=this.MAX_STACK_SIZE&&this.undoStack.shift(),this.undoStack.push({cmd:a,index:b,svg:ParaPara.frames.getFrame(b).cloneNode(!0)}),c!==!1&&(this.redoStack=[])},"undefined"==typeof document||"classList"in document.createElement("a")&&"classList"in document.createElementNS("http://www.w3.org/2000/svg","g")||!function(a){"use strict";var b="http://www.w3.org/2000/svg",c="classList",d="prototype",e=Object,f=String[d].trim||function(){return this.replace(/^\s+|\s+$/g,"")},g=Array[d].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1},h=function(a,b){this.name=a,this.code=DOMException[a],this.message=b},i=function(a,b){if(""===b)throw new h("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(b))throw new h("INVALID_CHARACTER_ERR","String contains an invalid character");return g.call(a,b)},j=function(a){for(var b="undefined"!=typeof a.className.baseVal?a.className.baseVal:a.className,c=f.call(b),d=c?c.split(/\s+/):[],e=0,g=d.length;g>e;e++)this.push(d[e]);this._updateClassName=function(){"undefined"!=typeof a.className.baseVal?a.className.baseVal=this.toString():a.className=this.toString()}},k=j[d]=[],l=function(){return new j(this)},m=function(a){if(e.defineProperty){var b={get:l,enumerable:!0,configurable:!0};try{e.defineProperty(a[d],c,b)}catch(f){-2146823252===f.number&&(b.enumerable=!1,e.defineProperty(a[d],c,b))}}else e[d].__defineGetter__&&elemCtrl[d].__defineGetter__(c,l)},n=function(a,c){"classList"in a.createElement("a")||m(c.HTMLElement||c.Element),"classList"in a.createElementNS(b,"g")||m(c.SVGElement)},o=function(a){if(a.contentDocument&&"complete"==a.contentDocument.readyState){var b=a.contentWindow||a.contentDocument.defaultView;n(a.contentDocument,b)}},p=function(){for(var a=document.getElementsByTagName("object"),b=0;b<a.length;++b)o(a[b])},q=function(){p(),document.addEventListener("DOMNodeInserted",r,!0)},r=function(a){o(a.srcElement),a.srcElement.addEventListener("load",p,!0)};h[d]=Error[d],k.item=function(a){return this[a]||null},k.contains=function(a){return a+="",-1!==i(this,a)},k.add=function(a){a+="",-1===i(this,a)&&(this.push(a),this._updateClassName())},k.remove=function(a){a+="";var b=i(this,a);-1!==b&&(this.splice(b,1),this._updateClassName())},k.toggle=function(a){a+="",-1===i(this,a)?this.add(a):this.remove(a)},k.toString=function(){return this.join(" ")},n(document,a),"complete"!=document.readyState?(document.addEventListener("DOMContentLoaded",q,!0),window.addEventListener("load",p,!0)):q()}(self),UUID.generate=function(){var a=UUID._gri,b=UUID._ha;return b(a(32),8)+"-"+b(a(16),4)+"-"+b(16384|a(12),4)+"-"+b(32768|a(14),4)+"-"+b(a(48),12)},UUID._gri=function(a){return 0>a?NaN:30>=a?0|Math.random()*(1<<a):53>=a?(0|Math.random()*(1<<30))+(0|Math.random()*(1<<a-30))*(1<<30):NaN},UUID._ha=function(a,b){for(var c=a.toString(16),d=b-c.length,e="0";d>0;d>>>=1,e+=e)1&d&&(c=e+c);return c};var ParaPara=ParaPara||{};ParaPara.XHR_TIMEOUT=8e3,ParaPara.postRequest=function(a,b,c,d){var e=JSON.stringify(b),f=new XMLHttpRequest;f.open("POST",a,!0),f.setRequestHeader("Content-Type","application/json"),f.onreadystatechange=function(){if(4==f.readyState)if(200==f.status||0==f.status)try{var a=JSON.parse(f.responseText);a.error_key?d(a.error_key,a.error_detail):c(JSON.parse(f.responseText))}catch(b){if(!(b instanceof SyntaxError))throw b;console.debug("Error sending to server, could not parse response: "+f.responseText),d("server-fail")}else d("no-access")};try{f.send(e)}catch(g){return console.debug(g),void d("send-fail")}window.setTimeout(function(){0!=f.readyState&&4!=f.readyState&&(f.abort(),d("timeout"))},ParaPara.XHR_TIMEOUT),ParaPara.abortRequest=function(){0!=f.readyState&&4!=f.readyState&&f.abort()}},ParaPara.abortRequest=function(){};

0 comments on commit 358fe05

Please sign in to comment.