pushing preview for import
3
.gitignore
vendored
@ -4,6 +4,9 @@
|
||||
# nodejs local installs
|
||||
node_modules
|
||||
|
||||
#build artifacts
|
||||
build
|
||||
|
||||
# sublime text stuff (the -project should actually be shared, but then we'd have to share the same disk location)
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
|
189
closure_compiled_binary.js
Normal file
@ -0,0 +1,189 @@
|
||||
var Constants={DEFAULT:{HEIGHT:32,WIDTH:32,FPS:12},MODEL_VERSION:1,MAX_HEIGHT:128,MAX_WIDTH:128,PREVIEW_FILM_SIZE:120,DEFAULT_PEN_COLOR:"#000000",TRANSPARENT_COLOR:"TRANSPARENT",SELECTION_TRANSPARENT_COLOR:"rgba(255, 255, 255, 0.6)",TOOL_TARGET_HIGHLIGHT_COLOR:"rgba(255, 255, 255, 0.2)",STATIC:{URL:{SAVE:"http://3.piskel-app.appspot.com/store",GET:"http://3.piskel-app.appspot.com/get"}},APPENGINE:{URL:{SAVE:"save"}},IMAGE_SERVICE_UPLOAD_URL:"http://screenletstore.appspot.com/__/upload",IMAGE_SERVICE_GET_URL:"http://screenletstore.appspot.com/img/",
|
||||
GRID_STROKE_WIDTH:1,LEFT_BUTTON:"left_button_1",RIGHT_BUTTON:"right_button_2"};var Events={TOOL_SELECTED:"TOOL_SELECTED",TOOL_RELEASED:"TOOL_RELEASED",PRIMARY_COLOR_SELECTED:"PRIMARY_COLOR_SELECTED",PRIMARY_COLOR_UPDATED:"PRIMARY_COLOR_UPDATED",SECONDARY_COLOR_SELECTED:"SECONDARY_COLOR_SELECTED",SECONDARY_COLOR_UPDATED:"SECONDARY_COLOR_UPDATED",LOCALSTORAGE_REQUEST:"LOCALSTORAGE_REQUEST",CANVAS_RIGHT_CLICKED:"CANVAS_RIGHT_CLICKED",REFRESH:"REFRESH",REDRAW_PREVIEWFILM:"REDRAW_PREVIEWFILM",USER_SETTINGS_CHANGED:"USER_SETTINGS_CHANGED",CLOSE_SETTINGS_DRAWER:"CLOSE_SETTINGS_DRAWER",
|
||||
PISKEL_RESET:"PISKEL_RESET",FRAME_SIZE_CHANGED:"FRAME_SIZE_CHANGED",CURRENT_FRAME_SET:"CURRENT_FRAME_SET",SELECTION_CREATED:"SELECTION_CREATED",SELECTION_MOVE_REQUEST:"SELECTION_MOVE_REQUEST",SELECTION_DISMISSED:"SELECTION_DISMISSED",SHOW_NOTIFICATION:"SHOW_NOTIFICATION",HIDE_NOTIFICATION:"HIDE_NOTIFICATION",UNDO:"UNDO",REDO:"REDO",CUT:"CUT",COPY:"COPY",PASTE:"PASTE"};(function(){$.namespace("pskl").app={init:function(){var a=this.readSizeFromURL_(),d=new pskl.model.Piskel(a.width,a.height),b=new pskl.model.Layer("Layer 1"),a=new pskl.model.Frame(a.width,a.height);b.addFrame(a);d.addLayer(b);this.piskelController=new pskl.controller.PiskelController(d);this.drawingController=new pskl.controller.DrawingController(this.piskelController,$("#drawing-canvas-container"));this.drawingController.init();this.animationController=new pskl.controller.AnimatedPreviewController(this.piskelController,
|
||||
$("#preview-canvas-container"));this.animationController.init();this.previewsController=new pskl.controller.PreviewFilmController(this.piskelController,$("#preview-list"));this.previewsController.init();this.layersListController=new pskl.controller.LayersListController(this.piskelController);this.layersListController.init();this.settingsController=new pskl.controller.settings.SettingsController(this.piskelController);this.settingsController.init();this.selectionManager=new pskl.selection.SelectionManager(this.piskelController);
|
||||
this.selectionManager.init();this.historyService=new pskl.service.HistoryService(this.piskelController);this.historyService.init();this.keyboardEventService=new pskl.service.KeyboardEventService;this.keyboardEventService.init();this.notificationController=new pskl.controller.NotificationController;this.notificationController.init();this.localStorageService=new pskl.service.LocalStorageService(this.piskelController);this.localStorageService.init();this.imageUploadService=new pskl.service.ImageUploadService;
|
||||
this.imageUploadService.init();this.toolController=new pskl.controller.ToolController;this.toolController.init();this.paletteController=new pskl.controller.PaletteController;this.paletteController.init();d=new pskl.rendering.DrawingLoop;d.addCallback(this.render,this);d.start();this.initBootstrapTooltips_();(this.isStaticVersion=!pskl.appEngineToken_)?this.finishInitStatic_():this.finishInitAppEngine_()},finishInitStatic_:function(){var a=this.readFramesheetIdFromURL_();a?($.publish(Events.SHOW_NOTIFICATION,
|
||||
[{content:"Loading animation with id : ["+a+"]"}]),this.loadFramesheetFromService(a)):this.localStorageService.displayRestoreNotification()},finishInitAppEngine_:function(){if(pskl.framesheetData_&&pskl.framesheetData_.content){var a=pskl.utils.Serializer.createPiskel(pskl.framesheetData_.content);pskl.app.piskelController.setPiskel(a);pskl.app.animationController.setFPS(pskl.framesheetData_.fps)}},initBootstrapTooltips_:function(){$("body").tooltip({selector:"[rel=tooltip]"})},render:function(a){this.drawingController.render(a);
|
||||
this.animationController.render(a);this.previewsController.render(a)},readSizeFromURL_:function(){var a,d=this.readUrlParameter_("size").split("x");!d||2!=d.length||isNaN(d[0])||isNaN(d[1])?a={height:Constants.DEFAULT.HEIGHT,width:Constants.DEFAULT.WIDTH}:(a=parseInt(d[0],10),d=parseInt(d[1],10),a={height:Math.min(d,Constants.MAX_HEIGHT),width:Math.min(a,Constants.MAX_WIDTH)});return a},readFramesheetIdFromURL_:function(){return this.readUrlParameter_("frameId")},readUrlParameter_:function(a){var d,
|
||||
b,c=window.location.search.substring(1).split("&");for(d=0;d<c.length;d++)if(b=c[d].split("="),b[0]==a)return window.unescape(b[1]);return""},loadFramesheetFromService:function(a){var d=new XMLHttpRequest;d.open("GET",Constants.STATIC.URL.GET+"?l="+a,!0);d.responseType="text";d.onload=function(d){d=JSON.parse(this.responseText);var a=pskl.utils.Serializer.createPiskel(d.framesheet);pskl.app.piskelController.setPiskel(a);pskl.app.animationController.setFPS(d.fps);$.publish(Events.HIDE_NOTIFICATION)};
|
||||
d.onerror=function(){$.publish(Events.HIDE_NOTIFICATION)};d.send()},storeSheet:function(a){this.isStaticVersion?this.storeSheetStatic_():this.storeSheetAppEngine_();a&&(a.stopPropagation(),a.preventDefault());return!1},storeSheetStatic_:function(){var a=new XMLHttpRequest,d=new FormData;d.append("framesheet_content",this.piskelController.serialize());d.append("fps_speed",$("#preview-fps").val());a.open("POST",Constants.STATIC.URL.SAVE,!0);a.onload=function(d){if(200==this.status)d=window.location.href.replace(window.location.search,
|
||||
""),window.location.href=d+"?frameId="+this.responseText;else this.onerror(d)};a.onerror=function(d){$.publish(Events.SHOW_NOTIFICATION,[{content:"Saving failed ("+this.status+")"}])};a.send(d)},storeSheetAppEngine_:function(){var a=new XMLHttpRequest,d=new FormData;d.append("framesheet_content",this.piskelController.serialize());d.append("fps_speed",$("#preview-fps").val());d.append("name",$("#piskel-name").val());d.append("frames",this.piskelController.getFrameCount());d.append("preview",this.getFirstFrameAsPng());
|
||||
d.append("framesheet",this.getFramesheetAsPng());a.open("POST",Constants.APPENGINE.URL.SAVE,!0);a.onload=function(d){if(200==this.status)$.publish(Events.SHOW_NOTIFICATION,[{content:"Successfully saved !"}]);else this.onerror(d)};a.onerror=function(d){$.publish(Events.SHOW_NOTIFICATION,[{content:"Saving failed ("+this.status+")"}])};a.send(d)},getFirstFrameAsPng:function(){var a=this.piskelController.getFrameAt(0),a=new pskl.rendering.CanvasRenderer(a,1);a.drawTransparentAs("rgba(0,0,0,0)");return a.render().canvas.toDataURL("image/png")},
|
||||
getFramesheetAsPng:function(){return(new pskl.rendering.SpritesheetRenderer(this.piskelController)).render().toDataURL("image/png")},uploadAsSpritesheetPNG:function(){var a=this.getFramesheetAsPng();this.imageUploadService.upload(a,this.openWindow.bind(this))},openWindow:function(a){var d=["dialog=yes,scrollbars=no,status=no","width="+this.piskelController.getWidth()*this.piskelController.getFrameCount(),"height="+this.piskelController.getHeight()].join();window.open(a,"piskel-export",d)}}})();(function(){var a=$.namespace("pskl.controller");a.AnimatedPreviewController=function(d,a,c){this.piskelController=d;this.container=a;this.currentIndex=this.elapsedTime=0;this.setFPS(Constants.DEFAULT.FPS);d={dpi:this.calculateDPI_()};this.renderer=new pskl.rendering.FrameRenderer(this.container,d);$.subscribe(Events.FRAME_SIZE_CHANGED,this.updateDPI_.bind(this))};a.AnimatedPreviewController.prototype.init=function(){$("#preview-fps")[0].addEventListener("change",this.onFPSSliderChange.bind(this))};
|
||||
a.AnimatedPreviewController.prototype.onFPSSliderChange=function(d){this.setFPS(parseInt($("#preview-fps")[0].value,10))};a.AnimatedPreviewController.prototype.setFPS=function(d){this.fps=d;$("#preview-fps").val(this.fps);$("#display-fps").html(this.fps+" FPS")};a.AnimatedPreviewController.prototype.getFPS=function(){return this.fps};a.AnimatedPreviewController.prototype.render=function(d){this.elapsedTime+=d;d=Math.floor(this.elapsedTime/(1E3/this.fps));d!=this.currentIndex&&(this.currentIndex=d,
|
||||
this.piskelController.hasFrameAt(this.currentIndex)||(this.elapsedTime=this.currentIndex=0),this.renderer.render(this.piskelController.getFrameAt(this.currentIndex)))};a.AnimatedPreviewController.prototype.calculateDPI_=function(){var d=this.piskelController.getCurrentFrame().getHeight(),a=this.piskelController.getCurrentFrame().getWidth();return pskl.PixelUtils.calculateDPI(200,200,d,a)};a.AnimatedPreviewController.prototype.updateDPI_=function(){this.dpi=this.calculateDPI_();this.renderer.setDPI(this.dpi)}})();(function(){var a=$.namespace("pskl.controller");a.DrawingController=function(d,a){this.piskelController=d;this.overlayFrame=pskl.model.Frame.createEmptyFromFrame(d.getCurrentFrame());this.container=a;this.dpi=this.calculateDPI_();var c={dpi:this.dpi,supportGridRendering:!0};this.overlayRenderer=new pskl.rendering.FrameRenderer(this.container,c,["canvas-overlay"]);this.renderer=new pskl.rendering.FrameRenderer(this.container,c,["drawing-canvas"]);this.layersBelowRenderer=new pskl.rendering.FrameRenderer(this.container,
|
||||
c,["layers-canvas","layers-below-canvas"]);this.layersAboveRenderer=new pskl.rendering.FrameRenderer(this.container,c,["layers-canvas","layers-above-canvas"]);this.isRightClicked=this.isClicked=!1;this.previousMousemoveTime=0;this.currentToolBehavior=null;this.primaryColor=Constants.DEFAULT_PEN_COLOR;this.secondaryColor=Constants.TRANSPARENT_COLOR};a.DrawingController.prototype.init=function(){this.initMouseBehavior();$.subscribe(Events.TOOL_SELECTED,$.proxy(function(d,a){console.log("Tool selected: ",
|
||||
a);this.currentToolBehavior=a;this.overlayFrame.clear()},this));$.subscribe(Events.PRIMARY_COLOR_SELECTED,$.proxy(function(d,a){console.log("Primary color selected: ",a);this.primaryColor=a;$.publish(Events.PRIMARY_COLOR_UPDATED,[a])},this));$.subscribe(Events.SECONDARY_COLOR_SELECTED,$.proxy(function(d,a){console.log("Secondary color selected: ",a);this.secondaryColor=a;$.publish(Events.SECONDARY_COLOR_UPDATED,[a])},this));$(window).resize($.proxy(this.startDPIUpdateTimer_,this));$.subscribe(Events.USER_SETTINGS_CHANGED,
|
||||
$.proxy(this.onUserSettingsChange_,this));$.subscribe(Events.FRAME_SIZE_CHANGED,$.proxy(this.updateDPI_,this));this.updateDPI_()};a.DrawingController.prototype.initMouseBehavior=function(){var d=$("body");this.container.mousedown($.proxy(this.onMousedown_,this));this.container.mousemove($.proxy(this.onMousemove_,this));d.mouseup($.proxy(this.onMouseup_,this));d.contextmenu(this.onCanvasContextMenu_)};a.DrawingController.prototype.startDPIUpdateTimer_=function(){this.dpiUpdateTimer&&window.clearInterval(this.dpiUpdateTimer);
|
||||
this.dpiUpdateTimer=window.setTimeout($.proxy(this.updateDPI_,this),200)};a.DrawingController.prototype.onUserSettingsChange_=function(d,a,c){a==pskl.UserSettings.SHOW_GRID&&this.updateDPI_()};a.DrawingController.prototype.onMousedown_=function(d){this.isClicked=!0;2==d.button&&(this.isRightClicked=!0,$.publish(Events.CANVAS_RIGHT_CLICKED));var a=this.getSpriteCoordinates(d);this.currentToolBehavior.applyToolAt(a.col,a.row,this.getCurrentColor_(),this.piskelController.getCurrentFrame(),this.overlayFrame,
|
||||
this.wrapEvtInfo_(d));$.publish(Events.LOCALSTORAGE_REQUEST)};a.DrawingController.prototype.onMousemove_=function(d){var a=(new Date).getTime();if(40<a-this.previousMousemoveTime){var c=this.getSpriteCoordinates(d);this.isClicked?(this.currentToolBehavior.moveToolAt(c.col,c.row,this.getCurrentColor_(),this.piskelController.getCurrentFrame(),this.overlayFrame,this.wrapEvtInfo_(d)),$.publish(Events.LOCALSTORAGE_REQUEST)):this.currentToolBehavior.moveUnactiveToolAt(c.col,c.row,this.getCurrentColor_(),
|
||||
this.piskelController.getCurrentFrame(),this.overlayFrame,this.wrapEvtInfo_(d));this.previousMousemoveTime=a}};a.DrawingController.prototype.onMouseup_=function(d){if(this.isClicked||this.isRightClicked){this.isRightClicked=this.isClicked=!1;var a=this.getSpriteCoordinates(d);this.currentToolBehavior.releaseToolAt(a.col,a.row,this.getCurrentColor_(),this.piskelController.getCurrentFrame(),this.overlayFrame,this.wrapEvtInfo_(d));$.publish(Events.TOOL_RELEASED)}};a.DrawingController.prototype.wrapEvtInfo_=
|
||||
function(d){var a={};0===d.button?a.button=Constants.LEFT_BUTTON:2==d.button&&(a.button=Constants.RIGHT_BUTTON);return a};a.DrawingController.prototype.getRelativeCoordinates=function(d,a){var c=this.container.offset();return{x:d-c.left,y:a-c.top}};a.DrawingController.prototype.getSpriteCoordinates=function(d){d=this.getRelativeCoordinates(d.clientX,d.clientY);return this.renderer.convertPixelCoordinatesIntoSpriteCoordinate(d)};a.DrawingController.prototype.getCurrentColor_=function(){return this.isRightClicked?
|
||||
this.secondaryColor:this.primaryColor};a.DrawingController.prototype.onCanvasContextMenu_=function(d){if($(d.target).closest("#drawing-canvas-container").length)return d.preventDefault(),d.stopPropagation(),d.cancelBubble=!0,!1};a.DrawingController.prototype.render=function(){this.renderLayers();this.renderFrame();this.renderOverlay()};a.DrawingController.prototype.renderFrame=function(){var d=this.piskelController.getCurrentFrame(),a=this.dpi+"-"+d.serialize();this.serializedFrame!=a&&(d.isSameSize(this.overlayFrame)||
|
||||
(this.overlayFrame=pskl.model.Frame.createEmptyFromFrame(d)),this.serializedFrame=a,this.renderer.render(d))};a.DrawingController.prototype.renderOverlay=function(){var d=this.dpi+"-"+this.overlayFrame.serialize();this.serializedOverlay!=d&&(this.serializedOverlay=d,this.overlayRenderer.render(this.overlayFrame))};a.DrawingController.prototype.renderLayers=function(){var d=this.piskelController.getLayers(),a=this.piskelController.currentFrameIndex,c=this.piskelController.currentLayerIndex,f=[this.dpi,
|
||||
a,c,d.length].join("-");if(this.serializedLayerFrame!=f){this.layersAboveRenderer.clear();this.layersBelowRenderer.clear();var e=d.slice(0,c),e=this.getFrameForLayersAt_(a,e);this.layersBelowRenderer.render(e);c+1<d.length&&(d=d.slice(c+1,d.length),a=this.getFrameForLayersAt_(a,d),this.layersAboveRenderer.render(a));this.serializedLayerFrame=f}};a.DrawingController.prototype.getFrameForLayersAt_=function(a,b){var c=b.map(function(c){return c.getFrameAt(a)});return pskl.utils.FrameUtils.merge(c)};
|
||||
a.DrawingController.prototype.calculateDPI_=function(){var a=$("#main-wrapper").height(),b=$(".left-column").outerWidth(!0),c=$(".right-column").outerWidth(!0),b=$("#main-wrapper").width()-b-c,c=this.piskelController.getCurrentFrame().getHeight(),f=this.piskelController.getCurrentFrame().getWidth();pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)&&(b-=f*Constants.GRID_STROKE_WIDTH,a-=c*Constants.GRID_STROKE_WIDTH);return pskl.PixelUtils.calculateDPI(a,b,c,f)};a.DrawingController.prototype.updateDPI_=
|
||||
function(){this.dpi=this.calculateDPI_();this.overlayRenderer.setDPI(this.dpi);this.renderer.setDPI(this.dpi);this.layersAboveRenderer.setDPI(this.dpi);this.layersBelowRenderer.setDPI(this.dpi);var a=this.piskelController.getCurrentFrame().getHeight(),b=a*this.dpi;pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)&&(b+=Constants.GRID_STROKE_WIDTH*a);a=Math.floor(($("#main-wrapper").height()-b)/2);$("#column-wrapper").css({top:a+"px",height:b+"px"})}})();(function(){var a=$.namespace("pskl.controller");a.LayersListController=function(a){this.piskelController=a};a.LayersListController.prototype.init=function(){this.layerItemTemplate_=pskl.utils.Template.get("layer-item-template");this.rootEl=document.querySelectorAll(".layers-list-container")[0];this.layersListEl=document.querySelectorAll(".layers-list")[0];this.rootEl.addEventListener("click",this.onClick_.bind(this));$.subscribe(Events.PISKEL_RESET,this.renderLayerList_.bind(this));this.renderLayerList_()};
|
||||
a.LayersListController.prototype.renderLayerList_=function(){this.layersListEl.innerHTML="";this.piskelController.getLayers().forEach(this.addLayerItem.bind(this))};a.LayersListController.prototype.addLayerItem=function(a){var b=pskl.utils.Template.replace(this.layerItemTemplate_,{layername:a.getName()}),b=pskl.utils.Template.createFromHTML(b);this.piskelController.getCurrentLayer()===a&&b.classList.add("current-layer-item");this.layersListEl.insertBefore(b,this.layersListEl.firstChild)};a.LayersListController.prototype.onClick_=
|
||||
function(a){a=a.target||a.srcElement;if("BUTTON"==a.nodeName)this.onButtonClick_(a);else"LI"==a.nodeName&&(a=a.getAttribute("data-layer-name"),this.piskelController.selectLayerByName(a))};a.LayersListController.prototype.onButtonClick_=function(a){a=a.getAttribute("data-action");"up"==a?this.piskelController.moveLayerUp():"down"==a?this.piskelController.moveLayerDown():"add"==a?this.piskelController.createLayer():"delete"==a&&this.piskelController.removeCurrentLayer()}})();(function(){var a=$.namespace("pskl.controller");a.NotificationController=function(){};a.NotificationController.prototype.init=function(){$.subscribe(Events.SHOW_NOTIFICATION,$.proxy(this.displayMessage_,this));$.subscribe(Events.HIDE_NOTIFICATION,$.proxy(this.removeMessage_,this))};a.NotificationController.prototype.displayMessage_=function(a,b){var c=document.createElement("div");c.id="user-message";c.className="user-message";c.innerHTML=b.content;c.innerHTML+="<div title='Close message' class='close'>x</div>";
|
||||
document.body.appendChild(c);$(c).find(".close").click($.proxy(this.removeMessage_,this));b.behavior&&b.behavior(c)};a.NotificationController.prototype.removeMessage_=function(a){a=$("#user-message");a.length&&a.remove()}})();(function(){var a=$.namespace("pskl.controller");a.PaletteController=function(){};a.PaletteController.prototype.init=function(){$(".palette-color[data-color=TRANSPARENT]").mouseup($.proxy(this.onPaletteColorClick_,this));$.subscribe(Events.PRIMARY_COLOR_UPDATED,$.proxy(function(a,d){this.updateColorPicker_(d,$("#color-picker"))},this));$.subscribe(Events.SECONDARY_COLOR_UPDATED,$.proxy(function(a,d){this.updateColorPicker_(d,$("#secondary-color-picker"))},this));var a=$("#color-picker");a.val(Constants.DEFAULT_PEN_COLOR);
|
||||
a.change({isPrimary:!0},$.proxy(this.onPickerChange_,this));a=$("#secondary-color-picker");a.val(Constants.TRANSPARENT_COLOR);a.change({isPrimary:!1},$.proxy(this.onPickerChange_,this));window.jscolor.install()};a.PaletteController.prototype.onPickerChange_=function(a,b){var c=$(a.target);a.data.isPrimary?$.publish(Events.PRIMARY_COLOR_SELECTED,[c.val()]):$.publish(Events.SECONDARY_COLOR_SELECTED,[c.val()])};a.PaletteController.prototype.onPaletteColorClick_=function(a){var b=$(a.target).data("color"),
|
||||
c=3==a.which;1==a.which?$.publish(Events.PRIMARY_COLOR_SELECTED,[b]):c&&$.publish(Events.SECONDARY_COLOR_SELECTED,[b])};a.PaletteController.prototype.updateColorPicker_=function(a,b){a==Constants.TRANSPARENT_COLOR?(b[0].color.fromString("#fff"),b.val(Constants.TRANSPARENT_COLOR)):b[0].color.fromString(a)}})();(function(){var a=$.namespace("pskl.controller");a.PiskelController=function(a){if(a)this.setPiskel(a);else throw"A piskel instance is mandatory for instanciating PiskelController";};a.PiskelController.prototype.setPiskel=function(a){this.piskel=a;this.currentFrameIndex=this.currentLayerIndex=0;this.layerIdCounter=1;$.publish(Events.PISKEL_RESET);$.publish(Events.FRAME_SIZE_CHANGED)};a.PiskelController.prototype.getHeight=function(){return this.piskel.getHeight()};a.PiskelController.prototype.getWidth=
|
||||
function(){return this.piskel.getWidth()};a.PiskelController.prototype.getFPS=function(){return pskl.app.animationController.getFPS()};a.PiskelController.prototype.getLayers=function(){return this.piskel.getLayers()};a.PiskelController.prototype.getCurrentLayer=function(){return this.piskel.getLayerAt(this.currentLayerIndex)};a.PiskelController.prototype.getCurrentFrame=function(){return this.getCurrentLayer().getFrameAt(this.currentFrameIndex)};a.PiskelController.prototype.getFrameAt=function(a){var b=
|
||||
this.getLayers().map(function(c){return c.getFrameAt(a)});return pskl.utils.FrameUtils.merge(b)};a.PiskelController.prototype.hasFrameAt=function(a){return!!this.getCurrentLayer().getFrameAt(a)};a.PiskelController.prototype.getFrameByIndex=a.PiskelController.prototype.getMergedFrameAt;a.PiskelController.prototype.addEmptyFrame=function(){this.getLayers().forEach(function(a){a.addFrame(this.createEmptyFrame_())}.bind(this))};a.PiskelController.prototype.createEmptyFrame_=function(){var a=this.piskel.getWidth(),
|
||||
b=this.piskel.getHeight();return new pskl.model.Frame(a,b)};a.PiskelController.prototype.removeFrameAt=function(a){this.getLayers().forEach(function(b){b.removeFrameAt(a)});this.currentFrameIndex>=a&&this.setCurrentFrameIndex(this.currentFrameIndex-1);$.publish(Events.PISKEL_RESET)};a.PiskelController.prototype.duplicateFrameAt=function(a){this.getLayers().forEach(function(b){b.duplicateFrameAt(a)})};a.PiskelController.prototype.moveFrame=function(a,b){this.getLayers().forEach(function(c){c.moveFrame(a,
|
||||
b)})};a.PiskelController.prototype.getFrameCount=function(){return this.piskel.getLayerAt(0).length()};a.PiskelController.prototype.setCurrentFrameIndex=function(a){this.currentFrameIndex=a;$.publish(Events.PISKEL_RESET)};a.PiskelController.prototype.setCurrentLayerIndex=function(a){this.currentLayerIndex=a;$.publish(Events.PISKEL_RESET)};a.PiskelController.prototype.selectLayer=function(a){a=this.getLayers().indexOf(a);-1!=a&&this.setCurrentLayerIndex(a)};a.PiskelController.prototype.selectLayerByName=
|
||||
function(a){this.hasLayerForName_(a)&&(a=this.piskel.getLayersByName(a)[0],this.selectLayer(a))};a.PiskelController.prototype.generateLayerName_=function(){for(var a="Layer "+this.layerIdCounter;this.hasLayerForName_(a);)this.layerIdCounter++,a="Layer "+this.layerIdCounter;return a};a.PiskelController.prototype.createLayer=function(a){a||(a=this.generateLayerName_());if(this.hasLayerForName_(a))throw"Layer name should be unique";a=new pskl.model.Layer(a);for(var b=0;b<this.getFrameCount();b++)a.addFrame(this.createEmptyFrame_());
|
||||
this.piskel.addLayer(a);this.setCurrentLayerIndex(this.piskel.getLayers().length-1)};a.PiskelController.prototype.hasLayerForName_=function(a){return 0<this.piskel.getLayersByName(a).length};a.PiskelController.prototype.moveLayerUp=function(){var a=this.getCurrentLayer();this.piskel.moveLayerUp(a);this.selectLayer(a)};a.PiskelController.prototype.moveLayerDown=function(){var a=this.getCurrentLayer();this.piskel.moveLayerDown(a);this.selectLayer(a)};a.PiskelController.prototype.removeCurrentLayer=
|
||||
function(){if(1<this.getLayers().length){var a=this.getCurrentLayer();this.piskel.removeLayer(a);this.setCurrentLayerIndex(0)}};a.PiskelController.prototype.serialize=function(){return pskl.utils.Serializer.serializePiskel(this.piskel)};a.PiskelController.prototype.load=function(a){this.deserialize(JSON.stringify(a))}})();(function(){var a=$.namespace("pskl.controller");a.PreviewFilmController=function(a,b,c){this.piskelController=a;this.container=b;this.dpi=this.calculateDPI_();this.redrawFlag=!0};a.PreviewFilmController.prototype.init=function(){$.subscribe(Events.TOOL_RELEASED,this.flagForRedraw_.bind(this));$.subscribe(Events.PISKEL_RESET,this.flagForRedraw_.bind(this));$.subscribe(Events.PISKEL_RESET,this.refreshDPI_.bind(this));$("#preview-list-scroller").scroll(this.updateScrollerOverflows.bind(this));this.updateScrollerOverflows()};
|
||||
a.PreviewFilmController.prototype.addFrame=function(){this.piskelController.addEmptyFrame();this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount()-1);this.updateScrollerOverflows()};a.PreviewFilmController.prototype.flagForRedraw_=function(){this.redrawFlag=!0};a.PreviewFilmController.prototype.refreshDPI_=function(){this.dpi=this.calculateDPI_()};a.PreviewFilmController.prototype.render=function(){this.redrawFlag&&(this.createPreviews_(),this.redrawFlag=!1)};a.PreviewFilmController.prototype.updateScrollerOverflows=
|
||||
function(){var a=$("#preview-list-scroller"),b=a.height(),c=a.scrollTop(),f=$("#preview-list").height(),e=$(".top-overflow").height(),g=a=!1;b<f&&(c>e&&(a=!0),f-c-b>e&&(g=!0));b=$("#preview-list-wrapper");b.toggleClass("top-overflow-visible",a);b.toggleClass("bottom-overflow-visible",g)};a.PreviewFilmController.prototype.createPreviews_=function(){this.container.html("");$(".tooltip").remove();for(var a=this.piskelController.getFrameCount(),b=0;b<a;b++)this.container.append(this.createPreviewTile_(b));
|
||||
b=document.createElement("div");b.id="add-frame-action";b.className="add-frame-action";b.innerHTML="<p class='label'>Add new frame</p>";this.container.append(b);$(b).click(this.addFrame.bind(this));1<a&&this.initDragndropBehavior_();this.updateScrollerOverflows()};a.PreviewFilmController.prototype.initDragndropBehavior_=function(){$("#preview-list").sortable({placeholder:"preview-tile-drop-proxy",update:$.proxy(this.onUpdate_,this),items:".preview-tile"});$("#preview-list").disableSelection()};a.PreviewFilmController.prototype.onUpdate_=
|
||||
function(a,b){var c=parseInt(b.item.data("tile-number"),10),f=$(".preview-tile").index(b.item);this.piskelController.moveFrame(c,f);this.piskelController.setCurrentFrameIndex(f);$.publish(Events.LOCALSTORAGE_REQUEST)};a.PreviewFilmController.prototype.createPreviewTile_=function(a){var b=this.piskelController.getCurrentLayer().getFrameAt(a),c=document.createElement("li"),f="preview-tile";c.setAttribute("data-tile-number",a);this.piskelController.getCurrentFrame()==b&&(f+=" selected");c.className=
|
||||
f;f=document.createElement("div");f.className="canvas-container";var e=document.createElement("div");e.className="canvas-background";f.appendChild(e);c.addEventListener("click",this.onPreviewClick_.bind(this,a));e=document.createElement("button");e.setAttribute("rel","tooltip");e.setAttribute("data-placement","right");e.setAttribute("title","Duplicate this frame");e.className="tile-overlay duplicate-frame-action";c.appendChild(e);e.addEventListener("click",this.onAddButtonClick_.bind(this,a));e={dpi:this.dpi};
|
||||
(new pskl.rendering.FrameRenderer($(f),e,["tile-view"])).render(b);c.appendChild(f);if(0<a||1<this.piskelController.getFrameCount())b=document.createElement("button"),b.setAttribute("rel","tooltip"),b.setAttribute("data-placement","right"),b.setAttribute("title","Delete this frame"),b.className="tile-overlay delete-frame-action",b.addEventListener("click",this.onDeleteButtonClick_.bind(this,a)),c.appendChild(b),b=document.createElement("div"),b.className="tile-overlay dnd-action",c.appendChild(b);
|
||||
b=document.createElement("div");b.className="tile-overlay tile-count";b.innerHTML=a;c.appendChild(b);return c};a.PreviewFilmController.prototype.onPreviewClick_=function(a,b){b.target.classList.contains("tile-overlay")||this.piskelController.setCurrentFrameIndex(a)};a.PreviewFilmController.prototype.onDeleteButtonClick_=function(a,b){this.piskelController.removeFrameAt(a);$.publish(Events.LOCALSTORAGE_REQUEST);this.updateScrollerOverflows()};a.PreviewFilmController.prototype.onAddButtonClick_=function(a,
|
||||
b){this.piskelController.duplicateFrameAt(a);$.publish(Events.LOCALSTORAGE_REQUEST);this.piskelController.setCurrentFrameIndex(a+1);this.updateScrollerOverflows()};a.PreviewFilmController.prototype.calculateDPI_=function(){var a=this.piskelController.getCurrentFrame(),b=a.getHeight(),a=a.getWidth(),c=Math.max(a,b);return pskl.PixelUtils.calculateDPI(Constants.PREVIEW_FILM_SIZE*b/c,Constants.PREVIEW_FILM_SIZE*a/c,b,a)||1}})();(function(){var a=$.namespace("pskl.controller");a.ToolController=function(){this.toolInstances={simplePen:new pskl.drawingtools.SimplePen,verticalMirrorPen:new pskl.drawingtools.VerticalMirrorPen,eraser:new pskl.drawingtools.Eraser,paintBucket:new pskl.drawingtools.PaintBucket,stroke:new pskl.drawingtools.Stroke,rectangle:new pskl.drawingtools.Rectangle,circle:new pskl.drawingtools.Circle,move:new pskl.drawingtools.Move,rectangleSelect:new pskl.drawingtools.RectangleSelect,shapeSelect:new pskl.drawingtools.ShapeSelect,
|
||||
colorPicker:new pskl.drawingtools.ColorPicker};this.previousSelectedTool=this.currentSelectedTool=this.toolInstances.simplePen};a.ToolController.prototype.init=function(){this.createToolMarkup_();this.selectTool_(this.toolInstances.simplePen);$("#tool-section").click($.proxy(this.onToolIconClicked_,this))};a.ToolController.prototype.activateToolOnStage_=function(a){var b=$("body"),c=b.data("selected-tool-class");c&&b.removeClass(c);b.addClass(a.toolId);b.data("selected-tool-class",a.toolId)};a.ToolController.prototype.selectTool_=
|
||||
function(a){console.log("Selecting Tool:",this.currentSelectedTool);this.currentSelectedTool=a;this.activateToolOnStage_(this.currentSelectedTool);$.publish(Events.TOOL_SELECTED,[a])};a.ToolController.prototype.onToolIconClicked_=function(a){a=$(a.target).closest(".tool-icon");if(a.length){var b=a.data().toolId;if(b=this.getToolById_(b))this.selectTool_(b),$("#tool-section .tool-icon.selected").removeClass("selected"),a.addClass("selected")}};a.ToolController.prototype.getToolById_=function(a){for(var b in this.toolInstances)if(this.toolInstances[b].toolId==
|
||||
a)return this.toolInstances[b];return null};a.ToolController.prototype.createToolMarkup_=function(){var a,b="",c,f;for(f in this.toolInstances)a=this.toolInstances[f],c=a.toolId,this.currentSelectedTool==a&&(c+=" selected"),b+='<li rel="tooltip" data-placement="right" class="tool-icon '+c+'" data-tool-id="'+a.toolId+'" title="'+a.helpText+'"></li>';$("#tools-container").html(b)}})();(function(){var a=$.namespace("pskl.controller.settings");a.ApplicationSettingsController=function(){};a.ApplicationSettingsController.prototype.init=function(){var a=pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);$("#background-picker-wrapper").find(".background-picker[data-background-class="+a+"]").addClass("selected");a=pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID);$("#show-grid").prop("checked",a);$("#show-grid").change($.proxy(function(a){a=$("#show-grid").prop("checked");pskl.UserSettings.set(pskl.UserSettings.SHOW_GRID,
|
||||
a)},this));$("#background-picker-wrapper").click(function(a){a=$(a.target).closest(".background-picker");if(a.length){var d=a.data("background-class");pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND,d);$(".background-picker").removeClass("selected");a.addClass("selected")}})}})();(function(){var a=$.namespace("pskl.controller.settings");a.GifExportController=function(a){this.piskelController=a};a.GifExportController.RESOLUTIONS=[{dpi:1},{dpi:5},{dpi:10,"default":!0},{dpi:20}];a.GifExportController.prototype.init=function(){this.radioTemplate_=pskl.utils.Template.get("gif-export-radio-template");this.previewContainerEl=document.querySelectorAll(".gif-export-preview")[0];this.radioGroupEl=document.querySelectorAll(".gif-export-radio-group")[0];this.uploadForm=$("[name=gif-export-upload-form]");
|
||||
this.uploadForm.submit(this.onUploadFormSubmit_.bind(this));this.createRadioElements_()};a.GifExportController.prototype.onUploadFormSubmit_=function(a){a.originalEvent.preventDefault();a=this.getSelectedDpi_();var b=this.piskelController.getFPS();this.renderAsImageDataAnimatedGIF(a,b,this.onGifRenderingCompleted_.bind(this))};a.GifExportController.prototype.onGifRenderingCompleted_=function(a){this.updatePreview_(a);this.previewContainerEl.classList.add("preview-upload-ongoing");pskl.app.imageUploadService.upload(a,
|
||||
this.onImageUploadCompleted_.bind(this))};a.GifExportController.prototype.onImageUploadCompleted_=function(a){this.updatePreview_(a);this.previewContainerEl.classList.remove("preview-upload-ongoing")};a.GifExportController.prototype.updatePreview_=function(a){this.previewContainerEl.innerHTML="<div><img style='max-width:240px;' src='"+a+"'/></div>"};a.GifExportController.prototype.getSelectedDpi_=function(){var a=this.uploadForm.get(0).querySelectorAll("[name=gif-dpi]"),a=Array.prototype.slice.call(a,
|
||||
0).filter(function(a){return!!a.checked});if(1==a.length)return a[0].value;throw"Unexpected error when retrieving selected dpi";};a.GifExportController.prototype.createRadioElements_=function(){for(var d=a.GifExportController.RESOLUTIONS,b=0;b<d.length;b++){var c=this.createRadioForResolution_(d[b]);this.radioGroupEl.appendChild(c)}};a.GifExportController.prototype.createRadioForResolution_=function(a){var b=a.dpi,c=b*this.piskelController.getWidth()+"x"+b*this.piskelController.getHeight(),b=pskl.utils.Template.replace(this.radioTemplate_,
|
||||
{value:b,label:c}),b=pskl.utils.Template.createFromHTML(b);a["default"]&&b.getElementsByTagName("input")[0].setAttribute("checked","checked");return b};a.GifExportController.prototype.blobToBase64_=function(a,b){var c=new FileReader;c.onload=function(){b(c.result)};c.readAsDataURL(a)};a.GifExportController.prototype.renderAsImageDataAnimatedGIF=function(a,b,c){for(var f=new window.GIF({workers:2,quality:10,width:this.piskelController.getWidth()*a,height:this.piskelController.getHeight()*a}),e=0;e<
|
||||
this.piskelController.getFrameCount();e++){var g=this.piskelController.getFrameAt(e),g=new pskl.rendering.CanvasRenderer(g,a);f.addFrame(g.render(),{delay:1E3/b})}f.on("finished",function(a){this.blobToBase64_(a,c)}.bind(this));f.render()}})();(function(){var a=$.namespace("pskl.controller.settings");a.ImportController=function(a){this.piskelController=a;this.importedImage_=null};a.ImportController.prototype.init=function(){this.importForm=$("[name=import-form]");this.hiddenFileInput=$("[name=file-upload-input]");this.fileInputButton=$(".file-input-button");this.fileInputStatus=$(".file-input-status");this.fileInputStatus.html("No file selected ...");this.importPreview=$(".import-section-preview");this.resizeWidth=$("[name=resize-width]");
|
||||
this.resizeHeight=$("[name=resize-height]");this.smoothResize=$("[name=smooth-resize-checkbox]");this.submitButton=$("[name=import-submit]");this.importForm.submit(this.onImportFormSubmit_.bind(this));this.hiddenFileInput.change(this.onFileUploadChange_.bind(this));this.fileInputButton.click(this.onFileInputClick_.bind(this));this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this,"width"));this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this,"height"))};a.ImportController.prototype.reset_=
|
||||
function(){this.importForm.get(0).reset();this.fileInputStatus.html("No file selected ...");$.publish(Events.CLOSE_SETTINGS_DRAWER)};a.ImportController.prototype.onResizeInputKeyUp_=function(a,b){this.importedImage_&&this.synchronizeResizeFields_(b.target.value,a)};a.ImportController.prototype.synchronizeResizeFields_=function(a,b){a=parseInt(a,10);isNaN(a)&&(a=0);var c=this.importedImage_.height,f=this.importedImage_.width;"width"===b?this.resizeHeight.val(Math.round(a*c/f)):this.resizeWidth.val(Math.round(a*
|
||||
f/c))};a.ImportController.prototype.onImportFormSubmit_=function(a){a.originalEvent.preventDefault();this.importImageToPiskel_()};a.ImportController.prototype.onFileUploadChange_=function(a){this.importFromFile_()};a.ImportController.prototype.onFileInputClick_=function(a){this.hiddenFileInput.click()};a.ImportController.prototype.importFromFile_=function(){var a=this.hiddenFileInput.get(0).files;if(1==a.length)if(a=a[0],this.isImage_(a))this.readImageFile_(a),this.enableDisabledSections_();else throw this.reset_(),
|
||||
"File is not an image : "+a.type;};a.ImportController.prototype.enableDisabledSections_=function(){this.resizeWidth.removeAttr("disabled");this.resizeHeight.removeAttr("disabled");this.smoothResize.removeAttr("disabled");this.submitButton.removeAttr("disabled");this.fileInputButton.removeClass("button-primary");this.fileInputButton.blur();$(".import-section-disabled").removeClass("import-section-disabled")};a.ImportController.prototype.readImageFile_=function(a){pskl.utils.FileUtils.readFile(a,this.processImageSource_.bind(this))};
|
||||
a.ImportController.prototype.processImageSource_=function(a){this.importedImage_=new Image;this.importedImage_.onload=this.onImageLoaded_.bind(this);this.importedImage_.src=a};a.ImportController.prototype.onImageLoaded_=function(a){a=this.importedImage_.width;var b=this.importedImage_.height,c=this.hiddenFileInput.val(),c=this.extractFileNameFromPath_(c);this.fileInputStatus.html(c);this.resizeWidth.val(a);this.resizeHeight.val(b);this.importPreview.width("auto");this.importPreview.append(this.createImagePreview_())};
|
||||
a.ImportController.prototype.createImagePreview_=function(){var a=document.createElement("IMG");a.src=this.importedImage_.src;a.setAttribute("height",60);return a};a.ImportController.prototype.extractFileNameFromPath_=function(a){var b=[],b=-1!==a.indexOf("/")?a.split("/"):-1!==a.indexOf("\\")?a.split("\\"):[a];return b[b.length-1]};a.ImportController.prototype.importImageToPiskel_=function(){if(this.importedImage_&&window.confirm("You are about to create a new Piskel, unsaved changes will be lost.")){var a=
|
||||
this.resizeWidth.val(),b=this.resizeHeight.val(),c=!!this.smoothResize.prop("checked"),a=pskl.utils.ImageResizer.resize(this.importedImage_,a,b,c),a=pskl.utils.FrameUtils.createFromImage(a),a=pskl.utils.Serializer.createPiskel([a]);pskl.app.piskelController.setPiskel(a);pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);this.reset_()}};a.ImportController.prototype.isImage_=function(a){return 0===a.type.indexOf("image")}})();(function(){var a=$.namespace("pskl.controller.settings"),d={user:{template:"templates/settings/application.html",controller:a.ApplicationSettingsController},gif:{template:"templates/settings/export-gif.html",controller:a.GifExportController},"import":{template:"templates/settings/import.html",controller:a.ImportController}};a.SettingsController=function(a){this.piskelController=a;this.drawerContainer=document.getElementById("drawer-container");this.settingsContainer=$("[data-pskl-controller=settings]");
|
||||
this.expanded=!1;this.currentSetting=null};a.SettingsController.prototype.init=function(){$("[data-setting]").click(function(a){a=a.originalEvent.currentTarget.getAttribute("data-setting");this.currentSetting!=a?this.loadSetting(a):this.closeDrawer()}.bind(this));$("body").click(function(a){a=$.contains(this.settingsContainer.get(0),a.target);this.expanded&&!a&&this.closeDrawer()}.bind(this));$.subscribe(Events.CLOSE_SETTINGS_DRAWER,this.closeDrawer.bind(this))};a.SettingsController.prototype.loadSetting=
|
||||
function(a){this.drawerContainer.innerHTML=pskl.utils.Template.get(d[a].template);(new d[a].controller(this.piskelController)).init();this.settingsContainer.addClass("expanded");$(".has-expanded-drawer").removeClass("has-expanded-drawer");$("[data-setting="+a+"]").addClass("has-expanded-drawer");this.expanded=!0;this.currentSetting=a};a.SettingsController.prototype.closeDrawer=function(){this.settingsContainer.removeClass("expanded");$(".has-expanded-drawer").removeClass("has-expanded-drawer");this.expanded=
|
||||
!1;this.currentSetting=null}})();(function(){var a=$.namespace("pskl.drawingtools");a.BaseTool=function(){};a.BaseTool.prototype.applyToolAt=function(a,b,c,f,e){};a.BaseTool.prototype.moveToolAt=function(a,b,c,f,e){};a.BaseTool.prototype.moveUnactiveToolAt=function(a,b,c,f,e){e.containsPixel(a,b)&&(isNaN(this.highlightedPixelCol)||isNaN(this.highlightedPixelRow)||this.highlightedPixelRow==b&&this.highlightedPixelCol==a||e.clear(),e.setPixel(a,b,Constants.TOOL_TARGET_HIGHLIGHT_COLOR),this.highlightedPixelCol=a,this.highlightedPixelRow=
|
||||
b)};a.BaseTool.prototype.releaseToolAt=function(a,b,c,f,e){};a.BaseTool.prototype.getLinePixels_=function(a,b,c,f){for(var e=[],g=Math.abs(b-a),h=Math.abs(f-c),k=a<b?1:-1,l=c<f?1:-1,m=g-h;;){e.push({col:a,row:c});if(a==b&&c==f)break;var n=2*m;n>-h&&(m-=h,a+=k);n<g&&(m+=g,c+=l)}return e}})();(function(){var a=$.namespace("pskl.drawingtools");a.Circle=function(){this.toolId="tool-circle";this.helpText="Circle tool";this.startRow=this.startCol=null};pskl.utils.inherit(a.Circle,a.BaseTool);a.Circle.prototype.applyToolAt=function(a,b,c,f,e){this.startCol=a;this.startRow=b;e.setPixel(a,b,c)};a.Circle.prototype.moveToolAt=function(a,b,c,f,e){e.clear();c==Constants.TRANSPARENT_COLOR&&(c=Constants.SELECTION_TRANSPARENT_COLOR);this.drawCircle_(a,b,c,e)};a.Circle.prototype.releaseToolAt=function(a,
|
||||
b,c,f,e){e.clear();f.containsPixel(a,b)&&this.drawCircle_(a,b,c,f)};a.Circle.prototype.drawCircle_=function(a,b,c,f){a=this.getCirclePixels_(this.startCol,this.startRow,a,b);for(b=0;b<a.length;b++)f.setPixel(a[b].col,a[b].row,c)};a.Circle.prototype.getCirclePixels_=function(a,b,c,f){a=pskl.PixelUtils.getOrderedRectangleCoordinates(a,b,c,f);b=(a.x0+a.x1)/2;c=(a.y0+a.y1)/2;f=a.x1-b;var e=a.y1-c,g=[],h,k,l;for(h=a.x0;h<a.x1;h++)l=Math.acos((h-b)/f),k=Math.round(e*Math.sin(l)+c),g.push({col:h,row:k}),
|
||||
g.push({col:2*b-h,row:2*c-k});for(k=a.y0;k<a.y1;k++)l=Math.asin((k-c)/e),h=Math.round(f*Math.cos(l)+b),g.push({col:h,row:k}),g.push({col:2*b-h,row:2*c-k});return g}})();(function(){var a=$.namespace("pskl.drawingtools");a.ColorPicker=function(){this.toolId="tool-colorpicker";this.helpText="Color picker"};pskl.utils.inherit(a.ColorPicker,a.BaseTool);a.ColorPicker.prototype.applyToolAt=function(a,b,c,f,e,g){f.containsPixel(a,b)&&(a=f.getPixel(a,b),g.button==Constants.LEFT_BUTTON?$.publish(Events.PRIMARY_COLOR_SELECTED,[a]):g.button==Constants.RIGHT_BUTTON&&$.publish(Events.SECONDARY_COLOR_SELECTED,[a]))}})();(function(){var a=$.namespace("pskl.drawingtools");a.Eraser=function(){this.toolId="tool-eraser";this.helpText="Eraser tool"};pskl.utils.inherit(a.Eraser,a.SimplePen);a.Eraser.prototype.applyToolAt=function(a,b,c,f,e){this.superclass.applyToolAt.call(this,a,b,Constants.TRANSPARENT_COLOR,f,e)}})();(function(){var a=$.namespace("pskl.drawingtools");a.Move=function(){this.toolId="tool-move";this.helpText="Move tool";this.startRow=this.startCol=null};pskl.utils.inherit(a.Move,a.BaseTool);a.Move.prototype.applyToolAt=function(a,b,c,f,e){this.startCol=a;this.startRow=b;this.frameClone=f.clone()};a.Move.prototype.moveToolAt=function(a,b,c,f,e){this.shiftFrame(a-this.startCol,b-this.startRow,f,this.frameClone)};a.Move.prototype.shiftFrame=function(a,b,c,f){for(var e,g=0;g<c.getWidth();g++)for(var h=
|
||||
0;h<c.getHeight();h++)e=f.containsPixel(g-a,h-b)?f.getPixel(g-a,h-b):Constants.TRANSPARENT_COLOR,c.setPixel(g,h,e)};a.Move.prototype.releaseToolAt=function(a,b,c,f,e){this.moveToolAt(a,b,c,f,e)}})();(function(){var a=$.namespace("pskl.drawingtools");a.PaintBucket=function(){this.toolId="tool-paint-bucket";this.helpText="Paint bucket tool"};pskl.utils.inherit(a.PaintBucket,a.BaseTool);a.PaintBucket.prototype.applyToolAt=function(a,b,c,f,e){pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(f,a,b,c)}})();(function(){var a=$.namespace("pskl.drawingtools");a.Rectangle=function(){this.toolId="tool-rectangle";this.helpText="Rectangle tool";this.startRow=this.startCol=null};pskl.utils.inherit(a.Rectangle,a.BaseTool);a.Rectangle.prototype.applyToolAt=function(a,b,c,f,e){this.startCol=a;this.startRow=b;e.setPixel(a,b,c)};a.Rectangle.prototype.moveToolAt=function(a,b,c,f,e){e.clear();c==Constants.TRANSPARENT_COLOR&&(c=Constants.SELECTION_TRANSPARENT_COLOR);this.drawRectangle_(a,b,c,e)};a.Rectangle.prototype.releaseToolAt=
|
||||
function(a,b,c,f,e){e.clear();f.containsPixel(a,b)&&this.drawRectangle_(a,b,c,f)};a.Rectangle.prototype.drawRectangle_=function(a,b,c,f){a=pskl.PixelUtils.getBoundRectanglePixels(this.startCol,this.startRow,a,b);for(b=0;b<a.length;b++)f.setPixel(a[b].col,a[b].row,c)}})();(function(){var a=$.namespace("pskl.drawingtools");a.SimplePen=function(){this.toolId="tool-pen";this.helpText="Pen tool";this.previousRow=this.previousCol=null};pskl.utils.inherit(a.SimplePen,a.BaseTool);a.SimplePen.prototype.applyToolAt=function(a,b,c,f,e){f.containsPixel(a,b)&&f.setPixel(a,b,c);this.previousCol=a;this.previousRow=b};a.SimplePen.prototype.moveToolAt=function(a,b,c,f,e){if(1<Math.abs(a-this.previousCol)||1<Math.abs(b-this.previousRow))for(var g=this.getLinePixels_(a,this.previousCol,
|
||||
b,this.previousRow),h=0,k=g.length;h<k;h++){var l=g[h];this.applyToolAt(l.col,l.row,c,f,e)}else this.applyToolAt(a,b,c,f,e);this.previousCol=a;this.previousRow=b}})();(function(){var a=$.namespace("pskl.drawingtools");a.Stroke=function(){this.toolId="tool-stroke";this.helpText="Stroke tool";this.startRow=this.startCol=null};pskl.utils.inherit(a.Stroke,a.BaseTool);a.Stroke.prototype.applyToolAt=function(a,b,c,f,e){this.startCol=a;this.startRow=b;e.setPixel(a,b,c)};a.Stroke.prototype.moveToolAt=function(a,b,c,f,e){e.clear();a=this.getLinePixels_(this.startCol,a,this.startRow,b);for(b=0;b<a.length;b++)c==Constants.TRANSPARENT_COLOR&&(c=Constants.SELECTION_TRANSPARENT_COLOR),
|
||||
e.setPixel(a[b].col,a[b].row,c)};a.Stroke.prototype.releaseToolAt=function(a,b,c,f,e){if(f.containsPixel(a,b))for(a=this.getLinePixels_(this.startCol,a,this.startRow,b),b=0;b<a.length;b++)f.setPixel(a[b].col,a[b].row,c);e.clear()}})();(function(){var a=$.namespace("pskl.drawingtools");a.VerticalMirrorPen=function(){this.toolId="tool-vertical-mirror-pen";this.helpText="vertical mirror pen tool";this.mirroredPreviousRow=this.mirroredPreviousCol=this.swap=null};pskl.utils.inherit(a.VerticalMirrorPen,a.SimplePen);a.VerticalMirrorPen.prototype.setMirrorContext=function(){this.swap=this.previousCol;this.previousCol=this.mirroredPreviousCol};a.VerticalMirrorPen.prototype.unsetMirrorContext=function(){this.mirroredPreviousCol=this.previousCol;
|
||||
this.previousCol=this.swap};a.VerticalMirrorPen.prototype.applyToolAt=function(a,b,c,f,e){this.superclass.applyToolAt.call(this,a,b,c,f,e);this.mirroredPreviousCol=a=this.getSymmetricCol_(a,f);this.setMirrorContext();this.superclass.applyToolAt.call(this,a,b,c,f,e);this.unsetMirrorContext()};a.VerticalMirrorPen.prototype.getSymmetricCol_=function(a,b){return b.getWidth()-a-1}})();(function(){var a=$.namespace("pskl.drawingtools");a.BaseSelect=function(){this.secondaryToolId="tool-move";this.BodyRoot=$("body");this.startRow=this.startCol=null};pskl.utils.inherit(a.BaseSelect,a.BaseTool);a.BaseSelect.prototype.applyToolAt=function(a,b,c,f,e){this.startCol=a;this.startRow=b;this.lastCol=a;this.lastRow=b;e.getPixel(a,b)!=Constants.SELECTION_TRANSPARENT_COLOR?(this.mode="select",this.onSelectStart_(a,b,c,f,e)):(this.mode="moveSelection",this.onSelectionDragStart_(a,b,c,f,e))};
|
||||
a.BaseSelect.prototype.moveToolAt=function(a,b,c,f,e){if("select"==this.mode)this.onSelect_(a,b,c,f,e);else if("moveSelection"==this.mode)this.onSelectionDrag_(a,b,c,f,e)};a.BaseSelect.prototype.releaseToolAt=function(a,b,c,f,e){if("select"==this.mode)this.onSelectEnd_(a,b,c,f,e);else if("moveSelection"==this.mode)this.onSelectionDragEnd_(a,b,c,f,e)};a.BaseSelect.prototype.moveUnactiveToolAt=function(a,b,c,f,e){e.getPixel(a,b)!=Constants.SELECTION_TRANSPARENT_COLOR?(this.BodyRoot.addClass(this.toolId),
|
||||
this.BodyRoot.removeClass(this.secondaryToolId)):(this.BodyRoot.addClass(this.secondaryToolId),this.BodyRoot.removeClass(this.toolId))};a.BaseSelect.prototype.drawSelectionOnOverlay_=function(a,b){for(var c=a.pixels,f=0,e=c.length;f<e;f++)b.setPixel(c[f].col,c[f].row,Constants.SELECTION_TRANSPARENT_COLOR)};a.BaseSelect.prototype.shiftOverlayFrame_=function(a,b,c,f){for(var e,g=0;g<c.getWidth();g++)for(var h=0;h<c.getHeight();h++)e=f.containsPixel(g-a,h-b)?f.getPixel(g-a,h-b):Constants.TRANSPARENT_COLOR,
|
||||
c.setPixel(g,h,e)};a.BaseSelect.prototype.onSelectStart_=function(a,b,c,f,e){};a.BaseSelect.prototype.onSelect_=function(a,b,c,f,e){};a.BaseSelect.prototype.onSelectEnd_=function(a,b,c,f,e){};a.BaseSelect.prototype.onSelectionDragStart_=function(a,b,c,f,e){this.overlayFrameReference=e.clone()};a.BaseSelect.prototype.onSelectionDrag_=function(a,b,c,f,e){c=a-this.lastCol;f=b-this.lastRow;this.shiftOverlayFrame_(a-this.startCol,b-this.startRow,e,this.overlayFrameReference);$.publish(Events.SELECTION_MOVE_REQUEST,
|
||||
[c,f]);this.lastCol=a;this.lastRow=b};a.BaseSelect.prototype.onSelectionDragEnd_=function(a,b,c,f,e){this.onSelectionDrag_(a,b,c,f,e)}})();(function(){var a=$.namespace("pskl.drawingtools");a.RectangleSelect=function(){this.toolId="tool-rectangle-select";this.helpText="Rectangle selection tool";a.BaseSelect.call(this)};pskl.utils.inherit(a.RectangleSelect,a.BaseSelect);a.RectangleSelect.prototype.onSelectStart_=function(a,b,c,f,e){e.setPixel(a,b,c)};a.RectangleSelect.prototype.onSelect_=function(a,b,c,f,e){e.clear();this.startCol==a&&this.startRow==b?$.publish(Events.SELECTION_DISMISSED):(a=new pskl.selection.RectangularSelection(this.startCol,
|
||||
this.startRow,a,b),$.publish(Events.SELECTION_CREATED,[a]),this.drawSelectionOnOverlay_(a,e))};a.RectangleSelect.prototype.onSelectEnd_=function(a,b,c,f,e){this.onSelect_(a,b,c,f,e)}})();(function(){var a=$.namespace("pskl.drawingtools");a.ShapeSelect=function(){this.toolId="tool-shape-select";this.helpText="Shape selection tool";a.BaseSelect.call(this)};pskl.utils.inherit(a.ShapeSelect,a.BaseSelect);a.ShapeSelect.prototype.onSelectStart_=function(a,b,c,f,e){$.publish(Events.SELECTION_DISMISSED);e.clear();a=pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(f,a,b);a=new pskl.selection.ShapeSelection(a);$.publish(Events.SELECTION_CREATED,[a]);this.drawSelectionOnOverlay_(a,e)}})();(function(){window.iframeloader={onLoad:function(a){a=a.target||a.srcElement;var d=a.getAttribute("data-iframe-loader");"display"===d?(d=document.createElement("div"),d.innerHTML=a.contentWindow.document.body.innerHTML,1==d.children.length&&(d=d.children[0]),a.parentNode.replaceChild(d,a)):"store"===d?(d=document.createElement("script"),d.setAttribute("type","text/html"),d.setAttribute("id",a.getAttribute("src")),d.innerHTML=a.contentWindow.document.body.innerHTML,a.parentNode.removeChild(a),document.body.appendChild(d)):
|
||||
console.error("iframeLoader invalid type : "+d)}}})();(function(a,d){function b(b,d){var e,f;e=b.nodeName.toLowerCase();if("area"===e){e=b.parentNode;f=e.name;if(!b.href||!f||"map"!==e.nodeName.toLowerCase())return!1;e=a("img[usemap=#"+f+"]")[0];return!!e&&c(e)}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"===e?b.href||d:d)&&c(b)}function c(c){return a.expr.filters.visible(c)&&!a(c).parents().addBack().filter(function(){return"hidden"===a.css(this,"visibility")}).length}var f=0,e=/^ui-id-\d+$/;a.ui=a.ui||{};a.extend(a.ui,{version:"1.10.3",
|
||||
keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}});a.fn.extend({focus:function(c){return function(b,d){return"number"===typeof b?this.each(function(){var c=this;setTimeout(function(){a(c).focus();d&&d.call(c)},b)}):c.apply(this,arguments)}}(a.fn.focus),scrollParent:function(){var c;c=
|
||||
a.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.css(this,"position"))&&/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0);return/fixed/.test(this.css("position"))||!c.length?a(document):
|
||||
c},zIndex:function(c){if(c!==d)return this.css("zIndex",c);if(this.length){c=a(this[0]);for(var b;c.length&&c[0]!==document;){b=c.css("position");if("absolute"===b||"relative"===b||"fixed"===b)if(b=parseInt(c.css("zIndex"),10),!isNaN(b)&&0!==b)return b;c=c.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++f)})},removeUniqueId:function(){return this.each(function(){e.test(this.id)&&a(this).removeAttr("id")})}});a.extend(a.expr[":"],{data:a.expr.createPseudo?
|
||||
a.expr.createPseudo(function(c){return function(b){return!!a.data(b,c)}}):function(c,b,d){return!!a.data(c,d[3])},focusable:function(c){return b(c,!isNaN(a.attr(c,"tabindex")))},tabbable:function(c){var d=a.attr(c,"tabindex"),e=isNaN(d);return(e||0<=d)&&b(c,!e)}});a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,b){function e(c,b,d,g){a.each(f,function(){b-=parseFloat(a.css(c,"padding"+this))||0;d&&(b-=parseFloat(a.css(c,"border"+this+"Width"))||0);g&&(b-=parseFloat(a.css(c,"margin"+
|
||||
this))||0)});return b}var f="Width"===b?["Left","Right"]:["Top","Bottom"],m=b.toLowerCase(),n={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+b]=function(c){return c===d?n["inner"+b].call(this):this.each(function(){a(this).css(m,e(this,c)+"px")})};a.fn["outer"+b]=function(c,d){return"number"!==typeof c?n["outer"+b].call(this,c):this.each(function(){a(this).css(m,e(this,c,!0,d)+"px")})}});a.fn.addBack||(a.fn.addBack=function(a){return this.add(null==
|
||||
a?this.prevObject:this.prevObject.filter(a))});a("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(a.fn.removeData=function(c){return function(b){return arguments.length?c.call(this,a.camelCase(b)):c.call(this)}}(a.fn.removeData));a.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());a.support.selectstart="onselectstart"in document.createElement("div");a.fn.extend({disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",
|
||||
function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.extend(a.ui,{plugin:{add:function(c,b,d){var e;c=a.ui[c].prototype;for(e in d)c.plugins[e]=c.plugins[e]||[],c.plugins[e].push([b,d[e]])},call:function(a,c,b){var d=a.plugins[c];if(d&&a.element[0].parentNode&&11!==a.element[0].parentNode.nodeType)for(c=0;c<d.length;c++)a.options[d[c][0]]&&d[c][1].apply(a.element,b)}},hasScroll:function(c,b){if("hidden"===a(c).css("overflow"))return!1;var d=
|
||||
b&&"left"===b?"scrollLeft":"scrollTop",e=!1;if(0<c[d])return!0;c[d]=1;e=0<c[d];c[d]=0;return e}})})(jQuery);
|
||||
(function(a,d){var b=0,c=Array.prototype.slice,f=a.cleanData;a.cleanData=function(c){for(var b=0,d;null!=(d=c[b]);b++)try{a(d).triggerHandler("remove")}catch(k){}f(c)};a.widget=function(c,b,d){var f,l,m,n,q={},p=c.split(".")[0];c=c.split(".")[1];f=p+"-"+c;d||(d=b,b=a.Widget);a.expr[":"][f.toLowerCase()]=function(c){return!!a.data(c,f)};a[p]=a[p]||{};l=a[p][c];m=a[p][c]=function(a,c){if(!this._createWidget)return new m(a,c);arguments.length&&this._createWidget(a,c)};a.extend(m,l,{version:d.version,
|
||||
_proto:a.extend({},d),_childConstructors:[]});n=new b;n.options=a.widget.extend({},n.options);a.each(d,function(c,d){a.isFunction(d)?q[c]=function(){var a=function(){return b.prototype[c].apply(this,arguments)},e=function(a){return b.prototype[c].apply(this,a)};return function(){var c=this._super,b=this._superApply,f;this._super=a;this._superApply=e;f=d.apply(this,arguments);this._super=c;this._superApply=b;return f}}():q[c]=d});m.prototype=a.widget.extend(n,{widgetEventPrefix:l?n.widgetEventPrefix:
|
||||
c},q,{constructor:m,namespace:p,widgetName:c,widgetFullName:f});l?(a.each(l._childConstructors,function(c,b){var d=b.prototype;a.widget(d.namespace+"."+d.widgetName,m,b._proto)}),delete l._childConstructors):b._childConstructors.push(m);a.widget.bridge(c,m)};a.widget.extend=function(b){for(var f=c.call(arguments,1),h=0,k=f.length,l,m;h<k;h++)for(l in f[h])m=f[h][l],f[h].hasOwnProperty(l)&&m!==d&&(a.isPlainObject(m)?b[l]=a.isPlainObject(b[l])?a.widget.extend({},b[l],m):a.widget.extend({},m):b[l]=m);
|
||||
return b};a.widget.bridge=function(b,f){var h=f.prototype.widgetFullName||b;a.fn[b]=function(k){var l="string"===typeof k,m=c.call(arguments,1),n=this;k=!l&&m.length?a.widget.extend.apply(null,[k].concat(m)):k;l?this.each(function(){var c,f=a.data(this,h);if(!f)return a.error("cannot call methods on "+b+" prior to initialization; attempted to call method '"+k+"'");if(!a.isFunction(f[k])||"_"===k.charAt(0))return a.error("no such method '"+k+"' for "+b+" widget instance");c=f[k].apply(f,m);if(c!==
|
||||
f&&c!==d)return n=c&&c.jquery?n.pushStack(c.get()):c,!1}):this.each(function(){var c=a.data(this,h);c?c.option(k||{})._init():a.data(this,h,new f(k,this))});return n}};a.Widget=function(){};a.Widget._childConstructors=[];a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(c,d){d=a(d||this.defaultElement||this)[0];this.element=a(d);this.uuid=b++;this.eventNamespace="."+this.widgetName+this.uuid;this.options=a.widget.extend({},
|
||||
this.options,this._getCreateOptions(),c);this.bindings=a();this.hoverable=a();this.focusable=a();d!==this&&(a.data(d,this.widgetFullName,this),this._on(!0,this.element,{remove:function(a){a.target===d&&this.destroy()}}),this.document=a(d.style?d.ownerDocument:d.document||d),this.window=a(this.document[0].defaultView||this.document[0].parentWindow));this._create();this._trigger("create",null,this._getCreateEventData());this._init()},_getCreateOptions:a.noop,_getCreateEventData:a.noop,_create:a.noop,
|
||||
_init:a.noop,destroy:function(){this._destroy();this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(a.camelCase(this.widgetFullName));this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled");this.bindings.unbind(this.eventNamespace);this.hoverable.removeClass("ui-state-hover");this.focusable.removeClass("ui-state-focus")},_destroy:a.noop,widget:function(){return this.element},
|
||||
option:function(c,b){var f=c,k,l,m;if(0===arguments.length)return a.widget.extend({},this.options);if("string"===typeof c)if(f={},k=c.split("."),c=k.shift(),k.length){l=f[c]=a.widget.extend({},this.options[c]);for(m=0;m<k.length-1;m++)l[k[m]]=l[k[m]]||{},l=l[k[m]];c=k.pop();if(b===d)return l[c]===d?null:l[c];l[c]=b}else{if(b===d)return this.options[c]===d?null:this.options[c];f[c]=b}this._setOptions(f);return this},_setOptions:function(a){for(var c in a)this._setOption(c,a[c]);return this},_setOption:function(a,
|
||||
c){this.options[a]=c;"disabled"===a&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!c).attr("aria-disabled",c),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"));return this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(c,b,d){var f,l=this;"boolean"!==typeof c&&(d=b,b=c,c=!1);d?(b=f=a(b),this.bindings=this.bindings.add(b)):(d=b,b=this.element,f=
|
||||
this.widget());a.each(d,function(d,h){function q(){if(c||!0!==l.options.disabled&&!a(this).hasClass("ui-state-disabled"))return("string"===typeof h?l[h]:h).apply(l,arguments)}"string"!==typeof h&&(q.guid=h.guid=h.guid||q.guid||a.guid++);var p=d.match(/^(\w+)\s*(.*)$/),r=p[1]+l.eventNamespace;(p=p[2])?f.delegate(p,r,q):b.bind(r,q)})},_off:function(a,c){c=(c||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace;a.unbind(c).undelegate(c)},_delay:function(a,c){var b=this;return setTimeout(function(){return("string"===
|
||||
typeof a?b[a]:a).apply(b,arguments)},c||0)},_hoverable:function(c){this.hoverable=this.hoverable.add(c);this._on(c,{mouseenter:function(c){a(c.currentTarget).addClass("ui-state-hover")},mouseleave:function(c){a(c.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(c){this.focusable=this.focusable.add(c);this._on(c,{focusin:function(c){a(c.currentTarget).addClass("ui-state-focus")},focusout:function(c){a(c.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(c,b,d){var f,
|
||||
l=this.options[c];d=d||{};b=a.Event(b);b.type=(c===this.widgetEventPrefix?c:this.widgetEventPrefix+c).toLowerCase();b.target=this.element[0];if(c=b.originalEvent)for(f in c)f in b||(b[f]=c[f]);this.element.trigger(b,d);return!(a.isFunction(l)&&!1===l.apply(this.element[0],[b].concat(d))||b.isDefaultPrevented())}};a.each({show:"fadeIn",hide:"fadeOut"},function(c,b){a.Widget.prototype["_"+c]=function(d,f,l){"string"===typeof f&&(f={effect:f});var m,n=f?!0===f||"number"===typeof f?b:f.effect||b:c;f=
|
||||
f||{};"number"===typeof f&&(f={duration:f});m=!a.isEmptyObject(f);f.complete=l;f.delay&&d.delay(f.delay);if(m&&a.effects&&a.effects.effect[n])d[c](f);else if(n!==c&&d[n])d[n](f.duration,f.easing,l);else d.queue(function(b){a(this)[c]();l&&l.call(d[0]);b()})}})})(jQuery);
|
||||
(function(a,d){var b=!1;a(document).mouseup(function(){b=!1});a.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var c=this;this.element.bind("mousedown."+this.widgetName,function(a){return c._mouseDown(a)}).bind("click."+this.widgetName,function(b){if(!0===a.data(b.target,c.widgetName+".preventClickEvent"))return a.removeData(b.target,c.widgetName+".preventClickEvent"),b.stopImmediatePropagation(),!1});this.started=
|
||||
!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);this._mouseMoveDelegate&&a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(c){if(!b){this._mouseStarted&&this._mouseUp(c);this._mouseDownEvent=c;var d=this,e=1===c.which,g="string"===typeof this.options.cancel&&c.target.nodeName?a(c.target).closest(this.options.cancel).length:!1;if(!e||g||!this._mouseCapture(c))return!0;this.mouseDelayMet=
|
||||
!this.options.delay;this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(c)&&this._mouseDelayMet(c)&&(this._mouseStarted=!1!==this._mouseStart(c),!this._mouseStarted))return c.preventDefault(),!0;!0===a.data(c.target,this.widgetName+".preventClickEvent")&&a.removeData(c.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(a){return d._mouseMove(a)};this._mouseUpDelegate=function(a){return d._mouseUp(a)};
|
||||
a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.preventDefault();return b=!0}},_mouseMove:function(c){if(a.ui.ie&&(!document.documentMode||9>document.documentMode)&&!c.button)return this._mouseUp(c);if(this._mouseStarted)return this._mouseDrag(c),c.preventDefault();this._mouseDistanceMet(c)&&this._mouseDelayMet(c)&&((this._mouseStarted=!1!==this._mouseStart(this._mouseDownEvent,c))?this._mouseDrag(c):this._mouseUp(c));
|
||||
return!this._mouseStarted},_mouseUp:function(c){a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);this._mouseStarted&&(this._mouseStarted=!1,c.target===this._mouseDownEvent.target&&a.data(c.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(c));return!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},
|
||||
_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);
|
||||
(function(a,d){function b(a){return/left|right/.test(a.css("float"))||/inline|table-cell/.test(a.css("display"))}a.widget("ui.sortable",a.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",
|
||||
zIndex:1E3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?"x"===a.axis||b(this.items[0].item):!1;this.offset=this.element.offset();this._mouseInit();this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled");this._mouseDestroy();
|
||||
for(var a=this.items.length-1;0<=a;a--)this.items[a].item.removeData(this.widgetName+"-item");return this},_setOption:function(c,b){"disabled"===c?(this.options[c]=b,this.widget().toggleClass("ui-sortable-disabled",!!b)):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(c,b){var d=null,g=!1,h=this;if(this.reverting||this.options.disabled||"static"===this.options.type)return!1;this._refreshItems(c);a(c.target).parents().each(function(){if(a.data(this,h.widgetName+"-item")===
|
||||
h)return d=a(this),!1});a.data(c.target,h.widgetName+"-item")===h&&(d=a(c.target));if(!d||this.options.handle&&!b&&(a(this.options.handle,d).find("*").addBack().each(function(){this===c.target&&(g=!0)}),!g))return!1;this.currentItem=d;this._removeCurrentsFromItems();return!0},_mouseStart:function(c,b,d){var g;b=this.options;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(c);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();
|
||||
this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:c.pageX-this.offset.left,top:c.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");this.originalPosition=this._generatePosition(c);this.originalPageX=c.pageX;this.originalPageY=c.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);
|
||||
this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!==this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();b.cursor&&"auto"!==b.cursor&&(g=this.document.find("body"),this.storedCursor=g.css("cursor"),g.css("cursor",b.cursor),this.storedStylesheet=a("<style>*{ cursor: "+b.cursor+" !important; }</style>").appendTo(g));b.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),
|
||||
this.helper.css("opacity",b.opacity));b.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",b.zIndex));this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset());this._trigger("start",c,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(d=this.containers.length-1;0<=d;d--)this.containers[d]._trigger("activate",c,this._uiHash(this));a.ui.ddmanager&&
|
||||
(a.ui.ddmanager.current=this);a.ui.ddmanager&&!b.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,c);this.dragging=!0;this.helper.addClass("ui-sortable-helper");this._mouseDrag(c);return!0},_mouseDrag:function(c){var b,d,g,h;b=this.options;d=!1;this.position=this._generatePosition(c);this.positionAbs=this._convertPositionTo("absolute");this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+
|
||||
this.scrollParent[0].offsetHeight-c.pageY<b.scrollSensitivity?this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop+b.scrollSpeed:c.pageY-this.overflowOffset.top<b.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-b.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-c.pageX<b.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+b.scrollSpeed:c.pageX-this.overflowOffset.left<b.scrollSensitivity&&(this.scrollParent[0].scrollLeft=
|
||||
d=this.scrollParent[0].scrollLeft-b.scrollSpeed)):(c.pageY-a(document).scrollTop()<b.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-b.scrollSpeed):a(window).height()-(c.pageY-a(document).scrollTop())<b.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+b.scrollSpeed)),c.pageX-a(document).scrollLeft()<b.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-b.scrollSpeed):a(window).width()-(c.pageX-a(document).scrollLeft())<b.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollLeft()+
|
||||
b.scrollSpeed))),!1!==d&&a.ui.ddmanager&&!b.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,c));this.positionAbs=this._convertPositionTo("absolute");this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px");this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px");for(b=this.items.length-1;0<=b;b--)if(d=this.items[b],g=d.item[0],(h=this._intersectsWithPointer(d))&&d.instance===this.currentContainer&&g!==this.currentItem[0]&&
|
||||
this.placeholder[1===h?"next":"prev"]()[0]!==g&&!a.contains(this.placeholder[0],g)&&("semi-dynamic"===this.options.type?!a.contains(this.element[0],g):1)){this.direction=1===h?"down":"up";if("pointer"===this.options.tolerance||this._intersectsWithSides(d))this._rearrange(c,d);else break;this._trigger("change",c,this._uiHash());break}this._contactContainers(c);a.ui.ddmanager&&a.ui.ddmanager.drag(this,c);this._trigger("sort",c,this._uiHash());this.lastPositionAbs=this.positionAbs;return!1},_mouseStop:function(c,
|
||||
b){if(c){a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,c);if(this.options.revert){var d=this,g=this.placeholder.offset(),h=this.options.axis,k={};h&&"x"!==h||(k.left=g.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft));h&&"y"!==h||(k.top=g.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop));this.reverting=!0;a(this.helper).animate(k,parseInt(this.options.revert,
|
||||
10)||500,function(){d._clear(c)})}else this._clear(c,b);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null});"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;0<=c;c--)this.containers[c]._trigger("deactivate",null,this._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,this._uiHash(this)),this.containers[c].containerCache.over=
|
||||
0)}this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem));return this},serialize:function(c){var b=this._getItemsAsjQuery(c&&c.connected),d=[];c=c||{};
|
||||
a(b).each(function(){var b=(a(c.item||this).attr(c.attribute||"id")||"").match(c.expression||/(.+)[\-=_](.+)/);b&&d.push((c.key||b[1]+"[]")+"="+(c.key&&c.expression?b[1]:b[2]))});!d.length&&c.key&&d.push(c.key+"=");return d.join("&")},toArray:function(c){var b=this._getItemsAsjQuery(c&&c.connected),d=[];c=c||{};b.each(function(){d.push(a(c.item||this).attr(c.attribute||"id")||"")});return d},_intersectsWith:function(a){var b=this.positionAbs.left,d=b+this.helperProportions.width,g=this.positionAbs.top,
|
||||
h=g+this.helperProportions.height,k=a.left,l=k+a.width,m=a.top,n=m+a.height,q=this.offset.click.top,p=this.offset.click.left,p="y"===this.options.axis||b+p>k&&b+p<l,q=("x"===this.options.axis||g+q>m&&g+q<n)&&p;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?q:k<b+this.helperProportions.width/2&&d-this.helperProportions.width/2<l&&m<g+this.helperProportions.height/
|
||||
2&&h-this.helperProportions.height/2<n},_intersectsWithPointer:function(a){var b="y"===this.options.axis||this.positionAbs.left+this.offset.click.left>a.left&&this.positionAbs.left+this.offset.click.left<a.left+a.width;a=("x"===this.options.axis||this.positionAbs.top+this.offset.click.top>a.top&&this.positionAbs.top+this.offset.click.top<a.top+a.height)&&b;var b=this._getDragVerticalDirection(),d=this._getDragHorizontalDirection();return a?this.floating?d&&"right"===d||"down"===b?2:1:b&&("down"===
|
||||
b?2:1):!1},_intersectsWithSides:function(a){var b=this.positionAbs.top+this.offset.click.top>a.top+a.height/2&&this.positionAbs.top+this.offset.click.top<a.top+a.height/2+a.height;a=this.positionAbs.left+this.offset.click.left>a.left+a.width/2&&this.positionAbs.left+this.offset.click.left<a.left+a.width/2+a.width;var d=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();return this.floating&&g?"right"===g&&a||"left"===g&&!a:d&&("down"===d&&b||"up"===d&&!b)},_getDragVerticalDirection:function(){var a=
|
||||
this.positionAbs.top-this.lastPositionAbs.top;return 0!==a&&(0<a?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return 0!==a&&(0<a?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor===String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(c){var b,d,g,h=[],k=[],l=this._connectWith();if(l&&c)for(c=l.length-1;0<=
|
||||
c;c--)for(d=a(l[c]),b=d.length-1;0<=b;b--)(g=a.data(d[b],this.widgetFullName))&&g!==this&&!g.options.disabled&&k.push([a.isFunction(g.options.items)?g.options.items.call(g.element):a(g.options.items,g.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),g]);k.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);
|
||||
for(c=k.length-1;0<=c;c--)k[c][0].each(function(){h.push(this)});return a(h)},_removeCurrentsFromItems:function(){var c=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=a.grep(this.items,function(a){for(var b=0;b<c.length;b++)if(c[b]===a.item[0])return!1;return!0})},_refreshItems:function(c){this.items=[];this.containers=[this];var b,d,g,h,k,l=this.items,m=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],c,{item:this.currentItem}):a(this.options.items,
|
||||
this.element),this]];if((k=this._connectWith())&&this.ready)for(b=k.length-1;0<=b;b--)for(g=a(k[b]),d=g.length-1;0<=d;d--)(h=a.data(g[d],this.widgetFullName))&&h!==this&&!h.options.disabled&&(m.push([a.isFunction(h.options.items)?h.options.items.call(h.element[0],c,{item:this.currentItem}):a(h.options.items,h.element),h]),this.containers.push(h));for(b=m.length-1;0<=b;b--)for(c=m[b][1],g=m[b][0],d=0,k=g.length;d<k;d++)h=a(g[d]),h.data(this.widgetName+"-item",c),l.push({item:h,instance:c,width:0,height:0,
|
||||
left:0,top:0})},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var d,e,g;for(d=this.items.length-1;0<=d;d--)e=this.items[d],e.instance!==this.currentContainer&&this.currentContainer&&e.item[0]!==this.currentItem[0]||(g=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item,b||(e.width=g.outerWidth(),e.height=g.outerHeight()),g=g.offset(),e.left=g.left,e.top=g.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);
|
||||
else for(d=this.containers.length-1;0<=d;d--)g=this.containers[d].element.offset(),this.containers[d].containerCache.left=g.left,this.containers[d].containerCache.top=g.top,this.containers[d].containerCache.width=this.containers[d].element.outerWidth(),this.containers[d].containerCache.height=this.containers[d].element.outerHeight();return this},_createPlaceholder:function(b){b=b||this;var d,e=b.options;e.placeholder&&e.placeholder.constructor!==String||(d=e.placeholder,e.placeholder={element:function(){var e=
|
||||
b.currentItem[0].nodeName.toLowerCase(),h=a("<"+e+">",b.document[0]).addClass(d||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");"tr"===e?b.currentItem.children().each(function(){a("<td> </td>",b.document[0]).attr("colspan",a(this).attr("colspan")||1).appendTo(h)}):"img"===e&&h.attr("src",b.currentItem.attr("src"));d||h.css("visibility","hidden");return h},update:function(a,h){if(!d||e.forcePlaceholderSize)h.height()||h.height(b.currentItem.innerHeight()-
|
||||
parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10)),h.width()||h.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}});b.placeholder=a(e.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);e.placeholder.update(b,b.placeholder)},_contactContainers:function(c){var d,e,g,h,k,l,m,n,q,p=e=null;for(d=this.containers.length-1;0<=d;d--)a.contains(this.currentItem[0],
|
||||
this.containers[d].element[0])||(this._intersectsWith(this.containers[d].containerCache)?e&&a.contains(this.containers[d].element[0],e.element[0])||(e=this.containers[d],p=d):this.containers[d].containerCache.over&&(this.containers[d]._trigger("out",c,this._uiHash(this)),this.containers[d].containerCache.over=0));if(e)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",c,this._uiHash(this)),this.containers[p].containerCache.over=1);else{d=1E4;
|
||||
g=null;h=(q=e.floating||b(this.currentItem))?"left":"top";k=q?"width":"height";l=this.positionAbs[h]+this.offset.click[h];for(e=this.items.length-1;0<=e;e--)a.contains(this.containers[p].element[0],this.items[e].item[0])&&this.items[e].item[0]!==this.currentItem[0]&&(!q||this.positionAbs.top+this.offset.click.top>this.items[e].top&&this.positionAbs.top+this.offset.click.top<this.items[e].top+this.items[e].height)&&(m=this.items[e].item.offset()[h],n=!1,Math.abs(m-l)>Math.abs(m+this.items[e][k]-l)&&
|
||||
(n=!0,m+=this.items[e][k]),Math.abs(m-l)<d&&(d=Math.abs(m-l),g=this.items[e],this.direction=n?"up":"down"));(g||this.options.dropOnEmpty)&&this.currentContainer!==this.containers[p]&&(g?this._rearrange(c,g,null,!0):this._rearrange(c,null,this.containers[p].element,!0),this._trigger("change",c,this._uiHash()),this.containers[p]._trigger("change",c,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",
|
||||
c,this._uiHash(this)),this.containers[p].containerCache.over=1)}},_createHelper:function(b){var d=this.options;b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[b,this.currentItem])):"clone"===d.helper?this.currentItem.clone():this.currentItem;b.parents("body").length||a("parent"!==d.appendTo?d.appendTo:this.currentItem[0].parentNode)[0].appendChild(b[0]);b[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),
|
||||
top:this.currentItem.css("top"),left:this.currentItem.css("left")});b[0].style.width&&!d.forceHelperSize||b.width(this.currentItem.width());b[0].style.height&&!d.forceHelperSize||b.height(this.currentItem.height());return b},_adjustOffsetFromHelper:function(b){"string"===typeof b&&(b=b.split(" "));a.isArray(b)&&(b={left:+b[0],top:+b[1]||0});"left"in b&&(this.offset.click.left=b.left+this.margins.left);"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left);"top"in
|
||||
b&&(this.offset.click.top=b.top+this.margins.top);"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&a.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&
|
||||
"html"===this.offsetParent[0].tagName.toLowerCase()&&a.ui.ie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,
|
||||
left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b,d,e;d=this.options;"parent"===d.containment&&(d.containment=this.helper[0].parentNode);if("document"===d.containment||"window"===d.containment)this.containment=[0-this.offset.relative.left-
|
||||
this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a("document"===d.containment?document:window).width()-this.helperProportions.width-this.margins.left,(a("document"===d.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];/^(document|window|parent)$/.test(d.containment)||(b=a(d.containment)[0],d=a(d.containment).offset(),e="hidden"!==a(b).css("overflow"),this.containment=[d.left+(parseInt(a(b).css("borderLeftWidth"),
|
||||
10)||0)+(parseInt(a(b).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(b).css("borderTopWidth"),10)||0)+(parseInt(a(b).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(a(b).css("borderLeftWidth"),10)||0)-(parseInt(a(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(a(b).css("borderTopWidth"),10)||0)-(parseInt(a(b).css("paddingBottom"),
|
||||
10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(b,d){d||(d=this.position);var e="absolute"===b?1:-1,g="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&a.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(g[0].tagName);return{top:d.top+this.offset.relative.top*e+this.offset.parent.top*e-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:g.scrollTop())*e,left:d.left+this.offset.relative.left*
|
||||
e+this.offset.parent.left*e-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:g.scrollLeft())*e}},_generatePosition:function(b){var d,e,g=this.options;e=b.pageX;d=b.pageY;var h="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&a.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,k=/(html|body)/i.test(h[0].tagName);"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=
|
||||
this._getRelativeOffset());this.originalPosition&&(this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(e=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(d=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(e=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(d=this.containment[3]+this.offset.click.top)),g.grid&&(d=this.originalPageY+Math.round((d-
|
||||
this.originalPageY)/g.grid[1])*g.grid[1],d=this.containment?d-this.offset.click.top>=this.containment[1]&&d-this.offset.click.top<=this.containment[3]?d:d-this.offset.click.top>=this.containment[1]?d-g.grid[1]:d+g.grid[1]:d,e=this.originalPageX+Math.round((e-this.originalPageX)/g.grid[0])*g.grid[0],e=this.containment?e-this.offset.click.left>=this.containment[0]&&e-this.offset.click.left<=this.containment[2]?e:e-this.offset.click.left>=this.containment[0]?e-g.grid[0]:e+g.grid[0]:e));return{top:d-
|
||||
this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():k?0:h.scrollTop()),left:e-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():k?0:h.scrollLeft())}},_rearrange:function(a,b,d,g){d?d[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?b.item[0]:b.item[0].nextSibling);var h=this.counter=
|
||||
this.counter?++this.counter:1;this._delay(function(){h===this.counter&&this.refreshPositions(!g)})},_clear:function(a,b){this.reverting=!1;var d,g=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]===this.currentItem[0]){for(d in this._storedCSS)if("auto"===this._storedCSS[d]||"static"===this._storedCSS[d])this._storedCSS[d]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();
|
||||
this.fromOutside&&!b&&g.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))});!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||b||g.push(function(a){this._trigger("update",a,this._uiHash())});this===this.currentContainer||b||(g.push(function(a){this._trigger("remove",a,this._uiHash())}),g.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,
|
||||
this.currentContainer)),g.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.currentContainer)));for(d=this.containers.length-1;0<=d;d--)b||g.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[d])),this.containers[d].containerCache.over&&(g.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[d])),this.containers[d].containerCache.over=0);this.storedCursor&&
|
||||
(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove());this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex);this.dragging=!1;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(d=0;d<g.length;d++)g[d].call(this,a);this._trigger("stop",a,this._uiHash())}return this.fromOutside=!1}b||this._trigger("beforeStop",a,this._uiHash());
|
||||
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!==this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(d=0;d<g.length;d++)g[d].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=!1;return!0},_trigger:function(){!1===a.Widget.prototype._trigger.apply(this,arguments)&&this.cancel()},_uiHash:function(b){var d=b||this;return{helper:d.helper,placeholder:d.placeholder||a([]),position:d.position,originalPosition:d.originalPosition,offset:d.positionAbs,
|
||||
item:d.currentItem,sender:b?b.element:null}}})})(jQuery);(function(a){var d=a({});a.subscribe=function(){d.on.apply(d,arguments)};a.unsubscribe=function(){d.off.apply(d,arguments)};a.publish=function(){d.trigger.apply(d,arguments)}})(jQuery);(function(){var a=$.namespace("pskl.model");a.Frame=function(d,b){if(d&&b)this.width=d,this.height=b,this.pixels=a.Frame.createEmptyPixelGrid_(d,b),this.previousStates=[this.getPixels()],this.stateIndex=0;else throw"Bad arguments in pskl.model.Frame constructor : "+d+", "+b;};a.Frame.fromPixelGrid=function(a){if(a.length&&a[0].length){var b=new pskl.model.Frame(a.length,a[0].length);b.setPixels(a);return b}throw"Bad arguments in pskl.model.Frame.fromPixelGrid : "+a;};a.Frame.createEmptyPixelGrid_=
|
||||
function(a,b){for(var c=[],f=0;f<a;f++){for(var e=[],g=0;g<b;g++)e.push(Constants.TRANSPARENT_COLOR);c[f]=e}return c};a.Frame.createEmptyFromFrame=function(d){return new a.Frame(d.getWidth(),d.getHeight())};a.Frame.prototype.clone=function(){var d=new a.Frame(this.width,this.height);d.setPixels(this.getPixels());return d};a.Frame.prototype.getPixels=function(){return this.clonePixels_(this.pixels)};a.Frame.prototype.setPixels=function(a){this.pixels=this.clonePixels_(a)};a.Frame.prototype.clear=function(){var d=
|
||||
a.Frame.createEmptyPixelGrid_(this.getWidth(),this.getHeight());this.setPixels(d)};a.Frame.prototype.clonePixels_=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c].slice(0,a[c].length);return b};a.Frame.prototype.serialize=function(){return JSON.stringify(this.pixels)};a.Frame.prototype.setPixel=function(a,b,c){this.pixels[a][b]=c};a.Frame.prototype.getPixel=function(a,b){return this.pixels[a][b]};a.Frame.prototype.forEachPixel=function(a){for(var b=0;b<this.getWidth();b++)for(var c=0;c<this.getHeight();c++)a(this.getPixel(b,
|
||||
c),b,c)};a.Frame.prototype.getWidth=function(){return this.width};a.Frame.prototype.getHeight=function(){return this.height};a.Frame.prototype.containsPixel=function(a,b){return 0<=a&&0<=b&&a<this.pixels.length&&b<this.pixels[0].length};a.Frame.prototype.saveState=function(){this.previousStates.length=this.stateIndex+1;this.previousStates.push(this.getPixels());this.stateIndex=this.previousStates.length-1};a.Frame.prototype.loadPreviousState=function(){0<this.stateIndex&&(this.stateIndex--,this.setPixels(this.previousStates[this.stateIndex]))};
|
||||
a.Frame.prototype.loadNextState=function(){this.stateIndex<this.previousStates.length-1&&(this.stateIndex++,this.setPixels(this.previousStates[this.stateIndex]))};a.Frame.prototype.isSameSize=function(a){return this.getHeight()==a.getHeight()&&this.getWidth()==a.getWidth()}})();(function(){var a=$.namespace("pskl.model");a.Layer=function(a){if(a)this.name=a,this.frames=[];else throw"Invalid arguments in Layer constructor : 'name' is mandatory";};a.Layer.prototype.getName=function(){return this.name};a.Layer.prototype.getFrames=function(){return this.frames};a.Layer.prototype.getFrameAt=function(a){return this.frames[a]};a.Layer.prototype.addFrame=function(a){this.frames.push(a)};a.Layer.prototype.addFrameAt=function(a,b){this.frames.splice(b,0,a)};a.Layer.prototype.removeFrame=
|
||||
function(a){a=this.frames.indexOf(a);this.removeFrameAt(a)};a.Layer.prototype.removeFrameAt=function(a){if(this.frames[a])this.frames.splice(a,1);else throw"Invalid index in removeFrameAt : "+a+" (size : "+this.length()+")";};a.Layer.prototype.moveFrame=function(a,b){var c=this.frames.splice(a,1)[0];this.frames.splice(b,0,c)};a.Layer.prototype.swapFramesAt=function(a,b){var c=this.frames[a],f=this.frames[b];if(c&&f)this.frames[b]=c,this.frames[a]=f;else throw console.log("frames",this.frames),console.log("fromIndex",
|
||||
a,"toIndex",b),"Frame not found in moveFrameAt";};a.Layer.prototype.duplicateFrame=function(a){this.frames.indexOf(a);this.duplicateFrameAt()};a.Layer.prototype.duplicateFrameAt=function(a){var b=this.frames[a];if(b)b=b.clone(),this.addFrameAt(b,a);else throw"Frame not found in duplicateFrameAt";};a.Layer.prototype.length=function(){return this.frames.length}})();(function(){var a=$.namespace("pskl.model");a.Piskel=function(a,b){if(a&&b)this.layers=[],this.width=a,this.height=b;else throw"Missing arguments in Piskel constructor : "+Array.prototype.join.call(arguments,",");};a.Piskel.prototype.getLayers=function(){return this.layers};a.Piskel.prototype.getHeight=function(){return this.height};a.Piskel.prototype.getWidth=function(){return this.width};a.Piskel.prototype.getLayers=function(){return this.layers};a.Piskel.prototype.getLayerAt=function(a){return this.layers[a]};
|
||||
a.Piskel.prototype.getLayersByName=function(a){return this.layers.filter(function(b){return b.getName()==a})};a.Piskel.prototype.addLayer=function(a){this.layers.push(a)};a.Piskel.prototype.moveLayerUp=function(a){var b=this.layers.indexOf(a);-1<b&&b<this.layers.length-1&&(this.layers[b]=this.layers[b+1],this.layers[b+1]=a)};a.Piskel.prototype.moveLayerDown=function(a){var b=this.layers.indexOf(a);0<b&&(this.layers[b]=this.layers[b-1],this.layers[b-1]=a)};a.Piskel.prototype.removeLayer=function(a){a=
|
||||
this.layers.indexOf(a);-1!=a&&this.layers.splice(a,1)};a.Piskel.prototype.removeLayerAt=function(a){this.layers.splice(a,1)}})();(function(){var a=$.namespace("pskl.rendering");a.CanvasRenderer=function(a,b){this.frame=a;this.dpi=b;this.transparentColor_="white"};a.CanvasRenderer.prototype.drawTransparentAs=function(a){this.transparentColor_=a};a.CanvasRenderer.prototype.render=function(){for(var a=this.createCanvas_().getContext("2d"),b=0,c=this.frame.getWidth();b<c;b++)for(var f=0,e=this.frame.getHeight();f<e;f++){var g=this.frame.getPixel(b,f);this.renderPixel_(g,b,f,a)}return a};a.CanvasRenderer.prototype.renderPixel_=
|
||||
function(a,b,c,f){a==Constants.TRANSPARENT_COLOR&&(a=this.transparentColor_);f.fillStyle=a;f.fillRect(b*this.dpi,c*this.dpi,this.dpi,this.dpi)};a.CanvasRenderer.prototype.createCanvas_=function(){var a=this.frame.getWidth()*this.dpi,b=this.frame.getHeight()*this.dpi;return pskl.CanvasUtils.createCanvas(a,b)}})();(function(){var a=$.namespace("pskl.rendering");a.DrawingLoop=function(){this.requestAnimationFrame=this.getRequestAnimationFrameShim_();this.isRunning=!1;this.previousTime=0;this.callbacks=[]};a.DrawingLoop.prototype.addCallback=function(a,b,c){a={fn:a,scope:b,args:c};this.callbacks.push(a);return a};a.DrawingLoop.prototype.removeCallback=function(a){a=this.callbacks.indexOf(a);-1!=a&&this.callbacks.splice(a,1)};a.DrawingLoop.prototype.start=function(){this.isRunning=!0;this.loop_()};a.DrawingLoop.prototype.loop_=
|
||||
function(){var a=Date.now();this.executeCallbacks_(a-this.previousTime);this.previousTime=a;this.requestAnimationFrame.call(window,this.loop_.bind(this))};a.DrawingLoop.prototype.executeCallbacks_=function(a){for(var b=0;b<this.callbacks.length;b++){var c=this.callbacks[b];c.fn.call(c.scope,a,c.args)}};a.DrawingLoop.prototype.stop=function(){this.isRunning=!1};a.DrawingLoop.prototype.getRequestAnimationFrameShim_=function(){return window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||
|
||||
window.msRequestAnimationFrame||function(a){window.setTimeout(a,1E3/60)}}})();(function(){var a=$.namespace("pskl.rendering");a.FrameRenderer=function(a,b,c){this.defaultRenderingOptions={supportGridRendering:!1};b=$.extend(!0,{},this.defaultRenderingOptions,b);if(void 0===a)throw"Bad FrameRenderer initialization. <container> undefined.";if(isNaN(b.dpi))throw"Bad FrameRenderer initialization. <dpi> not well defined.";this.container=a;this.dpi=b.dpi;this.supportGridRendering=b.supportGridRendering;this.classes=c||[];this.classes.push("canvas");this.canvas=null;this.enableGrid(pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID));
|
||||
this.canvasConfigDirty=!0;this.updateBackgroundClass_(pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND));$.subscribe(Events.USER_SETTINGS_CHANGED,$.proxy(this.onUserSettingsChange_,this))};a.FrameRenderer.prototype.setDPI=function(a){this.dpi=a;this.canvasConfigDirty=!0};a.FrameRenderer.prototype.onUserSettingsChange_=function(a,b,c){b==pskl.UserSettings.SHOW_GRID?this.enableGrid(c):b==pskl.UserSettings.CANVAS_BACKGROUND&&this.updateBackgroundClass_(c)};a.FrameRenderer.prototype.updateBackgroundClass_=
|
||||
function(a){var b=this.container.data("current-background-class");b&&this.container.removeClass(b);this.container.addClass(a);this.container.data("current-background-class",a)};a.FrameRenderer.prototype.enableGrid=function(a){this.gridStrokeWidth=a&&this.supportGridRendering?Constants.GRID_STROKE_WIDTH:0;this.canvasConfigDirty=!0};a.FrameRenderer.prototype.render=function(a){if(a){this.clear();for(var b=this.getCanvas_(a).getContext("2d"),c=0,f=a.getWidth();c<f;c++)for(var e=0,g=a.getHeight();e<g;e++){var h=
|
||||
a.getPixel(c,e);this.renderPixel_(h,c,e,b)}this.lastRenderedFrame=a}};a.FrameRenderer.prototype.renderPixel_=function(a,b,c,f){a!=Constants.TRANSPARENT_COLOR&&(f.fillStyle=a,f.fillRect(this.getFramePos_(b),this.getFramePos_(c),this.dpi,this.dpi))};a.FrameRenderer.prototype.clear=function(){this.canvas&&this.canvas.getContext("2d").clearRect(0,0,this.canvas.width,this.canvas.height)};a.FrameRenderer.prototype.convertPixelCoordinatesIntoSpriteCoordinate=function(a){var b=this.dpi+this.gridStrokeWidth;
|
||||
return{col:(a.x-a.x%b)/b,row:(a.y-a.y%b)/b}};a.FrameRenderer.prototype.getFramePos_=function(a){return a*this.dpi+(a-1)*this.gridStrokeWidth};a.FrameRenderer.prototype.getCanvas_=function(a){if(this.canvasConfigDirty){$(this.canvas).remove();var b=a.getWidth();a=a.getHeight();b=pskl.CanvasUtils.createCanvas(b*this.dpi+this.gridStrokeWidth*(b-1),a*this.dpi+this.gridStrokeWidth*(a-1),this.classes);this.container.append(b);this.canvas=b;this.canvasConfigDirty=!1}return this.canvas}})();(function(){var a=$.namespace("pskl.rendering");a.SpritesheetRenderer=function(a){this.piskelController=a};a.SpritesheetRenderer.prototype.render=function(){for(var a=this.createCanvas_(),b=0;b<this.piskelController.getFrameCount();b++){var c=this.piskelController.getFrameAt(b);this.drawFrameInCanvas_(c,a,b*this.piskelController.getWidth(),0)}return a};a.SpritesheetRenderer.prototype.drawFrameInCanvas_=function(a,b,c,f){b=b.getContext("2d");for(var e=0,g=a.getWidth();e<g;e++)for(var h=0,k=a.getHeight();h<
|
||||
k;h++){var l=a.getPixel(e,h);l!=Constants.TRANSPARENT_COLOR&&(b.fillStyle=l,b.fillRect(e+c,h+f,1,1))}};a.SpritesheetRenderer.prototype.createCanvas_=function(){var a=this.piskelController.getFrameCount();if(0<a){var a=a*this.piskelController.getWidth(),b=this.piskelController.getHeight();return pskl.CanvasUtils.createCanvas(a,b)}throw"Cannot render empty Spritesheet";}})();(function(){var a=$.namespace("pskl.selection");a.BaseSelection=function(){this.reset()};a.BaseSelection.prototype.reset=function(){this.pixels=[];this.hasPastedContent=!1};a.BaseSelection.prototype.move=function(a,b){for(var c,f=[],e=0,g=this.pixels.length;e<g;e++)c=this.pixels[e],c.col+=a,c.row+=b,f.push(c);this.pixels=f};a.BaseSelection.prototype.fillSelectionFromFrame=function(a){for(var b,c=0,f=this.pixels.length;c<f;c++)b=this.pixels[c],b.copiedColor=a.getPixel(b.col,b.row);this.hasPastedContent=
|
||||
!0}})();(function(){var a=$.namespace("pskl.selection");a.RectangularSelection=function(a,b,c,f){this.pixels=pskl.PixelUtils.getRectanglePixels(a,b,c,f)};pskl.utils.inherit(a.RectangularSelection,a.BaseSelection)})();(function(){var a=$.namespace("pskl.selection");a.SelectionManager=function(a){this.piskelController=a;this.currentSelection=null};a.SelectionManager.prototype.init=function(){$.subscribe(Events.SELECTION_CREATED,$.proxy(this.onSelectionCreated_,this));$.subscribe(Events.SELECTION_DISMISSED,$.proxy(this.onSelectionDismissed_,this));$.subscribe(Events.SELECTION_MOVE_REQUEST,$.proxy(this.onSelectionMoved_,this));$.subscribe(Events.PASTE,$.proxy(this.onPaste_,this));$.subscribe(Events.COPY,$.proxy(this.onCopy_,
|
||||
this));$.subscribe(Events.CUT,$.proxy(this.onCut_,this));$.subscribe(Events.TOOL_SELECTED,$.proxy(this.onToolSelected_,this))};a.SelectionManager.prototype.cleanSelection_=function(){this.currentSelection&&this.currentSelection.reset()};a.SelectionManager.prototype.onToolSelected_=function(a,b){b instanceof pskl.drawingtools.BaseSelect||this.cleanSelection_()};a.SelectionManager.prototype.onSelectionDismissed_=function(a){this.cleanSelection_()};a.SelectionManager.prototype.onCut_=function(a){if(this.currentSelection){this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());
|
||||
a=this.currentSelection.pixels;for(var b=this.piskelController.getCurrentFrame(),c=0,f=a.length;c<f;c++)try{b.setPixel(a[c].col,a[c].row,Constants.TRANSPARENT_COLOR)}catch(e){}}else throw"Bad state for CUT callback in SelectionManager";};a.SelectionManager.prototype.onPaste_=function(a){if(this.currentSelection&&this.currentSelection.hasPastedContent){a=this.currentSelection.pixels;for(var b=this.piskelController.getCurrentFrame(),c=0,f=a.length;c<f;c++)try{b.setPixel(a[c].col,a[c].row,a[c].copiedColor)}catch(e){}}};
|
||||
a.SelectionManager.prototype.onCopy_=function(a){if(this.currentSelection&&this.piskelController.getCurrentFrame())this.currentSelection.fillSelectionFromFrame(this.piskelController.getCurrentFrame());else throw"Bad state for CUT callback in SelectionManager";};a.SelectionManager.prototype.onSelectionCreated_=function(a,b){if(b)this.currentSelection=b;else throw"No selection set in SelectionManager";};a.SelectionManager.prototype.onSelectionMoved_=function(a,b,c){if(this.currentSelection)this.currentSelection.move(b,
|
||||
c);else throw"Bad state: No currentSelection set when trying to move it in SelectionManager";}})();(function(){var a=$.namespace("pskl.selection");a.ShapeSelection=function(a){this.pixels=a};pskl.utils.inherit(a.ShapeSelection,a.BaseSelection)})();(function(){var a=$.namespace("pskl.service");a.HistoryService=function(a){this.piskelController=a};a.HistoryService.prototype.init=function(){$.subscribe(Events.TOOL_RELEASED,this.saveState.bind(this));$.subscribe(Events.UNDO,this.undo.bind(this));$.subscribe(Events.REDO,this.redo.bind(this))};a.HistoryService.prototype.saveState=function(){this.piskelController.getCurrentFrame().saveState()};a.HistoryService.prototype.undo=function(){this.piskelController.getCurrentFrame().loadPreviousState();$.publish(Events.PISKEL_RESET)};
|
||||
a.HistoryService.prototype.redo=function(){this.piskelController.getCurrentFrame().loadNextState();$.publish(Events.PISKEL_RESET)}})();(function(){var a=$.namespace("pskl.service");a.ImageUploadService=function(){};a.ImageUploadService.prototype.init=function(){};a.ImageUploadService.prototype.upload=function(a,b,c){var f=new XMLHttpRequest,e=new FormData;e.append("data",a);f.open("POST",Constants.IMAGE_SERVICE_UPLOAD_URL,!0);f.onload=function(a){200==this.status?b(Constants.IMAGE_SERVICE_GET_URL+this.responseText):c()};f.send(e)}})();(function(){var a=$.namespace("pskl.service");a.KeyboardEventService=function(){};a.KeyboardEventService.prototype.KeyboardActions_={ctrl:{z:Events.UNDO,y:Events.REDO,x:Events.CUT,c:Events.COPY,v:Events.PASTE}};a.KeyboardEventService.prototype.CharCodeToKeyCodeMap_={90:"z",89:"y",88:"x",67:"c",86:"v"};a.KeyboardEventService.prototype.onKeyUp_=function(a){var b=!1;-1!=navigator.appVersion.indexOf("Mac")&&(b=!0);if(b?a.metaKey:a.ctrlKey)if(b=this.CharCodeToKeyCodeMap_[a.which])if(b=this.KeyboardActions_.ctrl[b])return $.publish(b),
|
||||
a.preventDefault(),!1};a.KeyboardEventService.prototype.init=function(){$(document.body).keydown($.proxy(this.onKeyUp_,this))}})();(function(){var a=$.namespace("pskl.service");a.LocalStorageService=function(a){if(void 0===a)throw"Bad LocalStorageService initialization: <undefined piskelController>";this.piskelController=a;this.localStorageThrottler_=null};a.LocalStorageService.prototype.init=function(a){$.subscribe(Events.LOCALSTORAGE_REQUEST,$.proxy(this.persistToLocalStorageRequest_,this))};a.LocalStorageService.prototype.persistToLocalStorageRequest_=function(){null!==this.localStorageThrottler_&&window.clearTimeout(this.localStorageThrottler_);
|
||||
this.localStorageThrottler_=window.setTimeout($.proxy(function(){this.persistToLocalStorage_();this.localStorageThrottler_=null},this),1E3)};a.LocalStorageService.prototype.persistToLocalStorage_=function(){console.log("[LocalStorage service]: Snapshot stored");window.localStorage.snapShot=this.piskelController.serialize()};a.LocalStorageService.prototype.restoreFromLocalStorage_=function(){this.piskelController.deserialize(window.localStorage.snapShot);this.piskelController.setCurrentFrameIndex(0)};
|
||||
a.LocalStorageService.prototype.cleanLocalStorage_=function(){console.log("[LocalStorage service]: Snapshot removed");delete window.localStorage.snapShot};a.LocalStorageService.prototype.displayRestoreNotification=function(){window.localStorage&&window.localStorage.snapShot&&$.publish(Events.SHOW_NOTIFICATION,[{content:"Non saved version found. <a href='#' class='localstorage-restore onclick='pskl.app.restoreFromLocalStorage()'>reload</a> or <a href='#' class='localstorage-discard' onclick='pskl.app.cleanLocalStorage()'>discard</a>",
|
||||
behavior:$.proxy(function(a){a=$(a);a.click($.proxy(function(a){a=$(a.target);a.hasClass("localstorage-restore")?this.restoreFromLocalStorage_():a.hasClass("localstorage-discard")&&this.cleanLocalStorage_();$.publish(Events.HIDE_NOTIFICATION)},this))},this)}])}})();(function(){$.namespace("pskl").CanvasUtils={createCanvas:function(a,d,b){var c=document.createElement("canvas");c.setAttribute("width",a);c.setAttribute("height",d);"string"==typeof b&&(b=[b]);if(Array.isArray(b))for(a=0;a<b.length;a++)c.classList.add(b[a]);return c}}})();(function(){$.namespace("pskl.utils").FileUtils={readFile:function(a,d){var b=new FileReader;b.onload=function(a){d(a.target.result)};b.readAsDataURL(a)}}})();(function(){$.namespace("pskl.utils").FrameUtils={merge:function(a){var d=null;if(a.length){d=a[0].clone();d.getWidth();d.getHeight();for(var b=1;b<a.length;b++)pskl.utils.FrameUtils.mergeFrames_(d,a[b])}return d},mergeFrames_:function(a,d){d.forEachPixel(function(b,c,d){b!=Constants.TRANSPARENT_COLOR&&a.setPixel(c,d,b)})},createFromImage:function(a){var d=a.width,b=a.height,c=pskl.CanvasUtils.createCanvas(d,b).getContext("2d");c.drawImage(a,0,0,d,b,0,0,d,b);d=c.getImageData(0,0,d,b).data;b=[];for(c=
|
||||
0;c<a.width;++c){b[c]=[];for(var f=0;f<a.height;++f){var e=4*(f*a.width+c),g=d[e],h=d[e+1],k=d[e+2];b[c][f]=125>d[e+3]?"TRANSPARENT":this.rgbToHex(g,h,k)}}return b},rgbToHex:function(a,d,b){return"#"+this.componentToHex(a)+this.componentToHex(d)+this.componentToHex(b)},componentToHex:function(a){a=a.toString(16);return 1==a.length?"0"+a:a}}})();(function(){$.namespace("pskl.utils").ImageResizer={resize:function(a,d,b,c){var f=pskl.CanvasUtils.createCanvas(d,b),e=f.getContext("2d");e.save();c||this.disableSmoothingOnContext(e);e.translate(f.width/2,f.height/2);e.scale(d/a.width,b/a.height);e.drawImage(a,-a.width/2,-a.height/2);e.restore();return f},disableSmoothingOnContext:function(a){a.imageSmoothingEnabled=!1;a.mozImageSmoothingEnabled=!1;a.oImageSmoothingEnabled=!1;a.webkitImageSmoothingEnabled=!1;a.msImageSmoothingEnabled=!1}}})();(function(){$.namespace("pskl").PixelUtils={getRectanglePixels:function(a,d,b,c){a=this.getOrderedRectangleCoordinates(a,d,b,c);d=[];for(b=a.x0;b<=a.x1;b++)for(c=a.y0;c<=a.y1;c++)d.push({col:b,row:c});return d},getBoundRectanglePixels:function(a,d,b,c){a=this.getOrderedRectangleCoordinates(a,d,b,c);d=[];for(b=a.x0;b<=a.x1;b++)d.push({col:b,row:a.y0}),d.push({col:b,row:a.y1});for(b=a.y0;b<=a.y1;b++)d.push({col:a.x0,row:b}),d.push({col:a.x1,row:b});return d},getOrderedRectangleCoordinates:function(a,
|
||||
d,b,c){return{x0:Math.min(a,b),y0:Math.min(d,c),x1:Math.max(a,b),y1:Math.max(d,c)}},getSimilarConnectedPixelsFromFrame:function(a,d,b){a=a.clone();return this.paintSimilarConnectedPixelsFromFrame(a,d,b,"sdfsdfsdf")},paintSimilarConnectedPixelsFromFrame:function(a,d,b,c){var f=[],e=[],g=[-1,0,1,0],h=[0,1,0,-1],k;try{k=a.getPixel(d,b)}catch(l){}if(k!=c){e.push({col:d,row:b});d=0;for(b=a.getWidth()*a.getHeight();0<e.length;){d++;var m=e.pop();a.setPixel(m.col,m.row,c);f.push({col:m.col,row:m.row});for(var n=
|
||||
0;4>n;n++){var q=m.col+h[n],p=m.row+g[n];try{a.containsPixel(q,p)&&a.getPixel(q,p)==k&&e.push({col:q,row:p})}catch(r){}}if(d>10*b){console.log("loop breaker called");break}}return f}},calculateDPIForContainer:function(a,d,b){return this.calculateDPI(a.height(),a.width(),d,b)},calculateDPI:function(a,d,b,c){return Math.min(Math.floor(a/b),Math.floor(d/c))}}})();(function(){$.namespace("pskl.utils").Serializer={serializePiskel:function(a){var d=a.getLayers().map(function(a){return pskl.utils.Serializer.serializeLayer(a)});return JSON.stringify({modelVersion:Constants.MODEL_VERSION,piskel:{height:a.getHeight(),width:a.getWidth(),layers:d}})},serializeLayer:function(a){var d=a.getFrames().map(function(a){return a.serialize()});return JSON.stringify({name:a.getName(),frames:d})},deserializePiskel:function(a){a=JSON.parse(a);return this.createPiskelFromData(a)},
|
||||
createPiskel:function(a){var d=null;a.modelVersion==Constants.MODEL_VERSION?(a=a.piskel,d=new pskl.model.Piskel(a.width,a.height),a.layers.forEach(function(a){a=pskl.utils.Serializer.deserializeLayer(a);d.addLayer(a)})):d=pskl.utils.Serializer.backwardDeserializer_(a);return d},deserializeLayer:function(a){a=JSON.parse(a);var d=new pskl.model.Layer(a.name);a.frames.forEach(function(a){a=pskl.utils.Serializer.deserializeFrame(a);d.addFrame(a)});return d},deserializeFrame:function(a){a=JSON.parse(a);
|
||||
return pskl.model.Frame.fromPixelGrid(a)},backwardDeserializer_:function(a){var d=new pskl.model.Layer("Layer 1");a.forEach(function(a){d.addFrame(pskl.model.Frame.fromPixelGrid(a))});a=d.getFrameAt(0).getWidth();var b=d.getFrameAt(0).getHeight();a=new pskl.model.Piskel(a,b);a.addLayer(d);return a}}})();(function(){$.namespace("pskl.utils").Template={get:function(a){var d=document.getElementById(a);if(d)return d.innerHTML;console.error("Could not find template for id :",a)},createFromHTML:function(a){var d=document.createElement("div");d.innerHTML=a;return d.children[0]},replace:function(a,d){for(var b in d)d.hasOwnProperty(b)&&(a=a.replace(RegExp("\\{\\{"+b+"\\}\\}","g"),d[b]));return a}}})();(function(){$.namespace("pskl").UserSettings={SHOW_GRID:"SHOW_GRID",CANVAS_BACKGROUND:"CANVAS_BACKGROUND",KEY_TO_DEFAULT_VALUE_MAP_:{SHOW_GRID:!1,CANVAS_BACKGROUND:"medium-canvas-background"},cache_:{},get:function(a){this.checkKeyValidity_(a);a in this.cache_||(this.cache_[a]=this.readFromLocalStorage_(a)||this.readFromDefaults_(a));return this.cache_[a]},set:function(a,d){this.checkKeyValidity_(a);this.cache_[a]=d;this.writeToLocalStorage_(a,d);$.publish(Events.USER_SETTINGS_CHANGED,[a,d])},readFromLocalStorage_:function(a){a=
|
||||
window.localStorage[a];"undefined"!=typeof a&&(a=JSON.parse(a));return a},writeToLocalStorage_:function(a,d){window.localStorage[a]=JSON.stringify(d)},readFromDefaults_:function(a){return this.KEY_TO_DEFAULT_VALUE_MAP_[a]},checkKeyValidity_:function(a){a in this.KEY_TO_DEFAULT_VALUE_MAP_||console.log("UserSettings key <"+a+"> not find in supported keys.")}}})();jQuery.namespace=function(){var a=arguments,d=null,b,c,f;for(b=0;b<a.length;b+=1)for(f=a[b].split("."),d=window,c=0;c<f.length;c+=1)d[f[c]]=d[f[c]]||{},d=d[f[c]];return d};"function"!==typeof Function.prototype.bind&&(Function.prototype.bind=function(a){var d=this;return function(){return d.apply(a,arguments)}});
|
||||
(function(){var a=$.namespace("pskl.utils");a.rgbToHex=function(a,b,c){if(255<a||255<b||255<c)throw"Invalid color component";return(a<<16|b<<8|c).toString(16)};a.inherit=function(a,b){a.prototype=Object.create(b.prototype);a.prototype.constructor=a;a.prototype.superclass=b.prototype}})();(function(){var a=function(a,b){var c=window.document.createElement("script");c.setAttribute("src",a);c.setAttribute("onload",b);window.document.body.appendChild(c)};if(-1!=window.location.href.indexOf("debug")){window.exports={};var d=0;window.loadNextScript=function(){d==window.exports.scripts.length?(pskl.app.init(),delete window.exports,delete window.loadDebugScripts,delete window.done):(a(window.exports.scripts[d],"loadNextScript()"),d++)};a("piskel-script-list.js","loadNextScript()")}else{var b;
|
||||
b=-1!=window.location.href.indexOf("pack")?"build/piskel-packaged.js":"build/piskel-packaged-min.js";var c=window.setInterval(function(){0===document.querySelectorAll("._ctl").length?(window.clearInterval(c),a(b,"pskl.app.init()")):console.log("waiting for templates to load ....")},100)}})();exports.scripts="js/lib/jquery-1.8.0.js js/lib/jquery-ui-1.10.3.custom.js js/lib/pubsub.js js/lib/bootstrap/bootstrap.js js/lib/gif/gif.worker.js js/lib/gif/gif.js js/Constants.js js/Events.js js/utils/core.js js/utils/CanvasUtils.js js/utils/FileUtils.js js/utils/FrameUtils.js js/utils/ImageResizer.js js/utils/PixelUtils.js js/utils/Serializer.js js/utils/Template.js js/utils/UserSettings.js js/lib/jsColor_1_4_0/jscolor.js js/rendering/DrawingLoop.js js/model/Frame.js js/model/Layer.js js/model/Piskel.js js/selection/SelectionManager.js js/selection/BaseSelection.js js/selection/RectangularSelection.js js/selection/ShapeSelection.js js/rendering/CanvasRenderer.js js/rendering/FrameRenderer.js js/rendering/SpritesheetRenderer.js js/controller/PiskelController.js js/controller/DrawingController.js js/controller/PreviewFilmController.js js/controller/LayersListController.js js/controller/AnimatedPreviewController.js js/controller/ToolController.js js/controller/PaletteController.js js/controller/NotificationController.js js/controller/settings/ApplicationSettingsController.js js/controller/settings/GifExportController.js js/controller/settings/ImportController.js js/controller/settings/SettingsController.js js/service/LocalStorageService.js js/service/HistoryService.js js/service/KeyboardEventService.js js/service/ImageUploadService.js js/drawingtools/BaseTool.js js/drawingtools/SimplePen.js js/drawingtools/VerticalMirrorPen.js js/drawingtools/Eraser.js js/drawingtools/Stroke.js js/drawingtools/PaintBucket.js js/drawingtools/Rectangle.js js/drawingtools/Circle.js js/drawingtools/Move.js js/drawingtools/selectiontools/BaseSelect.js js/drawingtools/selectiontools/RectangleSelect.js js/drawingtools/selectiontools/ShapeSelect.js js/drawingtools/ColorPicker.js js/app.js".split(" ");
|
8
preview/css/bootstrap/bootstrap-tooltip-custom.css
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
.tooltip.in {
|
||||
opacity: 0.95;
|
||||
filter: alpha(opacity=95);
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
line-height: 20px;
|
||||
}
|
112
preview/css/bootstrap/bootstrap.css
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
/*!
|
||||
* Bootstrap v2.1.1
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
||||
*/
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
display: table;
|
||||
content: "";
|
||||
line-height: 0;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
.hide-text {
|
||||
font: 0/0 a;
|
||||
color: transparent;
|
||||
text-shadow: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
.input-block-level {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.tooltip {
|
||||
position: absolute;
|
||||
z-index: 1030;
|
||||
display: block;
|
||||
visibility: visible;
|
||||
padding: 5px;
|
||||
font-size: 11px;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
}
|
||||
.tooltip.in {
|
||||
opacity: 0.8;
|
||||
filter: alpha(opacity=80);
|
||||
}
|
||||
.tooltip.top {
|
||||
margin-top: -3px;
|
||||
}
|
||||
.tooltip.right {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.tooltip.bottom {
|
||||
margin-top: 3px;
|
||||
}
|
||||
.tooltip.left {
|
||||
margin-left: -3px;
|
||||
}
|
||||
.tooltip-inner {
|
||||
max-width: 200px;
|
||||
padding: 3px 8px;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
background-color: #000000;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.tooltip-arrow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
}
|
||||
.tooltip.top .tooltip-arrow {
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px 5px 0;
|
||||
border-top-color: #000000;
|
||||
}
|
||||
.tooltip.right .tooltip-arrow {
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -5px;
|
||||
border-width: 5px 5px 5px 0;
|
||||
border-right-color: #000000;
|
||||
}
|
||||
.tooltip.left .tooltip-arrow {
|
||||
top: 50%;
|
||||
right: 0;
|
||||
margin-top: -5px;
|
||||
border-width: 5px 0 5px 5px;
|
||||
border-left-color: #000000;
|
||||
}
|
||||
.tooltip.bottom .tooltip-arrow {
|
||||
top: 0;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 0 5px 5px;
|
||||
border-bottom-color: #000000;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
line-height: 20px;
|
||||
}
|
1
preview/css/bootstrap/readme.txt
Normal file
@ -0,0 +1 @@
|
||||
Bootstrap custom build containing only the tooltip component
|
69
preview/css/forms.css
Normal file
@ -0,0 +1,69 @@
|
||||
.textfield {
|
||||
background : black;
|
||||
border : 1px solid #888;
|
||||
border-radius : 2px;
|
||||
padding : 3px 10px;
|
||||
color : white;
|
||||
}
|
||||
|
||||
.textfield[disabled=disabled] {
|
||||
background : #3a3a3a;
|
||||
}
|
||||
|
||||
.textfield-small {
|
||||
width : 50px;
|
||||
}
|
||||
|
||||
.button {
|
||||
height: 24px;
|
||||
box-sizing: border-box;
|
||||
|
||||
background-color: #3f3f3f;
|
||||
border: 1px solid #333;
|
||||
border-top-color: #666;
|
||||
border-bottom-color: #222;
|
||||
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
color: white;
|
||||
text-shadow: 0px -1px 0 black;
|
||||
font-weight: bold;
|
||||
font-size: 1rem;
|
||||
text-align: center;
|
||||
|
||||
transition: background-color 0.2s linear;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
text-decoration: none;
|
||||
background-color: #484848;
|
||||
color: gold;
|
||||
}
|
||||
|
||||
.button-primary {
|
||||
background-color: rgb(255,215,0); /* gold */
|
||||
|
||||
border-color: rgb(179, 164, 0);
|
||||
border-top-color: white;
|
||||
border-bottom-color: rgb(151, 133, 0);
|
||||
|
||||
color: black;
|
||||
text-shadow: 0px 1px 0 #fff;
|
||||
}
|
||||
|
||||
.button-primary:hover {
|
||||
background-color: rgb(255,235,20);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.button[disabled=disabled],
|
||||
.button[disabled=disabled]:hover {
|
||||
cursor:default;
|
||||
background-color: #aaa;
|
||||
color: #777;
|
||||
text-shadow: 0px 1px 0 #bbb;
|
||||
border-color: #666;
|
||||
border-top-color: #999;
|
||||
border-bottom-color: #555;
|
||||
}
|
185
preview/css/preview-film-section.css
Normal file
@ -0,0 +1,185 @@
|
||||
.preview-list-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.preview-list-scroller {
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.top-overflow,
|
||||
.bottom-overflow {
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 12px;
|
||||
|
||||
-webkit-transition: all 500ms ease-out;
|
||||
-moz-transition: all 500ms ease-out;
|
||||
-ms-transition: all 500ms ease-out;
|
||||
-o-transition: all 500ms ease-out;
|
||||
transition: all 500ms ease-out;
|
||||
|
||||
background-image: linear-gradient(45deg, rgba(0,0,0, 0.8) 25%, transparent 25%, transparent 75%, rgba(0,0,0, 0.8) 75%, rgba(0,0,0, 0.8)),
|
||||
linear-gradient(-45deg, rgba(0,0,0, 0.8) 25%, transparent 25%, transparent 75%, rgba(0,0,0, 0.8) 75%, rgba(0,0,0, 0.8));
|
||||
background-size: 29px 45px;
|
||||
background-repeat: repeat-x;
|
||||
background-position-x: 3px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.top-overflow {
|
||||
top: -20px;
|
||||
}
|
||||
|
||||
.bottom-overflow {
|
||||
bottom: -20px;
|
||||
background-position-x: 0;
|
||||
background-position-y: -23px;
|
||||
}
|
||||
|
||||
.top-overflow-visible .top-overflow {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.bottom-overflow-visible .bottom-overflow {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.preview-list {
|
||||
list-style-type: none;
|
||||
padding-right: 7px;
|
||||
}
|
||||
|
||||
.add-frame-action {
|
||||
border: #888 solid 4px;
|
||||
font-size: 13px;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
padding: 6px 0;
|
||||
border-radius: 4px;
|
||||
margin-top: 8px;
|
||||
background-image: url(../img/plus.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 3px 7px;
|
||||
background-size: 26px 26px;
|
||||
text-indent: 18px;
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
.add-frame-action .label {
|
||||
width: 80px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.add-frame-action:hover {
|
||||
border-color: gold;
|
||||
}
|
||||
|
||||
.preview-tile {
|
||||
position: relative;
|
||||
border: #444 3px solid;
|
||||
border-radius: 3px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.preview-tile:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.preview-tile:hover {
|
||||
border: #999 3px solid;
|
||||
}
|
||||
|
||||
.preview-tile .tile-overlay {
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
background-color: rgba(100, 100, 100, 0.6);
|
||||
opacity: 0;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.preview-tile:hover .tile-overlay {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.preview-tile .tile-overlay.tile-count {
|
||||
display: block;
|
||||
opacity: 1.0;
|
||||
border-bottom-right-radius: 3px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.preview-tile .tile-overlay.delete-frame-action {
|
||||
background-image: url(../img/garbage.png);
|
||||
background-repeat: no-repeat;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border-bottom-left-radius: 3px;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background-position: 5px 5px;
|
||||
background-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.preview-tile .tile-overlay.duplicate-frame-action {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border-bottom-left-radius: 3px;
|
||||
background-image: url(../img/duplicate.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 5px 5px;
|
||||
background-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.preview-tile .tile-overlay.dnd-action {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-top-right-radius: 3px;
|
||||
background-image: url(../img/dragndrop.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 5px 5px;
|
||||
background-size: 20px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.preview-tile.selected {
|
||||
border-color: gold;
|
||||
}
|
||||
|
||||
.preview-tile.selected:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 38px;
|
||||
right: -15px;
|
||||
border: transparent 4px solid;
|
||||
border-left-color: gold;
|
||||
border-width: 6px;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Drag n drop styles.
|
||||
*/
|
||||
|
||||
.preview-tile-drop-proxy {
|
||||
border: 3px dashed gold;
|
||||
height: 90px;
|
||||
border-radius: 9px;
|
||||
background-color: rgba(255, 215,0, 0.2);
|
||||
}
|
36
preview/css/reset.css
Normal file
@ -0,0 +1,36 @@
|
||||
html, body {
|
||||
height : 100%; width: 100%;
|
||||
margin : 0;
|
||||
overflow: hidden;
|
||||
cursor : default;
|
||||
font-family: arial;
|
||||
font-size: 11px;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
ul, li {
|
||||
margin : 0;
|
||||
padding : 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
|
||||
/* Force apparition of scrollbars on leopard */
|
||||
::-webkit-scrollbar {
|
||||
-webkit-appearance: none;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 2px;
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: rgba(50, 50, 50, 0.4);
|
||||
}
|
167
preview/css/settings.css
Normal file
@ -0,0 +1,167 @@
|
||||
|
||||
/** Righty sticky drawer expanded state. */
|
||||
|
||||
.right-sticky-section.sticky-section {
|
||||
right: 0;
|
||||
width: 47px;
|
||||
|
||||
-webkit-transition: all 200ms ease-out;
|
||||
-moz-transition: all 200ms ease-out;
|
||||
-ms-transition: all 200ms ease-out;
|
||||
transition: all 200ms ease-out;
|
||||
}
|
||||
|
||||
.right-sticky-section.expanded {
|
||||
right: 280px;
|
||||
}
|
||||
|
||||
.right-sticky-section .tool-icon {
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.drawer-content {
|
||||
overflow: hidden;
|
||||
background-color: #444;
|
||||
height: 550px;
|
||||
max-height: 100%;
|
||||
width: 280px;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.right-sticky-section.expanded .tool-icon {
|
||||
padding-right: 1px;
|
||||
}
|
||||
|
||||
.right-sticky-section .tool-icon.has-expanded-drawer {
|
||||
position: relative;
|
||||
background-color: #444;
|
||||
margin-right: 0;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
margin: 10px 20px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #ccc;
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
|
||||
.settings-title {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px #aaa solid;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.settings-item {}
|
||||
|
||||
.background-picker-wrapper {
|
||||
overflow: hidden;
|
||||
padding: 10px 5px 20px 5px;
|
||||
}
|
||||
|
||||
.background-picker {
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
height: 35px;
|
||||
width: 35px;
|
||||
background-color: transparent;
|
||||
margin-right: 15px;
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.background-picker:after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
bottom: -2px;
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
.background-picker:hover:after {
|
||||
border: #eee 1px solid;
|
||||
}
|
||||
|
||||
.background-picker.selected:after {
|
||||
border: gold 1px solid;
|
||||
}
|
||||
|
||||
/* Gif Export Setting panel*/
|
||||
.gif-upload-button,
|
||||
.gif-render-button {
|
||||
/*float : right;*/
|
||||
margin-top : 10px;
|
||||
margin-right : 10px;
|
||||
}
|
||||
|
||||
.gif-export-radio-group {
|
||||
margin:10px 0;
|
||||
}
|
||||
|
||||
.gif-export-preview {
|
||||
margin-top:20px;
|
||||
max-width:240px;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.preview-upload-ongoing:before{
|
||||
content: "Upload ongoing ...";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-top: 45%;
|
||||
box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Import panel */
|
||||
.import-section {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.import-section-disabled {
|
||||
color : #888;
|
||||
}
|
||||
|
||||
.import-section-preview {
|
||||
display : inline-block;
|
||||
height : 60px;
|
||||
width: 60px;
|
||||
border : 1px dashed #999;
|
||||
border-radius: 3px;
|
||||
margin-left : 10px;
|
||||
}
|
||||
|
||||
.import-resize-field {
|
||||
width: 30px;
|
||||
margin: 0px 8px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.file-input-button {
|
||||
margin: 0px 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.file-input-status {
|
||||
display: inline-block;
|
||||
width: 130px;
|
||||
overflow: hidden;
|
||||
|
||||
height: 1.5rem;
|
||||
word-break : break-all;
|
||||
vertical-align: middle;
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
text-shadow: none;
|
||||
}
|
294
preview/css/style.css
Normal file
@ -0,0 +1,294 @@
|
||||
|
||||
|
||||
body {
|
||||
background: radial-gradient(circle, #000, #373737);
|
||||
/* 16/06/2013 : -webkit still needed for
|
||||
safari, safari mobile and android browser and chrome for android
|
||||
cf http://caniuse.com/css-gradients */
|
||||
background: -webkit-radial-gradient(circle, #000, #373737);
|
||||
}
|
||||
|
||||
/**
|
||||
* Application layout
|
||||
*/
|
||||
|
||||
.main-wrapper {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 0;
|
||||
bottom: 5px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.column-wrapper {
|
||||
text-align: center;
|
||||
font-size: 0;
|
||||
position: absolute;
|
||||
left: 100px; /* Reserve room for tools on the left edge of the screen. */
|
||||
top: 0;
|
||||
right: 50px; /* Reserve room for actions on the right edge of the screen. */
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.piskel-name-container {
|
||||
overflow:hidden;
|
||||
position:fixed;
|
||||
top:10px;
|
||||
left:10px;
|
||||
color:white;
|
||||
font-family:Tahoma;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.piskel-name-container #piskel-name {
|
||||
border :none;
|
||||
color : lightgrey;
|
||||
background: transparent;
|
||||
font-size:16pt;
|
||||
|
||||
}
|
||||
|
||||
.column {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.left-column {
|
||||
vertical-align: top;
|
||||
height: 100%;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
.main-column {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.right-column {
|
||||
vertical-align: top;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.drawing-canvas-container {
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.sticky-section {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.sticky-section .sticky-section-wrap {
|
||||
display: table;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sticky-section .vertical-centerer {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.left-sticky-section.sticky-section {
|
||||
left: 0;
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.left-sticky-section .tool-icon {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canvases layout
|
||||
*/
|
||||
|
||||
.canvas {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.canvas-container {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.canvas-container .canvas-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.light-picker-background,
|
||||
.light-canvas-background .canvas-background {
|
||||
background: url(../img/canvas_background/light_canvas_background.png) repeat;
|
||||
}
|
||||
|
||||
.medium-picker-background,
|
||||
.medium-canvas-background .canvas-background {
|
||||
background: url(../img/canvas_background/medium_canvas_background.png) repeat;
|
||||
}
|
||||
|
||||
.lowcont-medium-picker-background,
|
||||
.lowcont-medium-canvas-background .canvas-background {
|
||||
background: url(../img/canvas_background/lowcont_medium_canvas_background.png) repeat;
|
||||
}
|
||||
|
||||
.lowcont-dark-picker-background,
|
||||
.lowcont-dark-canvas-background .canvas-background {
|
||||
background: url(../img/canvas_background/lowcont_dark_canvas_background.png) repeat;
|
||||
}
|
||||
|
||||
.layers-canvas {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.canvas.canvas-overlay,
|
||||
.canvas.layers-canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Z-indexes should match the drawing area canvas superposition order :
|
||||
* - 1 : draw layers below current layer
|
||||
* - 2 : draw current layer
|
||||
* - 3 : draw layers above current layer
|
||||
* - 4 : draw the tools overlay
|
||||
*/
|
||||
.canvas.layers-below-canvas {z-index: 7;}
|
||||
.canvas.drawing-canvas {z-index: 8;}
|
||||
.canvas.layers-above-canvas {z-index: 9;}
|
||||
.canvas.canvas-overlay {z-index: 10;}
|
||||
|
||||
/**
|
||||
* Animated preview styles.
|
||||
*/
|
||||
|
||||
.preview-container {
|
||||
border : 0px Solid black;
|
||||
border-radius:5px 0px 0px 5px;
|
||||
box-shadow : 0px 0px 2px rgba(0,0,0,0.2);
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.preview-container canvas {
|
||||
border : 0px Solid transparent;
|
||||
}
|
||||
|
||||
.display-fps {
|
||||
float: left;
|
||||
color: #aaa;
|
||||
font-size: 12px;
|
||||
min-width: 55px;
|
||||
vertical-align: bottom;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.range-fps {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layers container
|
||||
*/
|
||||
.layers-list-container {
|
||||
border: 4px solid #888;
|
||||
font-size: medium;
|
||||
color: white;
|
||||
text-align: left;
|
||||
border-radius: 4px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.layers-title {
|
||||
padding: 8px;
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
background: #222;
|
||||
background-image: url('../img/layers.svg');
|
||||
background-size: 22px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 97%;
|
||||
}
|
||||
|
||||
.layers-list {
|
||||
font-size : 12px;
|
||||
}
|
||||
|
||||
.layer-item {
|
||||
height:24px;
|
||||
line-height: 24px;
|
||||
padding : 0 10px;
|
||||
border-top: 1px solid #444;
|
||||
cursor : pointer;
|
||||
}
|
||||
|
||||
.layer-item:hover {
|
||||
background : #222;
|
||||
}
|
||||
|
||||
.current-layer-item,
|
||||
.current-layer-item:hover {
|
||||
background : #333;
|
||||
color: gold;
|
||||
}
|
||||
|
||||
.layers-button-container {
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
.layers-button-arrow {
|
||||
font-family : 'Lucida Grande', Calibri;
|
||||
padding : 2px 6px 0 6px;
|
||||
}
|
||||
|
||||
.layers-button {
|
||||
margin: 0;
|
||||
width: 25%;
|
||||
float : left;
|
||||
}
|
||||
|
||||
/* @override */
|
||||
.button.layers-button {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.layers-button:last-child {
|
||||
border-right-width: 0;
|
||||
}
|
||||
/**
|
||||
* User messages
|
||||
*/
|
||||
.user-message {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #F9EDBE;
|
||||
padding: 10px 47px;
|
||||
border-top-left-radius: 7px;
|
||||
color: #222;
|
||||
border: #F0C36D 1px solid;
|
||||
border-right: 0;
|
||||
border-bottom: 0;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
z-index: 10000;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.user-message .close {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 17px;
|
||||
color: gray;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.user-message .close:hover {
|
||||
color: black;
|
||||
}
|
229
preview/css/tools.css
Normal file
@ -0,0 +1,229 @@
|
||||
|
||||
.tools-wrapper,
|
||||
.options-wrapper,
|
||||
.palette-wrapper {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.tool-icon {
|
||||
cursor : pointer;
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
margin: 1px;
|
||||
background-color: #3a3a3a;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 12px 12px;
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
.tool-icon.selected {
|
||||
cursor: default;
|
||||
background-color: #444;
|
||||
border: 1px gold solid;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tool-icon:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tool icons:
|
||||
*/
|
||||
.tool-icon.tool-pen {
|
||||
background-image: url(../img/tools/pen.png);
|
||||
}
|
||||
|
||||
.tool-icon.tool-vertical-mirror-pen {
|
||||
background-image: url(../img/tools/mirror.png);
|
||||
background-position: 0px 10px;
|
||||
background-size: 38px 27px;
|
||||
}
|
||||
|
||||
.tool-icon.tool-paint-bucket {
|
||||
background-image: url(../img/tools/paintbucket.png);
|
||||
}
|
||||
|
||||
.tool-icon.tool-eraser {
|
||||
background-image: url(../img/tools/eraser.png);
|
||||
}
|
||||
|
||||
.tool-icon.tool-stroke {
|
||||
background-image: url(../img/tools/stroke.png);
|
||||
}
|
||||
|
||||
.tool-icon.tool-rectangle {
|
||||
background-image: url(../img/tools/rectangle.png);
|
||||
background-position: 12px 14px;
|
||||
background-size: 24px 20px;
|
||||
}
|
||||
|
||||
.tool-icon.tool-circle {
|
||||
background-image: url(../img/tools/circle.png);
|
||||
}
|
||||
|
||||
.tool-icon.tool-move {
|
||||
background-image: url(../img/tools/hand.png);
|
||||
background-position: 12px 12px;
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
.tool-icon.tool-rectangle-select {
|
||||
background-image: url(../img/tools/rectangle_selection.png);
|
||||
background-position: 12px 14px;
|
||||
background-size: 24px 20px;
|
||||
}
|
||||
|
||||
.tool-icon.tool-shape-select {
|
||||
background-image: url(../img/tools/magicwand.png);
|
||||
}
|
||||
|
||||
.tool-icon.tool-colorpicker {
|
||||
background-image: url(../img/tools/eyedropper.png);
|
||||
background-position: 12px 12px;
|
||||
background-size: 23px 23px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tool cursors:
|
||||
*/
|
||||
|
||||
.tool-paint-bucket .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/paint-bucket.png) 12 12, pointer;
|
||||
}
|
||||
|
||||
.tool-vertical-mirror-pen .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/vertical-mirror-pen.png) 5 15, pointer;
|
||||
}
|
||||
|
||||
.tool-pen .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/pen.png) 0 15, pointer;
|
||||
}
|
||||
|
||||
.tool-eraser .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/eraser.png) 0 15, pointer;
|
||||
}
|
||||
|
||||
.tool-stroke .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/pen.png) 0 15, pointer;
|
||||
}
|
||||
|
||||
.tool-rectangle .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/rectangle.png) 0 15, pointer;
|
||||
}
|
||||
|
||||
.tool-circle .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/circle.png) 2 15, pointer;
|
||||
}
|
||||
|
||||
.tool-move .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/hand.png) 15 15, pointer;
|
||||
}
|
||||
|
||||
.tool-rectangle-select .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/select.png) 15 15, pointer;
|
||||
}
|
||||
|
||||
.tool-shape-select .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/wand.png) 15 15, pointer;
|
||||
}
|
||||
|
||||
.tool-colorpicker .drawing-canvas-container:hover {
|
||||
cursor: url(../img/icons/dropper.png) 0 15, pointer;
|
||||
}
|
||||
|
||||
.tool-color-picker input {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
text-indent: -10000px;
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
position : relative;
|
||||
top: 10px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.tool-color-picker .secondary-color-picker {
|
||||
top : 18px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
.palette-color[data-color=TRANSPARENT] {
|
||||
position: relative;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
background-color: white;
|
||||
height : 16px;
|
||||
width : 16px;
|
||||
border: 2px solid #000;
|
||||
background-size: 16px 16px;
|
||||
background-position: 0 0;
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
right bottom,
|
||||
color-stop(0, #fff),
|
||||
color-stop(0.45, #fff),
|
||||
color-stop(0.5, #ff0000),
|
||||
color-stop(0.55, #fff),
|
||||
color-stop(1, #fff)
|
||||
);
|
||||
background-image: -moz-linear-gradient(
|
||||
left top,
|
||||
#fff 0%,
|
||||
#fff 45%,
|
||||
#f00 50%,
|
||||
#fff 55%,
|
||||
#fff 100%
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Framesheet level actions:
|
||||
*/
|
||||
|
||||
.tool-icon.gallery-icon {
|
||||
background-image: url(../img/gallery.png);
|
||||
background-position: 3px 3px;
|
||||
background-size: 39px 39px;
|
||||
}
|
||||
|
||||
.tool-icon.save-icon {
|
||||
background-image: url(../img/save.png);
|
||||
background-position: 6px 6px;
|
||||
background-size: 36px 36px;
|
||||
}
|
||||
|
||||
.tool-icon.gear-icon {
|
||||
background-image: url(../img/gear.png);
|
||||
background-position: 6px 7px;
|
||||
background-size: 32px 32px;
|
||||
}
|
||||
|
||||
.tool-icon.upload-cloud-icon {
|
||||
background-image: url(../img/cloud_export.png);
|
||||
background-position: 4px 0px;
|
||||
background-size: 36px 36px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tool-icon.import-icon {
|
||||
background-image: url(../img/import-icon.png);
|
||||
background-position: 10px 5px;
|
||||
background-size: 26px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.upload-cloud-icon .label {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 4px;
|
||||
right: 0;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
BIN
preview/img/canvas_background/light_canvas_background.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
preview/img/canvas_background/lowcont_dark_canvas_background.png
Normal file
After Width: | Height: | Size: 431 B |
After Width: | Height: | Size: 278 B |
BIN
preview/img/canvas_background/medium_canvas_background.png
Normal file
After Width: | Height: | Size: 418 B |
BIN
preview/img/cloud_export.png
Normal file
After Width: | Height: | Size: 594 B |
BIN
preview/img/dragndrop.png
Normal file
After Width: | Height: | Size: 532 B |
BIN
preview/img/duplicate.png
Normal file
After Width: | Height: | Size: 634 B |
BIN
preview/img/gallery.png
Normal file
After Width: | Height: | Size: 305 B |
BIN
preview/img/garbage.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
preview/img/gear.png
Normal file
After Width: | Height: | Size: 789 B |
BIN
preview/img/icons/circle.png
Normal file
After Width: | Height: | Size: 761 B |
BIN
preview/img/icons/color-palette.png
Normal file
After Width: | Height: | Size: 209 B |
BIN
preview/img/icons/dropper.png
Normal file
After Width: | Height: | Size: 543 B |
BIN
preview/img/icons/eraser.png
Normal file
After Width: | Height: | Size: 656 B |
BIN
preview/img/icons/hand.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
preview/img/icons/mirror-pen.png
Normal file
After Width: | Height: | Size: 557 B |
BIN
preview/img/icons/paint-bucket.png
Normal file
After Width: | Height: | Size: 707 B |
BIN
preview/img/icons/pen.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
preview/img/icons/rectangle.png
Normal file
After Width: | Height: | Size: 660 B |
BIN
preview/img/icons/select.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
preview/img/icons/stroke.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
preview/img/icons/vertical-mirror-pen.png
Normal file
After Width: | Height: | Size: 603 B |
BIN
preview/img/icons/wand.png
Normal file
After Width: | Height: | Size: 570 B |
BIN
preview/img/import-icon.png
Normal file
After Width: | Height: | Size: 720 B |
62
preview/img/layers.svg
Normal file
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="90"
|
||||
height="87.886002"
|
||||
id="svg3024">
|
||||
<defs
|
||||
id="defs3026" />
|
||||
<metadata
|
||||
id="metadata3029">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-266.63206,-597.79217)"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="translate(262.14286,465.21932)"
|
||||
id="Captions" />
|
||||
<g
|
||||
id="g3825" />
|
||||
<g
|
||||
transform="translate(-0.51079959,126.51585)"
|
||||
id="layer1-9"
|
||||
style="fill:#ffffff;fill-opacity:1">
|
||||
<g
|
||||
transform="translate(262.14286,465.21932)"
|
||||
id="Captions-4"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
<g
|
||||
id="g3825-8"
|
||||
style="fill:#ffffff;fill-opacity:1">
|
||||
<path
|
||||
d="m 357.14286,556.72132 c 0,1.346 -1.097,2.441 -2.442,2.441 h -60.239 c -1.347,0 -2.441,-1.096 -2.441,-2.441 v -4.555 h 50.241 c 4.346,0 7.884,-3.539 7.884,-7.885 v -48.128 h 4.555 c 1.346,0 2.442,1.096 2.442,2.441 v 58.127 z"
|
||||
id="path2989-8"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
<path
|
||||
d="m 279.58086,544.28132 v -4.555 h 6.997 2.722 2.721 37.803 c 4.346,0 7.884,-3.537 7.884,-7.883 v -35.69 -2.721 -2.721 -6.998 h 4.555 c 1.346,0 2.442,1.096 2.442,2.443 v 4.555 2.721 2.721 48.129 c 0,1.346 -1.097,2.443 -2.442,2.443 h -50.242 -2.721 -2.722 -4.555 c -1.347,0 -2.442,-1.098 -2.442,-2.444 z"
|
||||
id="path2991-2"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
<path
|
||||
d="m 329.82386,471.27632 h -60.239 c -1.347,0 -2.442,1.093 -2.442,2.441 v 58.127 c 0,1.344 1.095,2.441 2.442,2.441 h 4.555 2.721 2.721 6.997 2.722 2.721 37.803 c 1.345,0 2.441,-1.098 2.441,-2.441 v -35.691 -2.721 -2.721 -6.998 -2.721 -2.721 -4.554 c -10e-4,-1.348 -1.098,-2.441 -2.442,-2.441 z"
|
||||
id="path2993-4"
|
||||
style="fill:#ffffff;fill-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
BIN
preview/img/plus.png
Normal file
After Width: | Height: | Size: 271 B |
BIN
preview/img/save.png
Normal file
After Width: | Height: | Size: 395 B |
BIN
preview/img/tools/circle-dark.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
preview/img/tools/circle.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
preview/img/tools/eraser-dark.png
Normal file
After Width: | Height: | Size: 909 B |
BIN
preview/img/tools/eraser.png
Normal file
After Width: | Height: | Size: 1010 B |
BIN
preview/img/tools/eyedropper-dark.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
preview/img/tools/eyedropper.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
preview/img/tools/hand-dark.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
preview/img/tools/hand.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
preview/img/tools/magicwand-dark.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
preview/img/tools/magicwand.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
preview/img/tools/mirror.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
preview/img/tools/paintbucket-dark.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
preview/img/tools/paintbucket.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
preview/img/tools/pen-dark.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
preview/img/tools/pen.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
preview/img/tools/rectangle-dark.png
Normal file
After Width: | Height: | Size: 253 B |
BIN
preview/img/tools/rectangle.png
Normal file
After Width: | Height: | Size: 245 B |
BIN
preview/img/tools/rectangle_selection-dark.png
Normal file
After Width: | Height: | Size: 376 B |
BIN
preview/img/tools/rectangle_selection.png
Normal file
After Width: | Height: | Size: 372 B |
BIN
preview/img/tools/stroke.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
61
preview/index.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Piskel</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Julian Descottes">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" type="text/css" href="css/reset.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/style.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/forms.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/settings.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/tools.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap-tooltip-custom.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/preview-film-section.css">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="js/lib/iframeLoader.js"></script>
|
||||
<div class="piskel-name-container">
|
||||
<input readonly id="piskel-name" type="text" value=""/>
|
||||
</div>
|
||||
<div id="main-wrapper" class="main-wrapper">
|
||||
<iframe src="templates/drawing-tools.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
|
||||
|
||||
<div id="column-wrapper" class="column-wrapper">
|
||||
<div class='column left-column'>
|
||||
<iframe src="templates/frames-list.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
|
||||
</div>
|
||||
|
||||
<div class='column main-column'>
|
||||
<div id="drawing-canvas-container" class="drawing-canvas-container canvas-container">
|
||||
<div class="canvas-background"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column right-column">
|
||||
<iframe src="templates/preview.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
|
||||
<iframe src="templates/layers-list.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="application-action-section" data-pskl-controller="settings" class="sticky-section right-sticky-section">
|
||||
<div class="sticky-section-wrap">
|
||||
<iframe src="templates/settings.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
|
||||
<div class="drawer vertical-centerer">
|
||||
<div class="drawer-content" id="drawer-container">
|
||||
<iframe src="templates/settings/application.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
|
||||
<iframe src="templates/settings/export-gif.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
|
||||
<iframe src="templates/settings/import.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="piskel-boot.js"></script>
|
||||
</body>
|
||||
</html>
|
52
preview/js/Constants.js
Normal file
@ -0,0 +1,52 @@
|
||||
// TODO(grosbouddha): put under pskl namespace.
|
||||
var Constants = {
|
||||
DEFAULT : {
|
||||
HEIGHT : 32,
|
||||
WIDTH : 32,
|
||||
FPS : 12
|
||||
},
|
||||
|
||||
MODEL_VERSION : 1,
|
||||
|
||||
MAX_HEIGHT : 128,
|
||||
MAX_WIDTH : 128,
|
||||
|
||||
PREVIEW_FILM_SIZE : 120,
|
||||
|
||||
DEFAULT_PEN_COLOR : '#000000',
|
||||
TRANSPARENT_COLOR : 'TRANSPARENT',
|
||||
|
||||
/*
|
||||
* Fake semi-transparent color used to highlight transparent
|
||||
* strokes and rectangles:
|
||||
*/
|
||||
SELECTION_TRANSPARENT_COLOR: 'rgba(255, 255, 255, 0.6)',
|
||||
|
||||
/*
|
||||
* When a tool is hovering the drawing canvas, we highlight the eventual
|
||||
* pixel target with this color:
|
||||
*/
|
||||
TOOL_TARGET_HIGHLIGHT_COLOR: 'rgba(255, 255, 255, 0.2)',
|
||||
|
||||
/*
|
||||
* Default entry point for piskel web service:
|
||||
*/
|
||||
STATIC : {
|
||||
URL : {
|
||||
SAVE : 'http://3.piskel-app.appspot.com/store',
|
||||
GET : 'http://3.piskel-app.appspot.com/get'
|
||||
}
|
||||
},
|
||||
APPENGINE : {
|
||||
URL : {
|
||||
SAVE : 'save'
|
||||
}
|
||||
},
|
||||
IMAGE_SERVICE_UPLOAD_URL : 'http://screenletstore.appspot.com/__/upload',
|
||||
IMAGE_SERVICE_GET_URL : 'http://screenletstore.appspot.com/img/',
|
||||
|
||||
GRID_STROKE_WIDTH: 1,
|
||||
|
||||
LEFT_BUTTON : 'left_button_1',
|
||||
RIGHT_BUTTON : 'right_button_2'
|
||||
};
|
67
preview/js/Events.js
Normal file
@ -0,0 +1,67 @@
|
||||
// TODO(grosbouddha): put under pskl namespace.
|
||||
var Events = {
|
||||
|
||||
TOOL_SELECTED : "TOOL_SELECTED",
|
||||
TOOL_RELEASED : "TOOL_RELEASED",
|
||||
PRIMARY_COLOR_SELECTED: "PRIMARY_COLOR_SELECTED",
|
||||
PRIMARY_COLOR_UPDATED: "PRIMARY_COLOR_UPDATED",
|
||||
SECONDARY_COLOR_SELECTED: "SECONDARY_COLOR_SELECTED",
|
||||
SECONDARY_COLOR_UPDATED: "SECONDARY_COLOR_UPDATED",
|
||||
|
||||
/**
|
||||
* When this event is emitted, a request is sent to the localstorage
|
||||
* Service to save the current framesheet. The storage service
|
||||
* may not immediately store data (internal throttling of requests).
|
||||
*/
|
||||
LOCALSTORAGE_REQUEST: "LOCALSTORAGE_REQUEST",
|
||||
|
||||
CANVAS_RIGHT_CLICKED: "CANVAS_RIGHT_CLICKED",
|
||||
|
||||
/**
|
||||
* Event to request a refresh of the display.
|
||||
* A bit overkill but, it's just workaround in our current drawing system.
|
||||
* TODO: Remove or rework when redraw system is refactored.
|
||||
*/
|
||||
REFRESH: "REFRESH",
|
||||
|
||||
/**
|
||||
* Temporary event to bind the redraw of right preview film to the canvas.
|
||||
* This redraw should be driven by model updates.
|
||||
* TODO(vincz): Remove.
|
||||
*/
|
||||
REDRAW_PREVIEWFILM: "REDRAW_PREVIEWFILM",
|
||||
|
||||
/**
|
||||
* Fired each time a user setting change.
|
||||
* The payload will be:
|
||||
* 1st argument: Name of the settings
|
||||
* 2nd argument: New value
|
||||
*/
|
||||
USER_SETTINGS_CHANGED: "USER_SETTINGS_CHANGED",
|
||||
|
||||
/* Listened to by SettingsController */
|
||||
CLOSE_SETTINGS_DRAWER : "CLOSE_SETTINGS_DRAWER",
|
||||
|
||||
/**
|
||||
* The framesheet was reseted and is now probably drastically different.
|
||||
* Number of frames, content of frames, color used for the palette may have changed.
|
||||
*/
|
||||
PISKEL_RESET: "PISKEL_RESET",
|
||||
|
||||
FRAME_SIZE_CHANGED : "FRAME_SIZE_CHANGED",
|
||||
|
||||
CURRENT_FRAME_SET: "CURRENT_FRAME_SET",
|
||||
|
||||
SELECTION_CREATED: "SELECTION_CREATED",
|
||||
SELECTION_MOVE_REQUEST: "SELECTION_MOVE_REQUEST",
|
||||
SELECTION_DISMISSED: "SELECTION_DISMISSED",
|
||||
|
||||
SHOW_NOTIFICATION: "SHOW_NOTIFICATION",
|
||||
HIDE_NOTIFICATION: "HIDE_NOTIFICATION",
|
||||
|
||||
UNDO: "UNDO",
|
||||
REDO: "REDO",
|
||||
CUT: "CUT",
|
||||
COPY: "COPY",
|
||||
PASTE: "PASTE"
|
||||
};
|
262
preview/js/app.js
Normal file
@ -0,0 +1,262 @@
|
||||
/**
|
||||
* @require Constants
|
||||
* @require Events
|
||||
*/
|
||||
(function () {
|
||||
var ns = $.namespace("pskl");
|
||||
/**
|
||||
* Main application controller
|
||||
*/
|
||||
ns.app = {
|
||||
|
||||
init : function () {
|
||||
var size = this.readSizeFromURL_();
|
||||
var piskel = new pskl.model.Piskel(size.width, size.height);
|
||||
|
||||
var layer = new pskl.model.Layer("Layer 1");
|
||||
var frame = new pskl.model.Frame(size.width, size.height);
|
||||
layer.addFrame(frame);
|
||||
|
||||
piskel.addLayer(layer);
|
||||
|
||||
this.piskelController = new pskl.controller.PiskelController(piskel);
|
||||
|
||||
this.drawingController = new pskl.controller.DrawingController(this.piskelController, $('#drawing-canvas-container'));
|
||||
this.drawingController.init();
|
||||
|
||||
this.animationController = new pskl.controller.AnimatedPreviewController(this.piskelController, $('#preview-canvas-container'));
|
||||
this.animationController.init();
|
||||
|
||||
this.previewsController = new pskl.controller.PreviewFilmController(this.piskelController, $('#preview-list'));
|
||||
this.previewsController.init();
|
||||
|
||||
this.layersListController = new pskl.controller.LayersListController(this.piskelController);
|
||||
this.layersListController.init();
|
||||
|
||||
this.settingsController = new pskl.controller.settings.SettingsController(this.piskelController);
|
||||
this.settingsController.init();
|
||||
|
||||
this.selectionManager = new pskl.selection.SelectionManager(this.piskelController);
|
||||
this.selectionManager.init();
|
||||
|
||||
this.historyService = new pskl.service.HistoryService(this.piskelController);
|
||||
this.historyService.init();
|
||||
|
||||
this.keyboardEventService = new pskl.service.KeyboardEventService();
|
||||
this.keyboardEventService.init();
|
||||
|
||||
this.notificationController = new pskl.controller.NotificationController();
|
||||
this.notificationController.init();
|
||||
|
||||
this.localStorageService = new pskl.service.LocalStorageService(this.piskelController);
|
||||
this.localStorageService.init();
|
||||
|
||||
this.imageUploadService = new pskl.service.ImageUploadService();
|
||||
this.imageUploadService.init();
|
||||
|
||||
this.toolController = new pskl.controller.ToolController();
|
||||
this.toolController.init();
|
||||
|
||||
this.paletteController = new pskl.controller.PaletteController();
|
||||
this.paletteController.init();
|
||||
|
||||
var drawingLoop = new pskl.rendering.DrawingLoop();
|
||||
drawingLoop.addCallback(this.render, this);
|
||||
drawingLoop.start();
|
||||
|
||||
this.initBootstrapTooltips_();
|
||||
|
||||
/**
|
||||
* True when piskel is running in static mode (no back end needed).
|
||||
* When started from APP Engine, appEngineToken_ (Boolean) should be set on window.pskl
|
||||
*/
|
||||
this.isStaticVersion = !pskl.appEngineToken_;
|
||||
|
||||
if (this.isStaticVersion) {
|
||||
this.finishInitStatic_();
|
||||
} else {
|
||||
this.finishInitAppEngine_();
|
||||
}
|
||||
},
|
||||
|
||||
finishInitStatic_ : function () {
|
||||
var framesheetId = this.readFramesheetIdFromURL_();
|
||||
if (framesheetId) {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{
|
||||
"content" : "Loading animation with id : [" + framesheetId + "]"
|
||||
}]);
|
||||
this.loadFramesheetFromService(framesheetId);
|
||||
} else {
|
||||
this.localStorageService.displayRestoreNotification();
|
||||
}
|
||||
},
|
||||
|
||||
finishInitAppEngine_ : function () {
|
||||
if (pskl.framesheetData_ && pskl.framesheetData_.content) {
|
||||
var piskel = pskl.utils.Serializer.createPiskel(pskl.framesheetData_.content);
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(pskl.framesheetData_.fps);
|
||||
}
|
||||
},
|
||||
|
||||
initBootstrapTooltips_ : function () {
|
||||
$('body').tooltip({
|
||||
selector: '[rel=tooltip]'
|
||||
});
|
||||
},
|
||||
|
||||
render : function (delta) {
|
||||
this.drawingController.render(delta);
|
||||
this.animationController.render(delta);
|
||||
this.previewsController.render(delta);
|
||||
},
|
||||
|
||||
readSizeFromURL_ : function () {
|
||||
var sizeParam = this.readUrlParameter_("size"),
|
||||
size;
|
||||
// parameter expected as size=64x48 => size=widthxheight
|
||||
var parts = sizeParam.split("x");
|
||||
if (parts && parts.length == 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
|
||||
var width = parseInt(parts[0], 10),
|
||||
height = parseInt(parts[1], 10);
|
||||
|
||||
size = {
|
||||
height : Math.min(height, Constants.MAX_HEIGHT),
|
||||
width : Math.min(width, Constants.MAX_WIDTH)
|
||||
};
|
||||
} else {
|
||||
size = {
|
||||
height : Constants.DEFAULT.HEIGHT,
|
||||
width : Constants.DEFAULT.WIDTH
|
||||
};
|
||||
}
|
||||
return size;
|
||||
},
|
||||
|
||||
readFramesheetIdFromURL_ : function () {
|
||||
return this.readUrlParameter_("frameId");
|
||||
},
|
||||
|
||||
readUrlParameter_ : function (paramName) {
|
||||
var searchString = window.location.search.substring(1),
|
||||
i, val, params = searchString.split("&");
|
||||
|
||||
for (i = 0; i < params.length; i++) {
|
||||
val = params[i].split("=");
|
||||
if (val[0] == paramName) {
|
||||
return window.unescape(val[1]);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
loadFramesheetFromService : function (frameId) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', Constants.STATIC.URL.GET + '?l=' + frameId, true);
|
||||
xhr.responseType = 'text';
|
||||
xhr.onload = function (e) {
|
||||
var res = JSON.parse(this.responseText);
|
||||
var piskel = pskl.utils.Serializer.createPiskel(res.framesheet);
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(res.fps);
|
||||
$.publish(Events.HIDE_NOTIFICATION);
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
$.publish(Events.HIDE_NOTIFICATION);
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
},
|
||||
|
||||
storeSheet : function (event) {
|
||||
if (this.isStaticVersion) {
|
||||
this.storeSheetStatic_();
|
||||
} else {
|
||||
this.storeSheetAppEngine_();
|
||||
}
|
||||
|
||||
if(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
storeSheetStatic_ : function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var formData = new FormData();
|
||||
formData.append('framesheet_content', this.piskelController.serialize());
|
||||
formData.append('fps_speed', $('#preview-fps').val());
|
||||
|
||||
xhr.open('POST', Constants.STATIC.URL.SAVE, true);
|
||||
|
||||
xhr.onload = function(e) {
|
||||
if (this.status == 200) {
|
||||
var baseUrl = window.location.href.replace(window.location.search, "");
|
||||
window.location.href = baseUrl + "?frameId=" + this.responseText;
|
||||
} else {
|
||||
this.onerror(e);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function(e) {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+this.status+")"}]);
|
||||
};
|
||||
xhr.send(formData);
|
||||
},
|
||||
|
||||
storeSheetAppEngine_ : function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
var formData = new FormData();
|
||||
formData.append('framesheet_content', this.piskelController.serialize());
|
||||
formData.append('fps_speed', $('#preview-fps').val());
|
||||
formData.append('name', $('#piskel-name').val());
|
||||
formData.append('frames', this.piskelController.getFrameCount());
|
||||
formData.append('preview', this.getFirstFrameAsPng());
|
||||
formData.append('framesheet', this.getFramesheetAsPng());
|
||||
|
||||
xhr.open('POST', Constants.APPENGINE.URL.SAVE, true);
|
||||
|
||||
xhr.onload = function(e) {
|
||||
if (this.status == 200) {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Successfully saved !"}]);
|
||||
} else {
|
||||
this.onerror(e);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function(e) {
|
||||
$.publish(Events.SHOW_NOTIFICATION, [{"content": "Saving failed ("+this.status+")"}]);
|
||||
};
|
||||
xhr.send(formData);
|
||||
},
|
||||
|
||||
getFirstFrameAsPng : function () {
|
||||
var firstFrame = this.piskelController.getFrameAt(0);
|
||||
var frameRenderer = new pskl.rendering.CanvasRenderer(firstFrame, 1);
|
||||
frameRenderer.drawTransparentAs('rgba(0,0,0,0)');
|
||||
var firstFrameCanvas = frameRenderer.render().canvas;
|
||||
return firstFrameCanvas.toDataURL("image/png");
|
||||
},
|
||||
|
||||
getFramesheetAsPng : function () {
|
||||
var renderer = new pskl.rendering.SpritesheetRenderer(this.piskelController);
|
||||
var framesheetCanvas = renderer.render();
|
||||
return framesheetCanvas.toDataURL("image/png");
|
||||
},
|
||||
|
||||
uploadAsSpritesheetPNG : function () {
|
||||
var imageData = this.getFramesheetAsPng();
|
||||
this.imageUploadService.upload(imageData, this.openWindow.bind(this));
|
||||
},
|
||||
|
||||
openWindow : function (url) {
|
||||
var options = [
|
||||
"dialog=yes", "scrollbars=no", "status=no",
|
||||
"width=" + this.piskelController.getWidth() * this.piskelController.getFrameCount(),
|
||||
"height=" + this.piskelController.getHeight()
|
||||
].join(",");
|
||||
|
||||
window.open(url, "piskel-export", options);
|
||||
}
|
||||
};
|
||||
})();
|
71
preview/js/controller/AnimatedPreviewController.js
Normal file
@ -0,0 +1,71 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.AnimatedPreviewController = function (piskelController, container, dpi) {
|
||||
this.piskelController = piskelController;
|
||||
this.container = container;
|
||||
|
||||
this.elapsedTime = 0;
|
||||
this.currentIndex = 0;
|
||||
|
||||
this.setFPS(Constants.DEFAULT.FPS);
|
||||
|
||||
var renderingOptions = {
|
||||
"dpi": this.calculateDPI_()
|
||||
};
|
||||
this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions);
|
||||
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, this.updateDPI_.bind(this));
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.init = function () {
|
||||
// the oninput event won't work on IE10 unfortunately, but at least will provide a
|
||||
// consistent behavior across all other browsers that support the input type range
|
||||
// see https://bugzilla.mozilla.org/show_bug.cgi?id=853670
|
||||
$("#preview-fps")[0].addEventListener('change', this.onFPSSliderChange.bind(this));
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.onFPSSliderChange = function (evt) {
|
||||
this.setFPS(parseInt($("#preview-fps")[0].value, 10));
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.setFPS = function (fps) {
|
||||
this.fps = fps;
|
||||
$("#preview-fps").val(this.fps);
|
||||
$("#display-fps").html(this.fps + " FPS");
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.getFPS = function () {
|
||||
return this.fps;
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.render = function (delta) {
|
||||
this.elapsedTime += delta;
|
||||
var index = Math.floor(this.elapsedTime / (1000/this.fps));
|
||||
if (index != this.currentIndex) {
|
||||
this.currentIndex = index;
|
||||
if (!this.piskelController.hasFrameAt(this.currentIndex)) {
|
||||
this.currentIndex = 0;
|
||||
this.elapsedTime = 0;
|
||||
}
|
||||
this.renderer.render(this.piskelController.getFrameAt(this.currentIndex));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the preview DPI depending on the framesheet size
|
||||
*/
|
||||
ns.AnimatedPreviewController.prototype.calculateDPI_ = function () {
|
||||
var previewSize = 200,
|
||||
framePixelHeight = this.piskelController.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.piskelController.getCurrentFrame().getWidth();
|
||||
// TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?)
|
||||
|
||||
//return pskl.PixelUtils.calculateDPIForContainer($(".preview-container"), framePixelHeight, framePixelWidth);
|
||||
return pskl.PixelUtils.calculateDPI(previewSize, previewSize, framePixelHeight, framePixelWidth);
|
||||
};
|
||||
|
||||
ns.AnimatedPreviewController.prototype.updateDPI_ = function () {
|
||||
this.dpi = this.calculateDPI_();
|
||||
this.renderer.setDPI(this.dpi);
|
||||
};
|
||||
})();
|
353
preview/js/controller/DrawingController.js
Normal file
@ -0,0 +1,353 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.DrawingController = function (piskelController, container) {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
this.piskelController = piskelController;
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(piskelController.getCurrentFrame());
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.container = container;
|
||||
|
||||
this.dpi = this.calculateDPI_();
|
||||
|
||||
// TODO(vincz): Store user prefs in a localstorage string ?
|
||||
var renderingOptions = {
|
||||
"dpi": this.dpi,
|
||||
"supportGridRendering" : true
|
||||
};
|
||||
|
||||
this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, ["canvas-overlay"]);
|
||||
this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, ["drawing-canvas"]);
|
||||
this.layersBelowRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, ["layers-canvas", "layers-below-canvas"]);
|
||||
this.layersAboveRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, ["layers-canvas", "layers-above-canvas"]);
|
||||
|
||||
|
||||
// State of drawing controller:
|
||||
this.isClicked = false;
|
||||
this.isRightClicked = false;
|
||||
this.previousMousemoveTime = 0;
|
||||
this.currentToolBehavior = null;
|
||||
this.primaryColor = Constants.DEFAULT_PEN_COLOR;
|
||||
this.secondaryColor = Constants.TRANSPARENT_COLOR;
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.init = function () {
|
||||
this.initMouseBehavior();
|
||||
|
||||
$.subscribe(Events.TOOL_SELECTED, $.proxy(function(evt, toolBehavior) {
|
||||
console.log("Tool selected: ", toolBehavior);
|
||||
this.currentToolBehavior = toolBehavior;
|
||||
this.overlayFrame.clear();
|
||||
}, this));
|
||||
|
||||
/**
|
||||
* TODO(grosbouddha): Primary/secondary color state are kept in this general controller.
|
||||
* Find a better place to store that. Perhaps PaletteController?
|
||||
*/
|
||||
$.subscribe(Events.PRIMARY_COLOR_SELECTED, $.proxy(function(evt, color) {
|
||||
console.log("Primary color selected: ", color);
|
||||
this.primaryColor = color;
|
||||
$.publish(Events.PRIMARY_COLOR_UPDATED, [color]);
|
||||
}, this));
|
||||
$.subscribe(Events.SECONDARY_COLOR_SELECTED, $.proxy(function(evt, color) {
|
||||
console.log("Secondary color selected: ", color);
|
||||
this.secondaryColor = color;
|
||||
$.publish(Events.SECONDARY_COLOR_UPDATED, [color]);
|
||||
}, this));
|
||||
|
||||
$(window).resize($.proxy(this.startDPIUpdateTimer_, this));
|
||||
|
||||
$.subscribe(Events.USER_SETTINGS_CHANGED, $.proxy(this.onUserSettingsChange_, this));
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, $.proxy(this.updateDPI_, this));
|
||||
|
||||
this.updateDPI_();
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.initMouseBehavior = function() {
|
||||
var body = $('body');
|
||||
this.container.mousedown($.proxy(this.onMousedown_, this));
|
||||
this.container.mousemove($.proxy(this.onMousemove_, this));
|
||||
body.mouseup($.proxy(this.onMouseup_, this));
|
||||
|
||||
// Deactivate right click:
|
||||
body.contextmenu(this.onCanvasContextMenu_);
|
||||
};
|
||||
|
||||
|
||||
|
||||
ns.DrawingController.prototype.startDPIUpdateTimer_ = function () {
|
||||
if (this.dpiUpdateTimer) {
|
||||
window.clearInterval(this.dpiUpdateTimer);
|
||||
}
|
||||
this.dpiUpdateTimer = window.setTimeout($.proxy(this.updateDPI_, this), 200);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onUserSettingsChange_ = function (evt, settingsName, settingsValue) {
|
||||
if(settingsName == pskl.UserSettings.SHOW_GRID) {
|
||||
this.updateDPI_();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMousedown_ = function (event) {
|
||||
this.isClicked = true;
|
||||
|
||||
if(event.button == 2) { // right click
|
||||
this.isRightClicked = true;
|
||||
$.publish(Events.CANVAS_RIGHT_CLICKED);
|
||||
}
|
||||
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
|
||||
this.currentToolBehavior.applyToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMousemove_ = function (event) {
|
||||
var currentTime = new Date().getTime();
|
||||
// Throttling of the mousemove event:
|
||||
if ((currentTime - this.previousMousemoveTime) > 40 ) {
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
if (this.isClicked) {
|
||||
|
||||
this.currentToolBehavior.moveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
// TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
|
||||
// Eg when drawing, it may make sense to have it here. However for a non drawing tool,
|
||||
// you don't need to draw anything when mousemoving and you request useless localStorage.
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
} else {
|
||||
|
||||
this.currentToolBehavior.moveUnactiveToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
}
|
||||
this.previousMousemoveTime = currentTime;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onMouseup_ = function (event) {
|
||||
if(this.isClicked || this.isRightClicked) {
|
||||
// A mouse button was clicked on the drawing canvas before this mouseup event,
|
||||
// the user was probably drawing on the canvas.
|
||||
// Note: The mousemove movement (and the mouseup) may end up outside
|
||||
// of the drawing canvas.
|
||||
|
||||
this.isClicked = false;
|
||||
this.isRightClicked = false;
|
||||
|
||||
var coords = this.getSpriteCoordinates(event);
|
||||
//console.log("mousemove: col: " + spriteCoordinate.col + " - row: " + spriteCoordinate.row);
|
||||
this.currentToolBehavior.releaseToolAt(
|
||||
coords.col, coords.row,
|
||||
this.getCurrentColor_(),
|
||||
this.piskelController.getCurrentFrame(),
|
||||
this.overlayFrame,
|
||||
this.wrapEvtInfo_(event)
|
||||
);
|
||||
|
||||
$.publish(Events.TOOL_RELEASED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.wrapEvtInfo_ = function (event) {
|
||||
var evtInfo = {};
|
||||
if (event.button === 0) {
|
||||
evtInfo.button = Constants.LEFT_BUTTON;
|
||||
} else if (event.button == 2) {
|
||||
evtInfo.button = Constants.RIGHT_BUTTON;
|
||||
}
|
||||
return evtInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getRelativeCoordinates = function (clientX, clientY) {
|
||||
var canvasPageOffset = this.container.offset();
|
||||
return {
|
||||
x : clientX - canvasPageOffset.left,
|
||||
y : clientY - canvasPageOffset.top
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getSpriteCoordinates = function(event) {
|
||||
var coords = this.getRelativeCoordinates(event.clientX, event.clientY);
|
||||
return this.renderer.convertPixelCoordinatesIntoSpriteCoordinate(coords);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.getCurrentColor_ = function () {
|
||||
if(this.isRightClicked) {
|
||||
return this.secondaryColor;
|
||||
} else {
|
||||
return this.primaryColor;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.onCanvasContextMenu_ = function (event) {
|
||||
if ($(event.target).closest('#drawing-canvas-container').length) {
|
||||
// Deactivate right click on drawing canvas only.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.cancelBubble = true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.render = function () {
|
||||
this.renderLayers();
|
||||
this.renderFrame();
|
||||
this.renderOverlay();
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.renderFrame = function () {
|
||||
var frame = this.piskelController.getCurrentFrame();
|
||||
var serializedFrame = this.dpi + "-" + frame.serialize();
|
||||
if (this.serializedFrame != serializedFrame) {
|
||||
if (!frame.isSameSize(this.overlayFrame)) {
|
||||
this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(frame);
|
||||
}
|
||||
this.serializedFrame = serializedFrame;
|
||||
this.renderer.render(frame);
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.renderOverlay = function () {
|
||||
var serializedOverlay = this.dpi + "-" + this.overlayFrame.serialize();
|
||||
if (this.serializedOverlay != serializedOverlay) {
|
||||
this.serializedOverlay = serializedOverlay;
|
||||
this.overlayRenderer.render(this.overlayFrame);
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.renderLayers = function () {
|
||||
var layers = this.piskelController.getLayers();
|
||||
var currentFrameIndex = this.piskelController.currentFrameIndex;
|
||||
var currentLayerIndex = this.piskelController.currentLayerIndex;
|
||||
|
||||
var serializedLayerFrame = [
|
||||
this.dpi,
|
||||
currentFrameIndex,
|
||||
currentLayerIndex,
|
||||
layers.length
|
||||
].join("-");
|
||||
|
||||
if (this.serializedLayerFrame != serializedLayerFrame) {
|
||||
this.layersAboveRenderer.clear();
|
||||
this.layersBelowRenderer.clear();
|
||||
|
||||
var downLayers = layers.slice(0, currentLayerIndex);
|
||||
var downFrame = this.getFrameForLayersAt_(currentFrameIndex, downLayers);
|
||||
this.layersBelowRenderer.render(downFrame);
|
||||
|
||||
if (currentLayerIndex + 1 < layers.length) {
|
||||
var upLayers = layers.slice(currentLayerIndex + 1, layers.length);
|
||||
var upFrame = this.getFrameForLayersAt_(currentFrameIndex, upLayers);
|
||||
this.layersAboveRenderer.render(upFrame);
|
||||
}
|
||||
|
||||
this.serializedLayerFrame = serializedLayerFrame;
|
||||
}
|
||||
};
|
||||
|
||||
ns.DrawingController.prototype.getFrameForLayersAt_ = function (frameIndex, layers) {
|
||||
var frames = layers.map(function (l) {
|
||||
return l.getFrameAt(frameIndex);
|
||||
});
|
||||
return pskl.utils.FrameUtils.merge(frames);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.calculateDPI_ = function() {
|
||||
var availableViewportHeight = $('#main-wrapper').height(),
|
||||
leftSectionWidth = $('.left-column').outerWidth(true),
|
||||
rightSectionWidth = $('.right-column').outerWidth(true),
|
||||
availableViewportWidth = $('#main-wrapper').width() - leftSectionWidth - rightSectionWidth,
|
||||
framePixelHeight = this.piskelController.getCurrentFrame().getHeight(),
|
||||
framePixelWidth = this.piskelController.getCurrentFrame().getWidth();
|
||||
|
||||
if (pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)) {
|
||||
availableViewportWidth = availableViewportWidth - (framePixelWidth * Constants.GRID_STROKE_WIDTH);
|
||||
availableViewportHeight = availableViewportHeight - (framePixelHeight * Constants.GRID_STROKE_WIDTH);
|
||||
}
|
||||
|
||||
var dpi = pskl.PixelUtils.calculateDPI(
|
||||
availableViewportHeight, availableViewportWidth, framePixelHeight, framePixelWidth);
|
||||
|
||||
return dpi;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.DrawingController.prototype.updateDPI_ = function() {
|
||||
this.dpi = this.calculateDPI_();
|
||||
|
||||
this.overlayRenderer.setDPI(this.dpi);
|
||||
this.renderer.setDPI(this.dpi);
|
||||
this.layersAboveRenderer.setDPI(this.dpi);
|
||||
this.layersBelowRenderer.setDPI(this.dpi);
|
||||
|
||||
var currentFrameHeight = this.piskelController.getCurrentFrame().getHeight();
|
||||
var canvasHeight = currentFrameHeight * this.dpi;
|
||||
if (pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID)) {
|
||||
canvasHeight += Constants.GRID_STROKE_WIDTH * currentFrameHeight;
|
||||
}
|
||||
|
||||
var verticalGapInPixel = Math.floor(($('#main-wrapper').height() - canvasHeight) / 2);
|
||||
$('#column-wrapper').css({
|
||||
'top': verticalGapInPixel + 'px',
|
||||
'height': canvasHeight + 'px'
|
||||
});
|
||||
};
|
||||
})();
|
59
preview/js/controller/LayersListController.js
Normal file
@ -0,0 +1,59 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller');
|
||||
|
||||
ns.LayersListController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.init = function () {
|
||||
this.layerItemTemplate_ = pskl.utils.Template.get('layer-item-template');
|
||||
this.rootEl = document.querySelectorAll('.layers-list-container')[0];
|
||||
this.layersListEl = document.querySelectorAll('.layers-list')[0];
|
||||
|
||||
this.rootEl.addEventListener('click', this.onClick_.bind(this));
|
||||
|
||||
$.subscribe(Events.PISKEL_RESET, this.renderLayerList_.bind(this));
|
||||
|
||||
this.renderLayerList_();
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.renderLayerList_ = function () {
|
||||
this.layersListEl.innerHTML = '';
|
||||
var layers = this.piskelController.getLayers();
|
||||
layers.forEach(this.addLayerItem.bind(this));
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.addLayerItem = function (layer) {
|
||||
var layerItemHtml = pskl.utils.Template.replace(this.layerItemTemplate_, {
|
||||
layername : layer.getName()
|
||||
});
|
||||
var layerItem = pskl.utils.Template.createFromHTML(layerItemHtml);
|
||||
if (this.piskelController.getCurrentLayer() === layer) {
|
||||
layerItem.classList.add('current-layer-item');
|
||||
}
|
||||
this.layersListEl.insertBefore(layerItem, this.layersListEl.firstChild);
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.onClick_ = function (evt) {
|
||||
var el = evt.target || evt.srcElement;
|
||||
if (el.nodeName == 'BUTTON') {
|
||||
this.onButtonClick_(el);
|
||||
} else if (el.nodeName == 'LI') {
|
||||
var layerName = el.getAttribute('data-layer-name');
|
||||
this.piskelController.selectLayerByName(layerName);
|
||||
}
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.onButtonClick_ = function (button) {
|
||||
var action = button.getAttribute('data-action');
|
||||
if (action == 'up') {
|
||||
this.piskelController.moveLayerUp();
|
||||
} else if (action == 'down') {
|
||||
this.piskelController.moveLayerDown();
|
||||
} else if (action == 'add') {
|
||||
this.piskelController.createLayer();
|
||||
} else if (action == 'delete') {
|
||||
this.piskelController.removeCurrentLayer();
|
||||
}
|
||||
};
|
||||
})();
|
39
preview/js/controller/NotificationController.js
Normal file
@ -0,0 +1,39 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
|
||||
ns.NotificationController = function () {};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.NotificationController.prototype.init = function() {
|
||||
$.subscribe(Events.SHOW_NOTIFICATION, $.proxy(this.displayMessage_, this));
|
||||
$.subscribe(Events.HIDE_NOTIFICATION, $.proxy(this.removeMessage_, this));
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.NotificationController.prototype.displayMessage_ = function (evt, messageInfo) {
|
||||
var message = document.createElement('div');
|
||||
message.id = "user-message";
|
||||
message.className = "user-message";
|
||||
message.innerHTML = messageInfo.content;
|
||||
message.innerHTML = message.innerHTML + "<div title='Close message' class='close'>x</div>";
|
||||
document.body.appendChild(message);
|
||||
$(message).find(".close").click($.proxy(this.removeMessage_, this));
|
||||
if(messageInfo.behavior) {
|
||||
messageInfo.behavior(message);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.NotificationController.prototype.removeMessage_ = function (evt) {
|
||||
var message = $("#user-message");
|
||||
if (message.length) {
|
||||
message.remove();
|
||||
}
|
||||
};
|
||||
})();
|
83
preview/js/controller/PaletteController.js
Normal file
@ -0,0 +1,83 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
|
||||
ns.PaletteController = function () {};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.PaletteController.prototype.init = function() {
|
||||
var transparentColorPalette = $(".palette-color[data-color=TRANSPARENT]");
|
||||
transparentColorPalette.mouseup($.proxy(this.onPaletteColorClick_, this));
|
||||
|
||||
$.subscribe(Events.PRIMARY_COLOR_UPDATED, $.proxy(function(evt, color) {
|
||||
this.updateColorPicker_(color, $('#color-picker'));
|
||||
}, this));
|
||||
|
||||
$.subscribe(Events.SECONDARY_COLOR_UPDATED, $.proxy(function(evt, color) {
|
||||
this.updateColorPicker_(color, $('#secondary-color-picker'));
|
||||
}, this));
|
||||
|
||||
// Initialize colorpickers:
|
||||
var colorPicker = $('#color-picker');
|
||||
colorPicker.val(Constants.DEFAULT_PEN_COLOR);
|
||||
colorPicker.change({isPrimary : true}, $.proxy(this.onPickerChange_, this));
|
||||
|
||||
|
||||
var secondaryColorPicker = $('#secondary-color-picker');
|
||||
secondaryColorPicker.val(Constants.TRANSPARENT_COLOR);
|
||||
secondaryColorPicker.change({isPrimary : false}, $.proxy(this.onPickerChange_, this));
|
||||
|
||||
window.jscolor.install();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PaletteController.prototype.onPickerChange_ = function(evt, isPrimary) {
|
||||
var inputPicker = $(evt.target);
|
||||
if(evt.data.isPrimary) {
|
||||
$.publish(Events.PRIMARY_COLOR_SELECTED, [inputPicker.val()]);
|
||||
} else {
|
||||
$.publish(Events.SECONDARY_COLOR_SELECTED, [inputPicker.val()]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PaletteController.prototype.onPaletteColorClick_ = function (event) {
|
||||
var selectedColor = $(event.target).data("color");
|
||||
var isLeftClick = (event.which == 1);
|
||||
var isRightClick = (event.which == 3);
|
||||
if (isLeftClick) {
|
||||
$.publish(Events.PRIMARY_COLOR_SELECTED, [selectedColor]);
|
||||
} else if (isRightClick) {
|
||||
$.publish(Events.SECONDARY_COLOR_SELECTED, [selectedColor]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PaletteController.prototype.updateColorPicker_ = function (color, colorPicker) {
|
||||
if (color == Constants.TRANSPARENT_COLOR) {
|
||||
// We can set the current palette color to transparent.
|
||||
// You can then combine this transparent color with an advanced
|
||||
// tool for customized deletions.
|
||||
// Eg: bucket + transparent: Delete a colored area
|
||||
// Stroke + transparent: hollow out the equivalent of a stroke
|
||||
|
||||
// The colorpicker can't be set to a transparent state.
|
||||
// We set its background to white and insert the
|
||||
// string "TRANSPARENT" to mimic this state:
|
||||
colorPicker[0].color.fromString("#fff");
|
||||
colorPicker.val(Constants.TRANSPARENT_COLOR);
|
||||
} else {
|
||||
colorPicker[0].color.fromString(color);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
194
preview/js/controller/PiskelController.js
Normal file
@ -0,0 +1,194 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller');
|
||||
|
||||
ns.PiskelController = function (piskel) {
|
||||
if (piskel) {
|
||||
this.setPiskel(piskel);
|
||||
} else {
|
||||
throw 'A piskel instance is mandatory for instanciating PiskelController';
|
||||
}
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.setPiskel = function (piskel) {
|
||||
this.piskel = piskel;
|
||||
this.currentLayerIndex = 0;
|
||||
this.currentFrameIndex = 0;
|
||||
|
||||
this.layerIdCounter = 1;
|
||||
|
||||
$.publish(Events.PISKEL_RESET);
|
||||
$.publish(Events.FRAME_SIZE_CHANGED);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getHeight = function () {
|
||||
return this.piskel.getHeight();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getWidth = function () {
|
||||
return this.piskel.getWidth();
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO : this should be removed
|
||||
* FPS should be stored in the Piskel model and not in the
|
||||
* animationController
|
||||
* Then piskelController should be able to return this information
|
||||
* @return {Number} Frames per second for the current animation
|
||||
*/
|
||||
ns.PiskelController.prototype.getFPS = function () {
|
||||
return pskl.app.animationController.getFPS();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getLayers = function () {
|
||||
return this.piskel.getLayers();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getCurrentLayer = function () {
|
||||
return this.piskel.getLayerAt(this.currentLayerIndex);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getCurrentFrame = function () {
|
||||
var layer = this.getCurrentLayer();
|
||||
return layer.getFrameAt(this.currentFrameIndex);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getFrameAt = function (index) {
|
||||
var frames = this.getLayers().map(function (l) {
|
||||
return l.getFrameAt(index);
|
||||
});
|
||||
return pskl.utils.FrameUtils.merge(frames);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.hasFrameAt = function (index) {
|
||||
return !!this.getCurrentLayer().getFrameAt(index);
|
||||
};
|
||||
|
||||
// backward from framesheet
|
||||
ns.PiskelController.prototype.getFrameByIndex =
|
||||
ns.PiskelController.prototype.getMergedFrameAt;
|
||||
|
||||
ns.PiskelController.prototype.addEmptyFrame = function () {
|
||||
var layers = this.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.addFrame(this.createEmptyFrame_());
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.createEmptyFrame_ = function () {
|
||||
var w = this.piskel.getWidth(), h = this.piskel.getHeight();
|
||||
return new pskl.model.Frame(w, h);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.removeFrameAt = function (index) {
|
||||
var layers = this.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.removeFrameAt(index);
|
||||
});
|
||||
// Current frame index is impacted if the removed frame was before the current frame
|
||||
if (this.currentFrameIndex >= index) {
|
||||
this.setCurrentFrameIndex(this.currentFrameIndex - 1);
|
||||
}
|
||||
|
||||
$.publish(Events.PISKEL_RESET);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.duplicateFrameAt = function (index) {
|
||||
var layers = this.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.duplicateFrameAt(index);
|
||||
});
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.moveFrame = function (fromIndex, toIndex) {
|
||||
var layers = this.getLayers();
|
||||
layers.forEach(function (l) {
|
||||
l.moveFrame(fromIndex, toIndex);
|
||||
});
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.getFrameCount = function () {
|
||||
var layer = this.piskel.getLayerAt(0);
|
||||
return layer.length();
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
|
||||
this.currentFrameIndex = index;
|
||||
$.publish(Events.PISKEL_RESET);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.setCurrentLayerIndex = function (index) {
|
||||
this.currentLayerIndex = index;
|
||||
$.publish(Events.PISKEL_RESET);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.selectLayer = function (layer) {
|
||||
var index = this.getLayers().indexOf(layer);
|
||||
if (index != -1) {
|
||||
this.setCurrentLayerIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.selectLayerByName = function (name) {
|
||||
if (this.hasLayerForName_(name)) {
|
||||
var layer = this.piskel.getLayersByName(name)[0];
|
||||
this.selectLayer(layer);
|
||||
}
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.generateLayerName_ = function () {
|
||||
var name = "Layer " + this.layerIdCounter;
|
||||
while (this.hasLayerForName_(name)) {
|
||||
this.layerIdCounter++;
|
||||
name = "Layer " + this.layerIdCounter;
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.createLayer = function (name) {
|
||||
if (!name) {
|
||||
name = this.generateLayerName_();
|
||||
}
|
||||
if (!this.hasLayerForName_(name)) {
|
||||
var layer = new pskl.model.Layer(name);
|
||||
for (var i = 0 ; i < this.getFrameCount() ; i++) {
|
||||
layer.addFrame(this.createEmptyFrame_());
|
||||
}
|
||||
this.piskel.addLayer(layer);
|
||||
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
|
||||
} else {
|
||||
throw 'Layer name should be unique';
|
||||
}
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.hasLayerForName_ = function (name) {
|
||||
return this.piskel.getLayersByName(name).length > 0;
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.moveLayerUp = function () {
|
||||
var layer = this.getCurrentLayer();
|
||||
this.piskel.moveLayerUp(layer);
|
||||
this.selectLayer(layer);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.moveLayerDown = function () {
|
||||
var layer = this.getCurrentLayer();
|
||||
this.piskel.moveLayerDown(layer);
|
||||
this.selectLayer(layer);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.removeCurrentLayer = function () {
|
||||
if (this.getLayers().length > 1) {
|
||||
var layer = this.getCurrentLayer();
|
||||
this.piskel.removeLayer(layer);
|
||||
this.setCurrentLayerIndex(0);
|
||||
}
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.serialize = function () {
|
||||
return pskl.utils.Serializer.serializePiskel(this.piskel);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.load = function (data) {
|
||||
this.deserialize(JSON.stringify(data));
|
||||
};
|
||||
})();
|
220
preview/js/controller/PreviewFilmController.js
Normal file
@ -0,0 +1,220 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
ns.PreviewFilmController = function (piskelController, container, dpi) {
|
||||
|
||||
this.piskelController = piskelController;
|
||||
this.container = container;
|
||||
this.dpi = this.calculateDPI_();
|
||||
|
||||
this.redrawFlag = true;
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.init = function() {
|
||||
$.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this));
|
||||
$.subscribe(Events.PISKEL_RESET, this.flagForRedraw_.bind(this));
|
||||
$.subscribe(Events.PISKEL_RESET, this.refreshDPI_.bind(this));
|
||||
|
||||
$('#preview-list-scroller').scroll(this.updateScrollerOverflows.bind(this));
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.addFrame = function () {
|
||||
this.piskelController.addEmptyFrame();
|
||||
this.piskelController.setCurrentFrameIndex(this.piskelController.getFrameCount() - 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.flagForRedraw_ = function () {
|
||||
this.redrawFlag = true;
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.refreshDPI_ = function () {
|
||||
this.dpi = this.calculateDPI_();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.render = function () {
|
||||
if (this.redrawFlag) {
|
||||
// TODO(vincz): Full redraw on any drawing modification, optimize.
|
||||
this.createPreviews_();
|
||||
this.redrawFlag = false;
|
||||
}
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.updateScrollerOverflows = function () {
|
||||
var scroller = $('#preview-list-scroller');
|
||||
var scrollerHeight = scroller.height();
|
||||
var scrollTop = scroller.scrollTop();
|
||||
var scrollerContentHeight = $('#preview-list').height();
|
||||
var treshold = $('.top-overflow').height();
|
||||
var overflowTop = false,
|
||||
overflowBottom = false;
|
||||
if (scrollerHeight < scrollerContentHeight) {
|
||||
if (scrollTop > treshold) {
|
||||
overflowTop = true;
|
||||
}
|
||||
var scrollBottom = (scrollerContentHeight - scrollTop) - scrollerHeight;
|
||||
if (scrollBottom > treshold) {
|
||||
overflowBottom = true;
|
||||
}
|
||||
}
|
||||
var wrapper = $('#preview-list-wrapper');
|
||||
wrapper.toggleClass('top-overflow-visible', overflowTop);
|
||||
wrapper.toggleClass('bottom-overflow-visible', overflowBottom);
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.createPreviews_ = function () {
|
||||
|
||||
this.container.html("");
|
||||
// Manually remove tooltips since mouseout events were shortcut by the DOM refresh:
|
||||
$(".tooltip").remove();
|
||||
|
||||
var frameCount = this.piskelController.getFrameCount();
|
||||
|
||||
for (var i = 0, l = frameCount; i < l ; i++) {
|
||||
this.container.append(this.createPreviewTile_(i));
|
||||
}
|
||||
// Append 'new empty frame' button
|
||||
var newFrameButton = document.createElement("div");
|
||||
newFrameButton.id = "add-frame-action";
|
||||
newFrameButton.className = "add-frame-action";
|
||||
newFrameButton.innerHTML = "<p class='label'>Add new frame</p>";
|
||||
this.container.append(newFrameButton);
|
||||
|
||||
$(newFrameButton).click(this.addFrame.bind(this));
|
||||
|
||||
var needDragndropBehavior = (frameCount > 1);
|
||||
if(needDragndropBehavior) {
|
||||
this.initDragndropBehavior_();
|
||||
}
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.initDragndropBehavior_ = function () {
|
||||
|
||||
$("#preview-list").sortable({
|
||||
placeholder: "preview-tile-drop-proxy",
|
||||
update: $.proxy(this.onUpdate_, this),
|
||||
items: ".preview-tile"
|
||||
});
|
||||
$("#preview-list").disableSelection();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.onUpdate_ = function( event, ui ) {
|
||||
var originFrameId = parseInt(ui.item.data("tile-number"), 10);
|
||||
var targetInsertionId = $('.preview-tile').index(ui.item);
|
||||
|
||||
this.piskelController.moveFrame(originFrameId, targetInsertionId);
|
||||
this.piskelController.setCurrentFrameIndex(targetInsertionId);
|
||||
|
||||
// TODO(grosbouddha): move localstorage request to the model layer?
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* TODO(vincz): clean this giant rendering function & remove listeners.
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) {
|
||||
var currentFrame = this.piskelController.getCurrentLayer().getFrameAt(tileNumber);
|
||||
|
||||
var previewTileRoot = document.createElement("li");
|
||||
var classname = "preview-tile";
|
||||
previewTileRoot.setAttribute("data-tile-number", tileNumber);
|
||||
|
||||
if (this.piskelController.getCurrentFrame() == currentFrame) {
|
||||
classname += " selected";
|
||||
}
|
||||
previewTileRoot.className = classname;
|
||||
|
||||
var canvasContainer = document.createElement("div");
|
||||
canvasContainer.className = "canvas-container";
|
||||
|
||||
var canvasBackground = document.createElement("div");
|
||||
canvasBackground.className = "canvas-background";
|
||||
canvasContainer.appendChild(canvasBackground);
|
||||
|
||||
previewTileRoot.addEventListener('click', this.onPreviewClick_.bind(this, tileNumber));
|
||||
|
||||
var cloneFrameButton = document.createElement("button");
|
||||
cloneFrameButton.setAttribute('rel', 'tooltip');
|
||||
cloneFrameButton.setAttribute('data-placement', 'right');
|
||||
cloneFrameButton.setAttribute('title', 'Duplicate this frame');
|
||||
cloneFrameButton.className = "tile-overlay duplicate-frame-action";
|
||||
previewTileRoot.appendChild(cloneFrameButton);
|
||||
cloneFrameButton.addEventListener('click', this.onAddButtonClick_.bind(this, tileNumber));
|
||||
|
||||
// TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim
|
||||
// is to make this update function (#createPreviewTile) less aggressive.
|
||||
var renderingOptions = {"dpi": this.dpi };
|
||||
var currentFrameRenderer = new pskl.rendering.FrameRenderer($(canvasContainer), renderingOptions, ["tile-view"]);
|
||||
currentFrameRenderer.render(currentFrame);
|
||||
|
||||
previewTileRoot.appendChild(canvasContainer);
|
||||
|
||||
if(tileNumber > 0 || this.piskelController.getFrameCount() > 1) {
|
||||
// Add 'remove frame' button.
|
||||
var deleteButton = document.createElement("button");
|
||||
deleteButton.setAttribute('rel', 'tooltip');
|
||||
deleteButton.setAttribute('data-placement', 'right');
|
||||
deleteButton.setAttribute('title', 'Delete this frame');
|
||||
deleteButton.className = "tile-overlay delete-frame-action";
|
||||
deleteButton.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber));
|
||||
previewTileRoot.appendChild(deleteButton);
|
||||
|
||||
// Add 'dragndrop handle'.
|
||||
var dndHandle = document.createElement("div");
|
||||
dndHandle.className = "tile-overlay dnd-action";
|
||||
previewTileRoot.appendChild(dndHandle);
|
||||
}
|
||||
var tileCount = document.createElement("div");
|
||||
tileCount.className = "tile-overlay tile-count";
|
||||
tileCount.innerHTML = tileNumber;
|
||||
previewTileRoot.appendChild(tileCount);
|
||||
|
||||
|
||||
return previewTileRoot;
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) {
|
||||
// has not class tile-action:
|
||||
if(!evt.target.classList.contains('tile-overlay')) {
|
||||
this.piskelController.setCurrentFrameIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) {
|
||||
this.piskelController.removeFrameAt(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) {
|
||||
this.piskelController.duplicateFrameAt(index);
|
||||
$.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model
|
||||
this.piskelController.setCurrentFrameIndex(index + 1);
|
||||
this.updateScrollerOverflows();
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the preview DPI depending on the piskel size
|
||||
*/
|
||||
ns.PreviewFilmController.prototype.calculateDPI_ = function () {
|
||||
var curFrame = this.piskelController.getCurrentFrame(),
|
||||
frameHeight = curFrame.getHeight(),
|
||||
frameWidth = curFrame.getWidth(),
|
||||
maxFrameDim = Math.max(frameWidth, frameHeight);
|
||||
|
||||
var previewHeight = Constants.PREVIEW_FILM_SIZE * frameHeight / maxFrameDim;
|
||||
var previewWidth = Constants.PREVIEW_FILM_SIZE * frameWidth / maxFrameDim;
|
||||
|
||||
return pskl.PixelUtils.calculateDPI(previewHeight, previewWidth, frameHeight, frameWidth) || 1;
|
||||
};
|
||||
})();
|
107
preview/js/controller/ToolController.js
Normal file
@ -0,0 +1,107 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller");
|
||||
|
||||
|
||||
ns.ToolController = function () {
|
||||
|
||||
this.toolInstances = {
|
||||
"simplePen" : new pskl.drawingtools.SimplePen(),
|
||||
"verticalMirrorPen" : new pskl.drawingtools.VerticalMirrorPen(),
|
||||
"eraser" : new pskl.drawingtools.Eraser(),
|
||||
"paintBucket" : new pskl.drawingtools.PaintBucket(),
|
||||
"stroke" : new pskl.drawingtools.Stroke(),
|
||||
"rectangle" : new pskl.drawingtools.Rectangle(),
|
||||
"circle" : new pskl.drawingtools.Circle(),
|
||||
"move" : new pskl.drawingtools.Move(),
|
||||
"rectangleSelect" : new pskl.drawingtools.RectangleSelect(),
|
||||
"shapeSelect" : new pskl.drawingtools.ShapeSelect(),
|
||||
"colorPicker" : new pskl.drawingtools.ColorPicker()
|
||||
};
|
||||
|
||||
this.currentSelectedTool = this.toolInstances.simplePen;
|
||||
this.previousSelectedTool = this.toolInstances.simplePen;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.ToolController.prototype.init = function() {
|
||||
this.createToolMarkup_();
|
||||
|
||||
// Initialize tool:
|
||||
// Set SimplePen as default selected tool:
|
||||
this.selectTool_(this.toolInstances.simplePen);
|
||||
// Activate listener on tool panel:
|
||||
$("#tool-section").click($.proxy(this.onToolIconClicked_, this));
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.activateToolOnStage_ = function(tool) {
|
||||
var stage = $("body");
|
||||
var previousSelectedToolClass = stage.data("selected-tool-class");
|
||||
if(previousSelectedToolClass) {
|
||||
stage.removeClass(previousSelectedToolClass);
|
||||
}
|
||||
stage.addClass(tool.toolId);
|
||||
stage.data("selected-tool-class", tool.toolId);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.selectTool_ = function(tool) {
|
||||
console.log("Selecting Tool:" , this.currentSelectedTool);
|
||||
this.currentSelectedTool = tool;
|
||||
this.activateToolOnStage_(this.currentSelectedTool);
|
||||
$.publish(Events.TOOL_SELECTED, [tool]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.onToolIconClicked_ = function(evt) {
|
||||
var target = $(evt.target);
|
||||
var clickedTool = target.closest(".tool-icon");
|
||||
|
||||
if(clickedTool.length) {
|
||||
var toolId = clickedTool.data().toolId;
|
||||
var tool = this.getToolById_(toolId);
|
||||
if (tool) {
|
||||
this.selectTool_(tool);
|
||||
|
||||
// Show tool as selected:
|
||||
$('#tool-section .tool-icon.selected').removeClass('selected');
|
||||
clickedTool.addClass('selected');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ToolController.prototype.getToolById_ = function (toolId) {
|
||||
for(var key in this.toolInstances) {
|
||||
if (this.toolInstances[key].toolId == toolId) {
|
||||
return this.toolInstances[key];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.ToolController.prototype.createToolMarkup_ = function() {
|
||||
var currentTool, toolMarkup = '', extraClass;
|
||||
// TODO(vincz): Tools rendering order is not enforced by the data stucture (this.toolInstances), fix that.
|
||||
for (var toolKey in this.toolInstances) {
|
||||
currentTool = this.toolInstances[toolKey];
|
||||
extraClass = currentTool.toolId;
|
||||
if (this.currentSelectedTool == currentTool) {
|
||||
extraClass = extraClass + " selected";
|
||||
}
|
||||
toolMarkup += '<li rel="tooltip" data-placement="right" class="tool-icon ' + extraClass + '" data-tool-id="' + currentTool.toolId +
|
||||
'" title="' + currentTool.helpText + '"></li>';
|
||||
}
|
||||
$('#tools-container').html(toolMarkup);
|
||||
};
|
||||
})();
|
@ -0,0 +1,38 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller.settings");
|
||||
|
||||
ns.ApplicationSettingsController = function () {};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.ApplicationSettingsController.prototype.init = function() {
|
||||
// Highlight selected background picker:
|
||||
var backgroundClass = pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);
|
||||
$('#background-picker-wrapper')
|
||||
.find('.background-picker[data-background-class=' + backgroundClass + ']')
|
||||
.addClass('selected');
|
||||
|
||||
// Initial state for grid display:
|
||||
var show_grid = pskl.UserSettings.get(pskl.UserSettings.SHOW_GRID);
|
||||
$('#show-grid').prop('checked', show_grid);
|
||||
|
||||
// Handle grid display changes:
|
||||
$('#show-grid').change($.proxy(function(evt) {
|
||||
var checked = $('#show-grid').prop('checked');
|
||||
pskl.UserSettings.set(pskl.UserSettings.SHOW_GRID, checked);
|
||||
}, this));
|
||||
|
||||
// Handle canvas background changes:
|
||||
$('#background-picker-wrapper').click(function(evt) {
|
||||
var target = $(evt.target).closest('.background-picker');
|
||||
if (target.length) {
|
||||
var backgroundClass = target.data('background-class');
|
||||
pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND, backgroundClass);
|
||||
|
||||
$('.background-picker').removeClass('selected');
|
||||
target.addClass('selected');
|
||||
}
|
||||
});
|
||||
};
|
||||
})();
|
129
preview/js/controller/settings/GifExportController.js
Normal file
@ -0,0 +1,129 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller.settings");
|
||||
|
||||
ns.GifExportController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
};
|
||||
|
||||
/**
|
||||
* List of Resolutions applicable for Gif export
|
||||
* @static
|
||||
* @type {Array} array of Objects {dpi:{Number}, default:{Boolean}}
|
||||
*/
|
||||
ns.GifExportController.RESOLUTIONS = [
|
||||
{
|
||||
'dpi' : 1
|
||||
},{
|
||||
'dpi' : 5
|
||||
},{
|
||||
'dpi' : 10,
|
||||
'default' : true
|
||||
},{
|
||||
'dpi' : 20
|
||||
}
|
||||
];
|
||||
|
||||
ns.GifExportController.prototype.init = function () {
|
||||
this.radioTemplate_ = pskl.utils.Template.get("gif-export-radio-template");
|
||||
|
||||
this.previewContainerEl = document.querySelectorAll(".gif-export-preview")[0];
|
||||
this.radioGroupEl = document.querySelectorAll(".gif-export-radio-group")[0];
|
||||
|
||||
this.uploadForm = $("[name=gif-export-upload-form]");
|
||||
this.uploadForm.submit(this.onUploadFormSubmit_.bind(this));
|
||||
|
||||
this.createRadioElements_();
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.onUploadFormSubmit_ = function (evt) {
|
||||
evt.originalEvent.preventDefault();
|
||||
var selectedDpi = this.getSelectedDpi_(),
|
||||
fps = this.piskelController.getFPS(),
|
||||
dpi = selectedDpi;
|
||||
|
||||
this.renderAsImageDataAnimatedGIF(dpi, fps, this.onGifRenderingCompleted_.bind(this));
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.onGifRenderingCompleted_ = function (imageData) {
|
||||
this.updatePreview_(imageData);
|
||||
this.previewContainerEl.classList.add("preview-upload-ongoing");
|
||||
pskl.app.imageUploadService.upload(imageData, this.onImageUploadCompleted_.bind(this));
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.onImageUploadCompleted_ = function (imageUrl) {
|
||||
this.updatePreview_(imageUrl);
|
||||
this.previewContainerEl.classList.remove("preview-upload-ongoing");
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.updatePreview_ = function (src) {
|
||||
this.previewContainerEl.innerHTML = "<div><img style='max-width:240px;' src='"+src+"'/></div>";
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.getSelectedDpi_ = function () {
|
||||
var radiosColl = this.uploadForm.get(0).querySelectorAll("[name=gif-dpi]"),
|
||||
radios = Array.prototype.slice.call(radiosColl,0);
|
||||
var selectedRadios = radios.filter(function(radio) {return !!radio.checked;});
|
||||
|
||||
if (selectedRadios.length == 1) {
|
||||
return selectedRadios[0].value;
|
||||
} else {
|
||||
throw "Unexpected error when retrieving selected dpi";
|
||||
}
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.createRadioElements_ = function () {
|
||||
var resolutions = ns.GifExportController.RESOLUTIONS;
|
||||
for (var i = 0 ; i < resolutions.length ; i++) {
|
||||
var radio = this.createRadioForResolution_(resolutions[i]);
|
||||
this.radioGroupEl.appendChild(radio);
|
||||
}
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.createRadioForResolution_ = function (resolution) {
|
||||
var dpi = resolution.dpi;
|
||||
var label = dpi*this.piskelController.getWidth() + "x" + dpi*this.piskelController.getHeight();
|
||||
var value = dpi;
|
||||
|
||||
var radioHTML = pskl.utils.Template.replace(this.radioTemplate_, {value : value, label : label});
|
||||
var radioEl = pskl.utils.Template.createFromHTML(radioHTML);
|
||||
|
||||
if (resolution['default']) {
|
||||
var input = radioEl.getElementsByTagName("input")[0];
|
||||
input.setAttribute("checked", "checked");
|
||||
}
|
||||
|
||||
return radioEl;
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.blobToBase64_ = function(blob, cb) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
var dataUrl = reader.result;
|
||||
cb(dataUrl);
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.renderAsImageDataAnimatedGIF = function(dpi, fps, cb) {
|
||||
var gif = new window.GIF({
|
||||
workers: 2,
|
||||
quality: 10,
|
||||
width: this.piskelController.getWidth()*dpi,
|
||||
height: this.piskelController.getHeight()*dpi
|
||||
});
|
||||
|
||||
for (var i = 0; i < this.piskelController.getFrameCount(); i++) {
|
||||
var frame = this.piskelController.getFrameAt(i);
|
||||
var renderer = new pskl.rendering.CanvasRenderer(frame, dpi);
|
||||
gif.addFrame(renderer.render(), {
|
||||
delay: 1000 / fps
|
||||
});
|
||||
}
|
||||
|
||||
gif.on('finished', function(blob) {
|
||||
this.blobToBase64_(blob, cb);
|
||||
}.bind(this));
|
||||
|
||||
gif.render();
|
||||
};
|
||||
})();
|
168
preview/js/controller/settings/ImportController.js
Normal file
@ -0,0 +1,168 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.settings');
|
||||
var DEFAULT_FILE_STATUS = 'No file selected ...';
|
||||
var PREVIEW_HEIGHT = 60;
|
||||
|
||||
ns.ImportController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
this.importedImage_ = null;
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.init = function () {
|
||||
this.importForm = $("[name=import-form]");
|
||||
this.hiddenFileInput = $("[name=file-upload-input]");
|
||||
this.fileInputButton = $(".file-input-button");
|
||||
this.fileInputStatus = $(".file-input-status");
|
||||
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
|
||||
|
||||
this.importPreview = $(".import-section-preview");
|
||||
|
||||
this.resizeWidth = $("[name=resize-width]");
|
||||
this.resizeHeight = $("[name=resize-height]");
|
||||
this.smoothResize = $("[name=smooth-resize-checkbox]");
|
||||
this.submitButton = $("[name=import-submit]");
|
||||
|
||||
this.importForm.submit(this.onImportFormSubmit_.bind(this));
|
||||
this.hiddenFileInput.change(this.onFileUploadChange_.bind(this));
|
||||
this.fileInputButton.click(this.onFileInputClick_.bind(this));
|
||||
|
||||
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
|
||||
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.reset_ = function () {
|
||||
this.importForm.get(0).reset();
|
||||
this.fileInputStatus.html(DEFAULT_FILE_STATUS);
|
||||
$.publish(Events.CLOSE_SETTINGS_DRAWER);
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onResizeInputKeyUp_ = function (from, evt) {
|
||||
if (this.importedImage_) {
|
||||
this.synchronizeResizeFields_(evt.target.value, from);
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.synchronizeResizeFields_ = function (value, from) {
|
||||
value = parseInt(value, 10);
|
||||
if (isNaN(value)) {
|
||||
value = 0;
|
||||
}
|
||||
var height = this.importedImage_.height, width = this.importedImage_.width;
|
||||
if (from === 'width') {
|
||||
this.resizeHeight.val(Math.round(value * height / width));
|
||||
} else {
|
||||
this.resizeWidth.val(Math.round(value * width / height));
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onImportFormSubmit_ = function (evt) {
|
||||
evt.originalEvent.preventDefault();
|
||||
this.importImageToPiskel_();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onFileUploadChange_ = function (evt) {
|
||||
this.importFromFile_();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onFileInputClick_ = function (evt) {
|
||||
this.hiddenFileInput.click();
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.importFromFile_ = function () {
|
||||
var files = this.hiddenFileInput.get(0).files;
|
||||
if (files.length == 1) {
|
||||
var file = files[0];
|
||||
if (this.isImage_(file)) {
|
||||
this.readImageFile_(file);
|
||||
this.enableDisabledSections_();
|
||||
} else {
|
||||
this.reset_();
|
||||
throw "File is not an image : " + file.type;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.enableDisabledSections_ = function () {
|
||||
this.resizeWidth.removeAttr('disabled');
|
||||
this.resizeHeight.removeAttr('disabled');
|
||||
this.smoothResize.removeAttr('disabled');
|
||||
this.submitButton.removeAttr('disabled');
|
||||
|
||||
this.fileInputButton.removeClass('button-primary');
|
||||
this.fileInputButton.blur();
|
||||
|
||||
$('.import-section-disabled').removeClass('import-section-disabled');
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.readImageFile_ = function (imageFile) {
|
||||
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an image from the given source (url or data-url), and onload forward to onImageLoaded
|
||||
* TODO : should be a generic utility method, should take a callback
|
||||
* @param {String} imageSource url or data-url, will be used as src for the image
|
||||
*/
|
||||
ns.ImportController.prototype.processImageSource_ = function (imageSource) {
|
||||
this.importedImage_ = new Image();
|
||||
this.importedImage_.onload = this.onImageLoaded_.bind(this);
|
||||
this.importedImage_.src = imageSource;
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.onImageLoaded_ = function (evt) {
|
||||
var w = this.importedImage_.width,
|
||||
h = this.importedImage_.height;
|
||||
var filePath = this.hiddenFileInput.val();
|
||||
var fileName = this.extractFileNameFromPath_(filePath);
|
||||
this.fileInputStatus.html(fileName);
|
||||
|
||||
this.resizeWidth.val(w);
|
||||
this.resizeHeight.val(h);
|
||||
|
||||
this.importPreview.width("auto");
|
||||
this.importPreview.append(this.createImagePreview_());
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.createImagePreview_ = function () {
|
||||
var image = document.createElement('IMG');
|
||||
image.src = this.importedImage_.src;
|
||||
image.setAttribute('height', PREVIEW_HEIGHT);
|
||||
return image;
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.extractFileNameFromPath_ = function (path) {
|
||||
var parts = [];
|
||||
if (path.indexOf('/') !== -1) {
|
||||
parts = path.split('/');
|
||||
} else if (path.indexOf('\\') !== -1) {
|
||||
parts = path.split('\\');
|
||||
} else {
|
||||
parts = [path];
|
||||
}
|
||||
return parts[parts.length-1];
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.importImageToPiskel_ = function () {
|
||||
if (this.importedImage_) {
|
||||
if (window.confirm("You are about to create a new Piskel, unsaved changes will be lost.")) {
|
||||
var w = this.resizeWidth.val(),
|
||||
h = this.resizeHeight.val(),
|
||||
smoothing = !!this.smoothResize.prop('checked');
|
||||
|
||||
var image = pskl.utils.ImageResizer.resize(this.importedImage_, w, h, smoothing);
|
||||
var frame = pskl.utils.FrameUtils.createFromImage(image);
|
||||
|
||||
var piskel = pskl.utils.Serializer.createPiskel([frame]);
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
pskl.app.animationController.setFPS(Constants.DEFAULT.FPS);
|
||||
|
||||
this.reset_();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImportController.prototype.isImage_ = function (file) {
|
||||
return file.type.indexOf('image') === 0;
|
||||
};
|
||||
|
||||
})();
|
76
preview/js/controller/settings/SettingsController.js
Normal file
@ -0,0 +1,76 @@
|
||||
(function () {
|
||||
var ns = $.namespace("pskl.controller.settings");
|
||||
|
||||
var settings = {
|
||||
'user' : {
|
||||
template : 'templates/settings/application.html',
|
||||
controller : ns.ApplicationSettingsController
|
||||
},
|
||||
'gif' : {
|
||||
template : 'templates/settings/export-gif.html',
|
||||
controller : ns.GifExportController
|
||||
},
|
||||
'import' : {
|
||||
template : 'templates/settings/import.html',
|
||||
controller : ns.ImportController
|
||||
}
|
||||
};
|
||||
|
||||
var SEL_SETTING_CLS = 'has-expanded-drawer';
|
||||
var EXP_DRAWER_CLS = 'expanded';
|
||||
|
||||
ns.SettingsController = function (piskelController) {
|
||||
this.piskelController = piskelController;
|
||||
this.drawerContainer = document.getElementById("drawer-container");
|
||||
this.settingsContainer = $('[data-pskl-controller=settings]');
|
||||
this.expanded = false;
|
||||
this.currentSetting = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
ns.SettingsController.prototype.init = function() {
|
||||
// Expand drawer when clicking 'Settings' tab.
|
||||
$('[data-setting]').click(function(evt) {
|
||||
var el = evt.originalEvent.currentTarget;
|
||||
var setting = el.getAttribute("data-setting");
|
||||
if (this.currentSetting != setting) {
|
||||
this.loadSetting(setting);
|
||||
} else {
|
||||
this.closeDrawer();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
$('body').click(function (evt) {
|
||||
var isInSettingsContainer = $.contains(this.settingsContainer.get(0), evt.target);
|
||||
if (this.expanded && !isInSettingsContainer) {
|
||||
this.closeDrawer();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
$.subscribe(Events.CLOSE_SETTINGS_DRAWER, this.closeDrawer.bind(this));
|
||||
};
|
||||
|
||||
ns.SettingsController.prototype.loadSetting = function (setting) {
|
||||
this.drawerContainer.innerHTML = pskl.utils.Template.get(settings[setting].template);
|
||||
(new settings[setting].controller(this.piskelController)).init();
|
||||
|
||||
this.settingsContainer.addClass(EXP_DRAWER_CLS);
|
||||
|
||||
$('.' + SEL_SETTING_CLS).removeClass(SEL_SETTING_CLS);
|
||||
$('[data-setting='+setting+']').addClass(SEL_SETTING_CLS);
|
||||
|
||||
this.expanded = true;
|
||||
this.currentSetting = setting;
|
||||
};
|
||||
|
||||
ns.SettingsController.prototype.closeDrawer = function () {
|
||||
this.settingsContainer.removeClass(EXP_DRAWER_CLS);
|
||||
$('.' + SEL_SETTING_CLS).removeClass(SEL_SETTING_CLS);
|
||||
|
||||
this.expanded = false;
|
||||
this.currentSetting = null;
|
||||
};
|
||||
|
||||
})();
|
75
preview/js/drawingtools/BaseTool.js
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.BaseTool
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.BaseTool = function() {};
|
||||
|
||||
ns.BaseTool.prototype.applyToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
ns.BaseTool.prototype.moveToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
ns.BaseTool.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay) {
|
||||
if (overlay.containsPixel(col, row)) {
|
||||
if (!isNaN(this.highlightedPixelCol) &&
|
||||
!isNaN(this.highlightedPixelRow) &&
|
||||
(this.highlightedPixelRow != row ||
|
||||
this.highlightedPixelCol != col)) {
|
||||
|
||||
// Clean the previously highlighted pixel:
|
||||
overlay.clear();
|
||||
}
|
||||
|
||||
// Show the current pixel targeted by the tool:
|
||||
overlay.setPixel(col, row, Constants.TOOL_TARGET_HIGHLIGHT_COLOR);
|
||||
|
||||
this.highlightedPixelCol = col;
|
||||
this.highlightedPixelRow = row;
|
||||
}
|
||||
};
|
||||
|
||||
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay) {};
|
||||
|
||||
/**
|
||||
* Bresenham line algorihtm: Get an array of pixels from
|
||||
* start and end coordinates.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
||||
* http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
ns.BaseTool.prototype.getLinePixels_ = function(x0, x1, y0, y1) {
|
||||
|
||||
var pixels = [];
|
||||
var dx = Math.abs(x1-x0);
|
||||
var dy = Math.abs(y1-y0);
|
||||
var sx = (x0 < x1) ? 1 : -1;
|
||||
var sy = (y0 < y1) ? 1 : -1;
|
||||
var err = dx-dy;
|
||||
|
||||
while(true){
|
||||
|
||||
// Do what you need to for this
|
||||
pixels.push({"col": x0, "row": y0});
|
||||
|
||||
if ((x0==x1) && (y0==y1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
var e2 = 2*err;
|
||||
if (e2>-dy){
|
||||
err -= dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 < dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
})();
|
85
preview/js/drawingtools/Circle.js
Normal file
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.Circle
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Circle = function() {
|
||||
this.toolId = "tool-circle";
|
||||
this.helpText = "Circle tool";
|
||||
|
||||
// Circle's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Circle, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Circle.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
ns.Circle.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
|
||||
// draw in overlay
|
||||
this.drawCircle_(col, row, color, overlay);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Circle.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
|
||||
// draw in frame to finalize
|
||||
this.drawCircle_(col, row, color, frame);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Circle.prototype.drawCircle_ = function (col, row, color, targetFrame) {
|
||||
var circlePoints = this.getCirclePixels_(this.startCol, this.startRow, col, row);
|
||||
for(var i = 0; i< circlePoints.length; i++) {
|
||||
// Change model:
|
||||
targetFrame.setPixel(circlePoints[i].col, circlePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Circle.prototype.getCirclePixels_ = function (x0, y0, x1, y1) {
|
||||
var coords = pskl.PixelUtils.getOrderedRectangleCoordinates(x0, y0, x1, y1);
|
||||
var xC = (coords.x0 + coords.x1)/2;
|
||||
var yC = (coords.y0 + coords.y1)/2;
|
||||
|
||||
var rX = coords.x1 - xC;
|
||||
var rY = coords.y1 - yC;
|
||||
|
||||
var pixels = [];
|
||||
var x, y, angle;
|
||||
for (x = coords.x0 ; x < coords.x1 ; x++) {
|
||||
angle = Math.acos((x - xC)/rX);
|
||||
y = Math.round(rY * Math.sin(angle) + yC);
|
||||
pixels.push({"col": x, "row": y});
|
||||
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
|
||||
}
|
||||
|
||||
for (y = coords.y0 ; y < coords.y1 ; y++) {
|
||||
angle = Math.asin((y - yC)/rY);
|
||||
x = Math.round(rX * Math.cos(angle) + xC);
|
||||
pixels.push({"col": x, "row": y});
|
||||
pixels.push({"col": 2*xC - x, "row": 2*yC - y});
|
||||
}
|
||||
return pixels;
|
||||
};
|
||||
})();
|
29
preview/js/drawingtools/ColorPicker.js
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.ColorPicker
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.ColorPicker = function() {
|
||||
this.toolId = "tool-colorpicker";
|
||||
this.helpText = "Color picker";
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ColorPicker, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.ColorPicker.prototype.applyToolAt = function(col, row, color, frame, overlay, context) {
|
||||
if (frame.containsPixel(col, row)) {
|
||||
var sampledColor = frame.getPixel(col, row);
|
||||
if (context.button == Constants.LEFT_BUTTON) {
|
||||
$.publish(Events.PRIMARY_COLOR_SELECTED, [sampledColor]);
|
||||
} else if (context.button == Constants.RIGHT_BUTTON) {
|
||||
$.publish(Events.SECONDARY_COLOR_SELECTED, [sampledColor]);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
23
preview/js/drawingtools/Eraser.js
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.Eraser
|
||||
*
|
||||
* @require Constants
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Eraser = function() {
|
||||
this.toolId = "tool-eraser";
|
||||
this.helpText = "Eraser tool";
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Eraser, ns.SimplePen);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Eraser.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.superclass.applyToolAt.call(this, col, row, Constants.TRANSPARENT_COLOR, frame, overlay);
|
||||
};
|
||||
})();
|
54
preview/js/drawingtools/Move.js
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.Move
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Move = function() {
|
||||
this.toolId = "tool-move";
|
||||
this.helpText = "Move tool";
|
||||
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Move, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Move.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
this.frameClone = frame.clone();
|
||||
};
|
||||
|
||||
ns.Move.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||
this.shiftFrame(colDiff, rowDiff, frame, this.frameClone);
|
||||
};
|
||||
|
||||
ns.Move.prototype.shiftFrame = function (colDiff, rowDiff, frame, reference) {
|
||||
var color;
|
||||
for (var col = 0 ; col < frame.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < frame.getHeight() ; row++) {
|
||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
||||
} else {
|
||||
color = Constants.TRANSPARENT_COLOR;
|
||||
}
|
||||
frame.setPixel(col, row, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Move.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
this.moveToolAt(col, row, color, frame, overlay);
|
||||
};
|
||||
})();
|
36
preview/js/drawingtools/PaintBucket.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.PaintBucket
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.PaintBucket = function() {
|
||||
this.toolId = "tool-paint-bucket";
|
||||
this.helpText = "Paint bucket tool";
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.PaintBucket, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.PaintBucket.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
|
||||
pskl.PixelUtils.paintSimilarConnectedPixelsFromFrame(frame, col, row, color);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
59
preview/js/drawingtools/Rectangle.js
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.Rectangle
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Rectangle = function() {
|
||||
this.toolId = "tool-rectangle";
|
||||
this.helpText = "Rectangle tool";
|
||||
|
||||
// Rectangle's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Rectangle, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Rectangle.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
ns.Rectangle.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
|
||||
// draw in overlay
|
||||
this.drawRectangle_(col, row, color, overlay);
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Rectangle.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(frame.containsPixel(col, row)) { // cancel if outside of canvas
|
||||
// draw in frame to finalize
|
||||
this.drawRectangle_(col, row, color, frame);
|
||||
}
|
||||
};
|
||||
|
||||
ns.Rectangle.prototype.drawRectangle_ = function (col, row, color, targetFrame) {
|
||||
var strokePoints = pskl.PixelUtils.getBoundRectanglePixels(this.startCol, this.startRow, col, row);
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// Change model:
|
||||
targetFrame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
})();
|
49
preview/js/drawingtools/SimplePen.js
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.SimplePen
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.SimplePen = function() {
|
||||
this.toolId = "tool-pen";
|
||||
this.helpText = "Pen tool";
|
||||
|
||||
this.previousCol = null;
|
||||
this.previousRow = null;
|
||||
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.SimplePen.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
if (frame.containsPixel(col, row)) {
|
||||
frame.setPixel(col, row, color);
|
||||
}
|
||||
this.previousCol = col;
|
||||
this.previousRow = row;
|
||||
};
|
||||
|
||||
ns.SimplePen.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
|
||||
// The pen movement is too fast for the mousemove frequency, there is a gap between the
|
||||
// current point and the previously drawn one.
|
||||
// We fill the gap by calculating missing dots (simple linear interpolation) and draw them.
|
||||
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
|
||||
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
|
||||
var coords = interpolatedPixels[i];
|
||||
this.applyToolAt(coords.col, coords.row, color, frame, overlay);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.applyToolAt(col, row, color, frame, overlay);
|
||||
}
|
||||
|
||||
this.previousCol = col;
|
||||
this.previousRow = row;
|
||||
};
|
||||
})();
|
80
preview/js/drawingtools/Stroke.js
Normal file
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.Stroke
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.Stroke = function() {
|
||||
this.toolId = "tool-stroke";
|
||||
this.helpText = "Stroke tool";
|
||||
|
||||
// Stroke's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.Stroke, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Stroke.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
// When drawing a stroke we don't change the model instantly, since the
|
||||
// user can move his cursor to change the stroke direction and length
|
||||
// dynamically. Instead we draw the (preview) stroke in a fake canvas that
|
||||
// overlay the drawing canvas.
|
||||
// We wait for the releaseToolAt callback to impact both the
|
||||
// frame model and canvas rendering.
|
||||
|
||||
// The fake canvas where we will draw the preview of the stroke:
|
||||
// Drawing the first point of the stroke in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
ns.Stroke.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
|
||||
// When the user moussemove (before releasing), we dynamically compute the
|
||||
// pixel to draw the line and draw this line in the overlay canvas:
|
||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||
|
||||
// Drawing current stroke:
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
|
||||
if(color == Constants.TRANSPARENT_COLOR) {
|
||||
// When mousemoving the stroke tool, we draw in the canvas overlay above the drawing canvas.
|
||||
// If the stroke color is transparent, we won't be
|
||||
// able to see it during the movement.
|
||||
// We set it to a semi-opaque white during the tool mousemove allowing to see colors below the stroke.
|
||||
// When the stroke tool will be released, It will draw a transparent stroke,
|
||||
// eg deleting the equivalent of a stroke.
|
||||
color = Constants.SELECTION_TRANSPARENT_COLOR;
|
||||
}
|
||||
overlay.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.Stroke.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
// If the stroke tool is released outside of the canvas, we cancel the stroke:
|
||||
// TODO: Mutualize this check in common method
|
||||
if(frame.containsPixel(col, row)) {
|
||||
// The user released the tool to draw a line. We will compute the pixel coordinate, impact
|
||||
// the model and draw them in the drawing canvas (not the fake overlay anymore)
|
||||
var strokePoints = this.getLinePixels_(this.startCol, col, this.startRow, row);
|
||||
for(var i = 0; i< strokePoints.length; i++) {
|
||||
// Change model:
|
||||
frame.setPixel(strokePoints[i].col, strokePoints[i].row, color);
|
||||
}
|
||||
}
|
||||
// For now, we are done with the stroke tool and don't need an overlay anymore:
|
||||
overlay.clear();
|
||||
};
|
||||
})();
|
46
preview/js/drawingtools/VerticalMirrorPen.js
Normal file
@ -0,0 +1,46 @@
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.VerticalMirrorPen = function() {
|
||||
this.toolId = "tool-vertical-mirror-pen";
|
||||
this.helpText = "vertical mirror pen tool";
|
||||
|
||||
this.swap = null;
|
||||
this.mirroredPreviousCol = null;
|
||||
this.mirroredPreviousRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
|
||||
|
||||
|
||||
ns.VerticalMirrorPen.prototype.setMirrorContext = function() {
|
||||
this.swap = this.previousCol;
|
||||
this.previousCol = this.mirroredPreviousCol;
|
||||
};
|
||||
|
||||
ns.VerticalMirrorPen.prototype.unsetMirrorContext = function() {
|
||||
this.mirroredPreviousCol = this.previousCol;
|
||||
this.previousCol = this.swap;
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.superclass.applyToolAt.call(this, col, row, color, frame, overlay);
|
||||
|
||||
var mirroredCol = this.getSymmetricCol_(col, frame);
|
||||
this.mirroredPreviousCol = mirroredCol;
|
||||
|
||||
this.setMirrorContext();
|
||||
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
|
||||
this.unsetMirrorContext();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.getSymmetricCol_ = function(col, frame) {
|
||||
return frame.getWidth() - col - 1;
|
||||
};
|
||||
})();
|
160
preview/js/drawingtools/selectiontools/BaseSelect.js
Normal file
@ -0,0 +1,160 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.BaseSelect
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.BaseSelect = function() {
|
||||
this.secondaryToolId = "tool-move";
|
||||
this.BodyRoot = $('body');
|
||||
|
||||
// Select's first point coordinates (set in applyToolAt)
|
||||
this.startCol = null;
|
||||
this.startRow = null;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.applyToolAt = function(col, row, color, frame, overlay) {
|
||||
this.startCol = col;
|
||||
this.startRow = row;
|
||||
|
||||
this.lastCol = col;
|
||||
this.lastRow = row;
|
||||
|
||||
// The select tool can be in two different state.
|
||||
// If the inital click of the tool is not on a selection, we go in "select"
|
||||
// mode to create a selection.
|
||||
// If the initial click is on a previous selection, we go in "moveSelection"
|
||||
// mode to allow to move the selection by drag'n dropping it.
|
||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||
|
||||
this.mode = "select";
|
||||
this.onSelectStart_(col, row, color, frame, overlay);
|
||||
}
|
||||
else {
|
||||
|
||||
this.mode = "moveSelection";
|
||||
this.onSelectionDragStart_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.moveToolAt = function(col, row, color, frame, overlay) {
|
||||
if(this.mode == "select") {
|
||||
|
||||
this.onSelect_(col, row, color, frame, overlay);
|
||||
}
|
||||
else if(this.mode == "moveSelection") {
|
||||
|
||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.releaseToolAt = function(col, row, color, frame, overlay) {
|
||||
if(this.mode == "select") {
|
||||
this.onSelectEnd_(col, row, color, frame, overlay);
|
||||
} else if(this.mode == "moveSelection") {
|
||||
|
||||
this.onSelectionDragEnd_(col, row, color, frame, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* If we mouseover the selection draw inside the overlay frame, show the 'move' cursor
|
||||
* instead of the 'select' one. It indicates that we can move the selection by dragndroping it.
|
||||
* @override
|
||||
*/
|
||||
ns.BaseSelect.prototype.moveUnactiveToolAt = function(col, row, color, frame, overlay) {
|
||||
|
||||
if(overlay.getPixel(col, row) != Constants.SELECTION_TRANSPARENT_COLOR) {
|
||||
// We're hovering the selection, show the move tool:
|
||||
this.BodyRoot.addClass(this.toolId);
|
||||
this.BodyRoot.removeClass(this.secondaryToolId);
|
||||
} else {
|
||||
// We're not hovering the selection, show create selection tool:
|
||||
this.BodyRoot.addClass(this.secondaryToolId);
|
||||
this.BodyRoot.removeClass(this.toolId);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* For each pixel in the selection draw it in white transparent on the tool overlay
|
||||
* @protected
|
||||
*/
|
||||
ns.BaseSelect.prototype.drawSelectionOnOverlay_ = function (selection, overlay) {
|
||||
var pixels = selection.pixels;
|
||||
for(var i=0, l=pixels.length; i<l; i++) {
|
||||
overlay.setPixel(pixels[i].col, pixels[i].row, Constants.SELECTION_TRANSPARENT_COLOR);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Move the overlay frame filled with semi-transparent pixels that represent the selection.
|
||||
* @private
|
||||
*/
|
||||
ns.BaseSelect.prototype.shiftOverlayFrame_ = function (colDiff, rowDiff, overlayFrame, reference) {
|
||||
var color;
|
||||
for (var col = 0 ; col < overlayFrame.getWidth() ; col++) {
|
||||
for (var row = 0 ; row < overlayFrame.getHeight() ; row++) {
|
||||
if (reference.containsPixel(col - colDiff, row - rowDiff)) {
|
||||
color = reference.getPixel(col - colDiff, row - rowDiff);
|
||||
} else {
|
||||
color = Constants.TRANSPARENT_COLOR;
|
||||
}
|
||||
overlayFrame.setPixel(col, row, color);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// The list of callbacks to implement by specialized tools to implement the selection creation behavior.
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {};
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {};
|
||||
/** @protected */
|
||||
ns.BaseSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {};
|
||||
|
||||
|
||||
// The list of callbacks that define the drag'n drop behavior of the selection.
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDragStart_ = function (col, row, color, frame, overlay) {
|
||||
// Since we will move the overlayFrame in which the current selection is rendered,
|
||||
// we clone it to have a reference for the later shifting process.
|
||||
this.overlayFrameReference = overlay.clone();
|
||||
};
|
||||
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDrag_ = function (col, row, color, frame, overlay) {
|
||||
var deltaCol = col - this.lastCol;
|
||||
var deltaRow = row - this.lastRow;
|
||||
|
||||
var colDiff = col - this.startCol, rowDiff = row - this.startRow;
|
||||
|
||||
// Shifting selection on overlay frame:
|
||||
this.shiftOverlayFrame_(colDiff, rowDiff, overlay, this.overlayFrameReference);
|
||||
|
||||
// Update selection model:
|
||||
$.publish(Events.SELECTION_MOVE_REQUEST, [deltaCol, deltaRow]);
|
||||
|
||||
this.lastCol = col;
|
||||
this.lastRow = row;
|
||||
};
|
||||
|
||||
/** @private */
|
||||
ns.BaseSelect.prototype.onSelectionDragEnd_ = function (col, row, color, frame, overlay) {
|
||||
this.onSelectionDrag_(col, row, color, frame, overlay);
|
||||
};
|
||||
})();
|
52
preview/js/drawingtools/selectiontools/RectangleSelect.js
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.RectangleSelect
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.RectangleSelect = function() {
|
||||
this.toolId = "tool-rectangle-select";
|
||||
this.helpText = "Rectangle selection tool";
|
||||
|
||||
ns.BaseSelect.call(this);
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.RectangleSelect, ns.BaseSelect);
|
||||
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||
// Drawing the first point of the rectangle in the fake overlay canvas:
|
||||
overlay.setPixel(col, row, color);
|
||||
};
|
||||
|
||||
/**
|
||||
* When creating the rectangle selection, we clear the current overlayFrame and
|
||||
* redraw the current rectangle based on the orgin coordinate and
|
||||
* the current mouse coordiinate in sprite.
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelect_ = function (col, row, color, frame, overlay) {
|
||||
overlay.clear();
|
||||
if(this.startCol == col &&this.startRow == row) {
|
||||
$.publish(Events.SELECTION_DISMISSED);
|
||||
} else {
|
||||
var selection = new pskl.selection.RectangularSelection(
|
||||
this.startCol, this.startRow, col, row);
|
||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
||||
this.drawSelectionOnOverlay_(selection, overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) {
|
||||
this.onSelect_(col, row, color, frame, overlay);
|
||||
};
|
||||
|
||||
})();
|
36
preview/js/drawingtools/selectiontools/ShapeSelect.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @provide pskl.drawingtools.ShapeSelect
|
||||
*
|
||||
* @require pskl.utils
|
||||
*/
|
||||
(function() {
|
||||
var ns = $.namespace("pskl.drawingtools");
|
||||
|
||||
ns.ShapeSelect = function() {
|
||||
this.toolId = "tool-shape-select";
|
||||
this.helpText = "Shape selection tool";
|
||||
|
||||
ns.BaseSelect.call(this);
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.ShapeSelect, ns.BaseSelect);
|
||||
|
||||
/**
|
||||
* For the shape select tool, you just need to click one time to create a selection.
|
||||
* So we jsut need to implement onSelectStart_ (no need for onSelect_ & onSelectEnd_)
|
||||
* @override
|
||||
*/
|
||||
ns.ShapeSelect.prototype.onSelectStart_ = function (col, row, color, frame, overlay) {
|
||||
// Clean previous selection:
|
||||
$.publish(Events.SELECTION_DISMISSED);
|
||||
overlay.clear();
|
||||
|
||||
// From the pixel cliked, get shape using an algorithm similar to the paintbucket one:
|
||||
var pixels = pskl.PixelUtils.getSimilarConnectedPixelsFromFrame(frame, col, row);
|
||||
var selection = new pskl.selection.ShapeSelection(pixels);
|
||||
|
||||
$.publish(Events.SELECTION_CREATED, [selection]);
|
||||
this.drawSelectionOnOverlay_(selection, overlay);
|
||||
};
|
||||
|
||||
})();
|
275
preview/js/lib/bootstrap/bootstrap.js
vendored
Normal file
@ -0,0 +1,275 @@
|
||||
/* ===========================================================
|
||||
* bootstrap-tooltip.js v2.1.1
|
||||
* http://twitter.github.com/bootstrap/javascript.html#tooltips
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ===========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
|
||||
!function ($) {
|
||||
|
||||
"use strict"; // jshint ;_;
|
||||
|
||||
|
||||
/* TOOLTIP PUBLIC CLASS DEFINITION
|
||||
* =============================== */
|
||||
|
||||
var Tooltip = function (element, options) {
|
||||
this.init('tooltip', element, options)
|
||||
}
|
||||
|
||||
Tooltip.prototype = {
|
||||
|
||||
constructor: Tooltip
|
||||
|
||||
, init: function (type, element, options) {
|
||||
var eventIn
|
||||
, eventOut
|
||||
|
||||
this.type = type
|
||||
this.$element = $(element)
|
||||
this.options = this.getOptions(options)
|
||||
this.enabled = true
|
||||
|
||||
if (this.options.trigger == 'click') {
|
||||
this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
|
||||
} else if (this.options.trigger != 'manual') {
|
||||
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
|
||||
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
|
||||
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
|
||||
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
|
||||
}
|
||||
|
||||
this.options.selector ?
|
||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||
this.fixTitle()
|
||||
}
|
||||
|
||||
, getOptions: function (options) {
|
||||
options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
|
||||
|
||||
if (options.delay && typeof options.delay == 'number') {
|
||||
options.delay = {
|
||||
show: options.delay
|
||||
, hide: options.delay
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
, enter: function (e) {
|
||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) return self.show()
|
||||
|
||||
clearTimeout(this.timeout)
|
||||
self.hoverState = 'in'
|
||||
this.timeout = setTimeout(function() {
|
||||
if (self.hoverState == 'in') self.show()
|
||||
}, self.options.delay.show)
|
||||
}
|
||||
|
||||
, leave: function (e) {
|
||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||
|
||||
if (this.timeout) clearTimeout(this.timeout)
|
||||
if (!self.options.delay || !self.options.delay.hide) return self.hide()
|
||||
|
||||
self.hoverState = 'out'
|
||||
this.timeout = setTimeout(function() {
|
||||
if (self.hoverState == 'out') self.hide()
|
||||
}, self.options.delay.hide)
|
||||
}
|
||||
|
||||
, show: function () {
|
||||
var $tip
|
||||
, inside
|
||||
, pos
|
||||
, actualWidth
|
||||
, actualHeight
|
||||
, placement
|
||||
, tp
|
||||
|
||||
if (this.hasContent() && this.enabled) {
|
||||
$tip = this.tip()
|
||||
this.setContent()
|
||||
|
||||
if (this.options.animation) {
|
||||
$tip.addClass('fade')
|
||||
}
|
||||
|
||||
placement = typeof this.options.placement == 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||
this.options.placement
|
||||
|
||||
inside = /in/.test(placement)
|
||||
|
||||
$tip
|
||||
.remove()
|
||||
.css({ top: 0, left: 0, display: 'block' })
|
||||
.appendTo(inside ? this.$element : document.body)
|
||||
|
||||
pos = this.getPosition(inside)
|
||||
|
||||
actualWidth = $tip[0].offsetWidth
|
||||
actualHeight = $tip[0].offsetHeight
|
||||
|
||||
switch (inside ? placement.split(' ')[1] : placement) {
|
||||
case 'bottom':
|
||||
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||
break
|
||||
case 'top':
|
||||
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||
break
|
||||
case 'left':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
|
||||
break
|
||||
case 'right':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
|
||||
break
|
||||
}
|
||||
|
||||
$tip
|
||||
.css(tp)
|
||||
.addClass(placement)
|
||||
.addClass('in')
|
||||
}
|
||||
}
|
||||
|
||||
, setContent: function () {
|
||||
var $tip = this.tip()
|
||||
, title = this.getTitle()
|
||||
|
||||
$tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
|
||||
$tip.removeClass('fade in top bottom left right')
|
||||
}
|
||||
|
||||
, hide: function () {
|
||||
var that = this
|
||||
, $tip = this.tip()
|
||||
|
||||
$tip.removeClass('in')
|
||||
|
||||
function removeWithAnimation() {
|
||||
var timeout = setTimeout(function () {
|
||||
$tip.off($.support.transition.end).remove()
|
||||
}, 500)
|
||||
|
||||
$tip.one($.support.transition.end, function () {
|
||||
clearTimeout(timeout)
|
||||
$tip.remove()
|
||||
})
|
||||
}
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
removeWithAnimation() :
|
||||
$tip.remove()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
, fixTitle: function () {
|
||||
var $e = this.$element
|
||||
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
|
||||
$e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
|
||||
}
|
||||
}
|
||||
|
||||
, hasContent: function () {
|
||||
return this.getTitle()
|
||||
}
|
||||
|
||||
, getPosition: function (inside) {
|
||||
return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
|
||||
width: this.$element[0].offsetWidth
|
||||
, height: this.$element[0].offsetHeight
|
||||
})
|
||||
}
|
||||
|
||||
, getTitle: function () {
|
||||
var title
|
||||
, $e = this.$element
|
||||
, o = this.options
|
||||
|
||||
title = $e.attr('data-original-title')
|
||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
, tip: function () {
|
||||
return this.$tip = this.$tip || $(this.options.template)
|
||||
}
|
||||
|
||||
, validate: function () {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide()
|
||||
this.$element = null
|
||||
this.options = null
|
||||
}
|
||||
}
|
||||
|
||||
, enable: function () {
|
||||
this.enabled = true
|
||||
}
|
||||
|
||||
, disable: function () {
|
||||
this.enabled = false
|
||||
}
|
||||
|
||||
, toggleEnabled: function () {
|
||||
this.enabled = !this.enabled
|
||||
}
|
||||
|
||||
, toggle: function () {
|
||||
this[this.tip().hasClass('in') ? 'hide' : 'show']()
|
||||
}
|
||||
|
||||
, destroy: function () {
|
||||
this.hide().$element.off('.' + this.type).removeData(this.type)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* TOOLTIP PLUGIN DEFINITION
|
||||
* ========================= */
|
||||
|
||||
$.fn.tooltip = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('tooltip')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.tooltip.Constructor = Tooltip
|
||||
|
||||
$.fn.tooltip.defaults = {
|
||||
animation: true
|
||||
, placement: 'top'
|
||||
, selector: false
|
||||
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
||||
, trigger: 'hover'
|
||||
, title: ''
|
||||
, delay: 0
|
||||
, html: true
|
||||
}
|
||||
|
||||
}(window.jQuery);
|
1
preview/js/lib/bootstrap/readme.txt
Normal file
@ -0,0 +1 @@
|
||||
Bootstrap custom build containing only the tooltip component
|
3
preview/js/lib/gif/gif.js
Normal file
12
preview/js/lib/gif/gif.worker.js
Normal file
52
preview/js/lib/iframeLoader.js
Normal file
@ -0,0 +1,52 @@
|
||||
(function () {
|
||||
/**
|
||||
* Depending on the value of the data-iframe-loader attribute, display or store the content of the iframe
|
||||
* @param {HTMLElement} iframe
|
||||
*/
|
||||
var processFrame = function (iframe) {
|
||||
var type = iframe.getAttribute('data-iframe-loader');
|
||||
if (type === "display") {
|
||||
displayFrame(iframe);
|
||||
} else if (type === "store") {
|
||||
storeFrame(iframe);
|
||||
} else {
|
||||
console.error('iframeLoader invalid type : ' + type);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace the existing iframe with the content of the iframe
|
||||
* If the iframe has a single root element, it will directly replace the iframe.
|
||||
* If there are several roots, a wrapping div will be created and will replace the iframe
|
||||
* @param {HTMLElement} iframe
|
||||
*/
|
||||
var displayFrame = function (iframe) {
|
||||
var div=document.createElement("div");
|
||||
div.innerHTML = iframe.contentWindow.document.body.innerHTML;
|
||||
if (div.children.length == 1) {
|
||||
div = div.children[0];
|
||||
}
|
||||
iframe.parentNode.replaceChild(div, iframe);
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the iframe content as a <script type="text/html" id={iframe-src}>{iframe-content}</script>
|
||||
* The content can later be accessed by getting the script (through getElementById for instance) and reading innerHTML
|
||||
* @param {HTMLElement} iframe
|
||||
*/
|
||||
var storeFrame = function (iframe) {
|
||||
var script=document.createElement("script");
|
||||
script.setAttribute("type", "text/html");
|
||||
script.setAttribute("id", iframe.getAttribute("src"));
|
||||
script.innerHTML = iframe.contentWindow.document.body.innerHTML;
|
||||
iframe.parentNode.removeChild(iframe);
|
||||
document.body.appendChild(script);
|
||||
};
|
||||
|
||||
window.iframeloader = {
|
||||
onLoad : function (event) {
|
||||
var iframe = event.target || event.srcElement;
|
||||
processFrame(iframe);
|
||||
}
|
||||
}
|
||||
})();
|
9227
preview/js/lib/jquery-1.8.0.js
vendored
Normal file
2252
preview/js/lib/jquery-ui-1.10.3.custom.js
vendored
Normal file
BIN
preview/js/lib/jsColor_1_4_0/arrow.gif
Normal file
After Width: | Height: | Size: 66 B |
BIN
preview/js/lib/jsColor_1_4_0/cross.gif
Normal file
After Width: | Height: | Size: 83 B |
12
preview/js/lib/jsColor_1_4_0/demo.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>jscolor demo</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script type="text/javascript" src="jscolor.js"></script>
|
||||
|
||||
Click here: <input class="color" value="66ff00">
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
preview/js/lib/jsColor_1_4_0/hs.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
preview/js/lib/jsColor_1_4_0/hv.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
927
preview/js/lib/jsColor_1_4_0/jscolor.js
Normal file
@ -0,0 +1,927 @@
|
||||
/**
|
||||
* jscolor, JavaScript Color Picker
|
||||
*
|
||||
* @version 1.4.0
|
||||
* @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
|
||||
* @author Jan Odvarko, http://odvarko.cz
|
||||
* @created 2008-06-15
|
||||
* @updated 2012-07-06
|
||||
* @link http://jscolor.com
|
||||
*/
|
||||
|
||||
|
||||
var jscolor = {
|
||||
|
||||
|
||||
dir : '', // location of jscolor directory (leave empty to autodetect)
|
||||
bindClass : 'color', // class name
|
||||
binding : true, // automatic binding via <input class="...">
|
||||
preloading : true, // use image preloading?
|
||||
|
||||
|
||||
install : function() {
|
||||
if (document.readyState === "complete") {
|
||||
jscolor.init();
|
||||
} else {
|
||||
jscolor.addEvent(window, 'load', jscolor.init);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
init : function() {
|
||||
if(jscolor.binding) {
|
||||
jscolor.bind();
|
||||
}
|
||||
if(jscolor.preloading) {
|
||||
jscolor.preload();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getDir : function() {
|
||||
return "/" + window.location.pathname.split("/")[1] + "/js/lib/jsColor_1_4_0/";
|
||||
},
|
||||
|
||||
|
||||
bind : function() {
|
||||
var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')\\s*(\\{[^}]*\\})?', 'i');
|
||||
var e = document.getElementsByTagName('input');
|
||||
for(var i=0; i<e.length; i+=1) {
|
||||
var m;
|
||||
if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
|
||||
var prop = {};
|
||||
if(m[3]) {
|
||||
try {
|
||||
prop = (new Function ('return (' + m[3] + ')'))();
|
||||
} catch(eInvalidProp) {}
|
||||
}
|
||||
e[i].color = new jscolor.color(e[i], prop);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
preload : function() {
|
||||
for(var fn in jscolor.imgRequire) {
|
||||
if(jscolor.imgRequire.hasOwnProperty(fn)) {
|
||||
jscolor.loadImage(fn);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
images : {
|
||||
pad : [ 181, 101 ],
|
||||
sld : [ 16, 101 ],
|
||||
cross : [ 15, 15 ],
|
||||
arrow : [ 7, 11 ]
|
||||
},
|
||||
|
||||
|
||||
imgRequire : {},
|
||||
imgLoaded : {},
|
||||
|
||||
|
||||
requireImage : function(filename) {
|
||||
jscolor.imgRequire[filename] = true;
|
||||
},
|
||||
|
||||
|
||||
loadImage : function(filename) {
|
||||
if(!jscolor.imgLoaded[filename]) {
|
||||
jscolor.imgLoaded[filename] = new Image();
|
||||
jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
fetchElement : function(mixed) {
|
||||
return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
|
||||
},
|
||||
|
||||
|
||||
addEvent : function(el, evnt, func) {
|
||||
if(el.addEventListener) {
|
||||
el.addEventListener(evnt, func, false);
|
||||
} else if(el.attachEvent) {
|
||||
el.attachEvent('on'+evnt, func);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
fireEvent : function(el, evnt) {
|
||||
if(!el) {
|
||||
return;
|
||||
}
|
||||
if(document.createEvent) {
|
||||
var ev = document.createEvent('HTMLEvents');
|
||||
ev.initEvent(evnt, true, true);
|
||||
el.dispatchEvent(ev);
|
||||
} else if(document.createEventObject) {
|
||||
var ev = document.createEventObject();
|
||||
el.fireEvent('on'+evnt, ev);
|
||||
} else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
|
||||
el['on'+evnt]();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getElementPos : function(e) {
|
||||
var e1=e, e2=e;
|
||||
var x=0, y=0;
|
||||
if(e1.offsetParent) {
|
||||
do {
|
||||
x += e1.offsetLeft;
|
||||
y += e1.offsetTop;
|
||||
} while(e1 = e1.offsetParent);
|
||||
}
|
||||
while((e2 = e2.parentNode) && e2.nodeName.toUpperCase() !== 'BODY') {
|
||||
x -= e2.scrollLeft;
|
||||
y -= e2.scrollTop;
|
||||
}
|
||||
return [x, y];
|
||||
},
|
||||
|
||||
|
||||
getElementSize : function(e) {
|
||||
return [e.offsetWidth, e.offsetHeight];
|
||||
},
|
||||
|
||||
|
||||
getRelMousePos : function(e) {
|
||||
var x = 0, y = 0;
|
||||
if (!e) { e = window.event; }
|
||||
if (typeof e.offsetX === 'number') {
|
||||
x = e.offsetX;
|
||||
y = e.offsetY;
|
||||
} else if (typeof e.layerX === 'number') {
|
||||
x = e.layerX;
|
||||
y = e.layerY;
|
||||
}
|
||||
return { x: x, y: y };
|
||||
},
|
||||
|
||||
|
||||
getViewPos : function() {
|
||||
if(typeof window.pageYOffset === 'number') {
|
||||
return [window.pageXOffset, window.pageYOffset];
|
||||
} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
|
||||
return [document.body.scrollLeft, document.body.scrollTop];
|
||||
} else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
|
||||
return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
|
||||
} else {
|
||||
return [0, 0];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getViewSize : function() {
|
||||
if(typeof window.innerWidth === 'number') {
|
||||
return [window.innerWidth, window.innerHeight];
|
||||
} else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
|
||||
return [document.body.clientWidth, document.body.clientHeight];
|
||||
} else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
|
||||
return [document.documentElement.clientWidth, document.documentElement.clientHeight];
|
||||
} else {
|
||||
return [0, 0];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
URI : function(uri) { // See RFC3986
|
||||
|
||||
this.scheme = null;
|
||||
this.authority = null;
|
||||
this.path = '';
|
||||
this.query = null;
|
||||
this.fragment = null;
|
||||
|
||||
this.parse = function(uri) {
|
||||
var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
|
||||
this.scheme = m[3] ? m[2] : null;
|
||||
this.authority = m[5] ? m[6] : null;
|
||||
this.path = m[7];
|
||||
this.query = m[9] ? m[10] : null;
|
||||
this.fragment = m[12] ? m[13] : null;
|
||||
return this;
|
||||
};
|
||||
|
||||
this.toString = function() {
|
||||
var result = '';
|
||||
if(this.scheme !== null) { result = result + this.scheme + ':'; }
|
||||
if(this.authority !== null) { result = result + '//' + this.authority; }
|
||||
if(this.path !== null) { result = result + this.path; }
|
||||
if(this.query !== null) { result = result + '?' + this.query; }
|
||||
if(this.fragment !== null) { result = result + '#' + this.fragment; }
|
||||
return result;
|
||||
};
|
||||
|
||||
this.toAbsolute = function(base) {
|
||||
var base = new jscolor.URI(base);
|
||||
var r = this;
|
||||
var t = new jscolor.URI;
|
||||
|
||||
if(base.scheme === null) { return false; }
|
||||
|
||||
if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
|
||||
r.scheme = null;
|
||||
}
|
||||
|
||||
if(r.scheme !== null) {
|
||||
t.scheme = r.scheme;
|
||||
t.authority = r.authority;
|
||||
t.path = removeDotSegments(r.path);
|
||||
t.query = r.query;
|
||||
} else {
|
||||
if(r.authority !== null) {
|
||||
t.authority = r.authority;
|
||||
t.path = removeDotSegments(r.path);
|
||||
t.query = r.query;
|
||||
} else {
|
||||
if(r.path === '') {
|
||||
t.path = base.path;
|
||||
if(r.query !== null) {
|
||||
t.query = r.query;
|
||||
} else {
|
||||
t.query = base.query;
|
||||
}
|
||||
} else {
|
||||
if(r.path.substr(0,1) === '/') {
|
||||
t.path = removeDotSegments(r.path);
|
||||
} else {
|
||||
if(base.authority !== null && base.path === '') {
|
||||
t.path = '/'+r.path;
|
||||
} else {
|
||||
t.path = base.path.replace(/[^\/]+$/,'')+r.path;
|
||||
}
|
||||
t.path = removeDotSegments(t.path);
|
||||
}
|
||||
t.query = r.query;
|
||||
}
|
||||
t.authority = base.authority;
|
||||
}
|
||||
t.scheme = base.scheme;
|
||||
}
|
||||
t.fragment = r.fragment;
|
||||
|
||||
return t;
|
||||
};
|
||||
|
||||
function removeDotSegments(path) {
|
||||
var out = '';
|
||||
while(path) {
|
||||
if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
|
||||
path = path.replace(/^\.+/,'').substr(1);
|
||||
} else if(path.substr(0,3)==='/./' || path==='/.') {
|
||||
path = '/'+path.substr(3);
|
||||
} else if(path.substr(0,4)==='/../' || path==='/..') {
|
||||
path = '/'+path.substr(4);
|
||||
out = out.replace(/\/?[^\/]*$/, '');
|
||||
} else if(path==='.' || path==='..') {
|
||||
path = '';
|
||||
} else {
|
||||
var rm = path.match(/^\/?[^\/]*/)[0];
|
||||
path = path.substr(rm.length);
|
||||
out = out + rm;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
if(uri) {
|
||||
this.parse(uri);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Usage example:
|
||||
* var myColor = new jscolor.color(myInputElement)
|
||||
*/
|
||||
|
||||
color : function(target, prop) {
|
||||
|
||||
|
||||
this.required = true; // refuse empty values?
|
||||
this.adjust = true; // adjust value to uniform notation?
|
||||
this.hash = false; // prefix color with # symbol?
|
||||
this.caps = true; // uppercase?
|
||||
this.slider = true; // show the value/saturation slider?
|
||||
this.valueElement = target; // value holder
|
||||
this.styleElement = target; // where to reflect current color
|
||||
this.onImmediateChange = null; // onchange callback (can be either string or function)
|
||||
this.hsv = [0, 0, 1]; // read-only 0-6, 0-1, 0-1
|
||||
this.rgb = [1, 1, 1]; // read-only 0-1, 0-1, 0-1
|
||||
this.minH = 0; // read-only 0-6
|
||||
this.maxH = 6; // read-only 0-6
|
||||
this.minS = 0; // read-only 0-1
|
||||
this.maxS = 1; // read-only 0-1
|
||||
this.minV = 0; // read-only 0-1
|
||||
this.maxV = 1; // read-only 0-1
|
||||
|
||||
this.pickerOnfocus = true; // display picker on focus?
|
||||
this.pickerMode = 'HSV'; // HSV | HVS
|
||||
this.pickerPosition = 'bottom'; // left | right | top | bottom
|
||||
this.pickerSmartPosition = true; // automatically adjust picker position when necessary
|
||||
this.pickerButtonHeight = 20; // px
|
||||
this.pickerClosable = false;
|
||||
this.pickerCloseText = 'Close';
|
||||
this.pickerButtonColor = 'ButtonText'; // px
|
||||
this.pickerFace = 10; // px
|
||||
this.pickerFaceColor = 'ThreeDFace'; // CSS color
|
||||
this.pickerBorder = 1; // px
|
||||
this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
|
||||
this.pickerInset = 1; // px
|
||||
this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
|
||||
this.pickerZIndex = 10000;
|
||||
|
||||
|
||||
for(var p in prop) {
|
||||
if(prop.hasOwnProperty(p)) {
|
||||
this[p] = prop[p];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.hidePicker = function() {
|
||||
if(isPickerOwner()) {
|
||||
removePicker();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.showPicker = function() {
|
||||
if(!isPickerOwner()) {
|
||||
var tp = jscolor.getElementPos(target); // target pos
|
||||
var ts = jscolor.getElementSize(target); // target size
|
||||
var vp = jscolor.getViewPos(); // view pos
|
||||
var vs = jscolor.getViewSize(); // view size
|
||||
var ps = getPickerDims(this); // picker size
|
||||
var a, b, c;
|
||||
switch(this.pickerPosition.toLowerCase()) {
|
||||
case 'left': a=1; b=0; c=-1; break;
|
||||
case 'right':a=1; b=0; c=1; break;
|
||||
case 'top': a=0; b=1; c=-1; break;
|
||||
default: a=0; b=1; c=1; break;
|
||||
}
|
||||
var l = (ts[b]+ps[b])/2;
|
||||
|
||||
// picker pos
|
||||
if (!this.pickerSmartPosition) {
|
||||
var pp = [
|
||||
tp[a],
|
||||
tp[b]+ts[b]-l+l*c
|
||||
];
|
||||
} else {
|
||||
var pp = [
|
||||
-vp[a]+tp[a]+ps[a] > vs[a] ?
|
||||
(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
|
||||
tp[a],
|
||||
-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
|
||||
(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
|
||||
(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
|
||||
];
|
||||
}
|
||||
drawPicker(pp[a], pp[b]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.importColor = function() {
|
||||
if(!valueElement) {
|
||||
this.exportColor();
|
||||
} else {
|
||||
if(!this.adjust) {
|
||||
if(!this.fromString(valueElement.value, leaveValue)) {
|
||||
styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
|
||||
styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
|
||||
styleElement.style.color = styleElement.jscStyle.color;
|
||||
this.exportColor(leaveValue | leaveStyle);
|
||||
}
|
||||
} else if(!this.required && /^\s*$/.test(valueElement.value)) {
|
||||
valueElement.value = '';
|
||||
styleElement.style.backgroundImage = styleElement.jscStyle.backgroundImage;
|
||||
styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
|
||||
styleElement.style.color = styleElement.jscStyle.color;
|
||||
this.exportColor(leaveValue | leaveStyle);
|
||||
|
||||
} else if(this.fromString(valueElement.value)) {
|
||||
// OK
|
||||
} else {
|
||||
this.exportColor();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.exportColor = function(flags) {
|
||||
if(!(flags & leaveValue) && valueElement) {
|
||||
var value = this.toString();
|
||||
if(this.caps) { value = value.toUpperCase(); }
|
||||
if(this.hash) { value = '#'+value; }
|
||||
valueElement.value = value;
|
||||
}
|
||||
if(!(flags & leaveStyle) && styleElement) {
|
||||
styleElement.style.backgroundImage = "none";
|
||||
styleElement.style.backgroundColor =
|
||||
'#'+this.toString();
|
||||
styleElement.style.color =
|
||||
0.213 * this.rgb[0] +
|
||||
0.715 * this.rgb[1] +
|
||||
0.072 * this.rgb[2]
|
||||
< 0.5 ? '#FFF' : '#000';
|
||||
}
|
||||
if(!(flags & leavePad) && isPickerOwner()) {
|
||||
redrawPad();
|
||||
}
|
||||
if(!(flags & leaveSld) && isPickerOwner()) {
|
||||
redrawSld();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.fromHSV = function(h, s, v, flags) { // null = don't change
|
||||
if(h !== null) { h = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, h)); }
|
||||
if(s !== null) { s = Math.max(0.0, this.minS, Math.min(1.0, this.maxS, s)); }
|
||||
if(v !== null) { v = Math.max(0.0, this.minV, Math.min(1.0, this.maxV, v)); }
|
||||
|
||||
this.rgb = HSV_RGB(
|
||||
h===null ? this.hsv[0] : (this.hsv[0]=h),
|
||||
s===null ? this.hsv[1] : (this.hsv[1]=s),
|
||||
v===null ? this.hsv[2] : (this.hsv[2]=v)
|
||||
);
|
||||
|
||||
this.exportColor(flags);
|
||||
};
|
||||
|
||||
|
||||
this.fromRGB = function(r, g, b, flags) { // null = don't change
|
||||
if(r !== null) { r = Math.max(0.0, Math.min(1.0, r)); }
|
||||
if(g !== null) { g = Math.max(0.0, Math.min(1.0, g)); }
|
||||
if(b !== null) { b = Math.max(0.0, Math.min(1.0, b)); }
|
||||
|
||||
var hsv = RGB_HSV(
|
||||
r===null ? this.rgb[0] : r,
|
||||
g===null ? this.rgb[1] : g,
|
||||
b===null ? this.rgb[2] : b
|
||||
);
|
||||
if(hsv[0] !== null) {
|
||||
this.hsv[0] = Math.max(0.0, this.minH, Math.min(6.0, this.maxH, hsv[0]));
|
||||
}
|
||||
if(hsv[2] !== 0) {
|
||||
this.hsv[1] = hsv[1]===null ? null : Math.max(0.0, this.minS, Math.min(1.0, this.maxS, hsv[1]));
|
||||
}
|
||||
this.hsv[2] = hsv[2]===null ? null : Math.max(0.0, this.minV, Math.min(1.0, this.maxV, hsv[2]));
|
||||
|
||||
// update RGB according to final HSV, as some values might be trimmed
|
||||
var rgb = HSV_RGB(this.hsv[0], this.hsv[1], this.hsv[2]);
|
||||
this.rgb[0] = rgb[0];
|
||||
this.rgb[1] = rgb[1];
|
||||
this.rgb[2] = rgb[2];
|
||||
|
||||
this.exportColor(flags);
|
||||
};
|
||||
|
||||
|
||||
this.fromString = function(hex, flags) {
|
||||
var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
|
||||
if(!m) {
|
||||
return false;
|
||||
} else {
|
||||
if(m[1].length === 6) { // 6-char notation
|
||||
this.fromRGB(
|
||||
parseInt(m[1].substr(0,2),16) / 255,
|
||||
parseInt(m[1].substr(2,2),16) / 255,
|
||||
parseInt(m[1].substr(4,2),16) / 255,
|
||||
flags
|
||||
);
|
||||
} else { // 3-char notation
|
||||
this.fromRGB(
|
||||
parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
|
||||
parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
|
||||
parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
|
||||
flags
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.toString = function() {
|
||||
return (
|
||||
(0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
|
||||
(0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
|
||||
(0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
function RGB_HSV(r, g, b) {
|
||||
var n = Math.min(Math.min(r,g),b);
|
||||
var v = Math.max(Math.max(r,g),b);
|
||||
var m = v - n;
|
||||
if(m === 0) { return [ null, 0, v ]; }
|
||||
var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
|
||||
return [ h===6?0:h, m/v, v ];
|
||||
}
|
||||
|
||||
|
||||
function HSV_RGB(h, s, v) {
|
||||
if(h === null) { return [ v, v, v ]; }
|
||||
var i = Math.floor(h);
|
||||
var f = i%2 ? h-i : 1-(h-i);
|
||||
var m = v * (1 - s);
|
||||
var n = v * (1 - s*f);
|
||||
switch(i) {
|
||||
case 6:
|
||||
case 0: return [v,n,m];
|
||||
case 1: return [n,v,m];
|
||||
case 2: return [m,v,n];
|
||||
case 3: return [m,n,v];
|
||||
case 4: return [n,m,v];
|
||||
case 5: return [v,m,n];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function removePicker() {
|
||||
delete jscolor.picker.owner;
|
||||
document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
|
||||
}
|
||||
|
||||
|
||||
function drawPicker(x, y) {
|
||||
if(!jscolor.picker) {
|
||||
jscolor.picker = {
|
||||
box : document.createElement('div'),
|
||||
boxB : document.createElement('div'),
|
||||
pad : document.createElement('div'),
|
||||
padB : document.createElement('div'),
|
||||
padM : document.createElement('div'),
|
||||
sld : document.createElement('div'),
|
||||
sldB : document.createElement('div'),
|
||||
sldM : document.createElement('div'),
|
||||
btn : document.createElement('div'),
|
||||
btnS : document.createElement('span'),
|
||||
btnT : document.createTextNode(THIS.pickerCloseText)
|
||||
};
|
||||
for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
|
||||
var seg = document.createElement('div');
|
||||
seg.style.height = segSize+'px';
|
||||
seg.style.fontSize = '1px';
|
||||
seg.style.lineHeight = '0';
|
||||
jscolor.picker.sld.appendChild(seg);
|
||||
}
|
||||
jscolor.picker.sldB.appendChild(jscolor.picker.sld);
|
||||
jscolor.picker.box.appendChild(jscolor.picker.sldB);
|
||||
jscolor.picker.box.appendChild(jscolor.picker.sldM);
|
||||
jscolor.picker.padB.appendChild(jscolor.picker.pad);
|
||||
jscolor.picker.box.appendChild(jscolor.picker.padB);
|
||||
jscolor.picker.box.appendChild(jscolor.picker.padM);
|
||||
jscolor.picker.btnS.appendChild(jscolor.picker.btnT);
|
||||
jscolor.picker.btn.appendChild(jscolor.picker.btnS);
|
||||
jscolor.picker.box.appendChild(jscolor.picker.btn);
|
||||
jscolor.picker.boxB.appendChild(jscolor.picker.box);
|
||||
}
|
||||
|
||||
var p = jscolor.picker;
|
||||
|
||||
// controls interaction
|
||||
p.box.onmouseup =
|
||||
p.box.onmouseout = function() { target.focus(); };
|
||||
p.box.onmousedown = function() { abortBlur=true; };
|
||||
p.box.onmousemove = function(e) {
|
||||
if (holdPad || holdSld) {
|
||||
holdPad && setPad(e);
|
||||
holdSld && setSld(e);
|
||||
if (document.selection) {
|
||||
document.selection.empty();
|
||||
} else if (window.getSelection) {
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
dispatchImmediateChange();
|
||||
}
|
||||
};
|
||||
p.padM.onmouseup =
|
||||
p.padM.onmouseout = function() { if(holdPad) { holdPad=false; jscolor.fireEvent(valueElement,'change'); } };
|
||||
p.padM.onmousedown = function(e) {
|
||||
// if the slider is at the bottom, move it up
|
||||
switch(modeID) {
|
||||
case 0: if (THIS.hsv[2] === 0) { THIS.fromHSV(null, null, 1.0); }; break;
|
||||
case 1: if (THIS.hsv[1] === 0) { THIS.fromHSV(null, 1.0, null); }; break;
|
||||
}
|
||||
holdPad=true;
|
||||
setPad(e);
|
||||
dispatchImmediateChange();
|
||||
};
|
||||
p.sldM.onmouseup =
|
||||
p.sldM.onmouseout = function() { if(holdSld) { holdSld=false; jscolor.fireEvent(valueElement,'change'); } };
|
||||
p.sldM.onmousedown = function(e) {
|
||||
holdSld=true;
|
||||
setSld(e);
|
||||
dispatchImmediateChange();
|
||||
};
|
||||
|
||||
// picker
|
||||
var dims = getPickerDims(THIS);
|
||||
p.box.style.width = dims[0] + 'px';
|
||||
p.box.style.height = dims[1] + 'px';
|
||||
|
||||
// picker border
|
||||
p.boxB.style.position = 'absolute';
|
||||
p.boxB.style.clear = 'both';
|
||||
p.boxB.style.left = x+'px';
|
||||
p.boxB.style.top = y+'px';
|
||||
p.boxB.style.zIndex = THIS.pickerZIndex;
|
||||
p.boxB.style.border = THIS.pickerBorder+'px solid';
|
||||
p.boxB.style.borderColor = THIS.pickerBorderColor;
|
||||
p.boxB.style.background = THIS.pickerFaceColor;
|
||||
|
||||
// pad image
|
||||
p.pad.style.width = jscolor.images.pad[0]+'px';
|
||||
p.pad.style.height = jscolor.images.pad[1]+'px';
|
||||
|
||||
// pad border
|
||||
p.padB.style.position = 'absolute';
|
||||
p.padB.style.left = THIS.pickerFace+'px';
|
||||
p.padB.style.top = THIS.pickerFace+'px';
|
||||
p.padB.style.border = THIS.pickerInset+'px solid';
|
||||
p.padB.style.borderColor = THIS.pickerInsetColor;
|
||||
|
||||
// pad mouse area
|
||||
p.padM.style.position = 'absolute';
|
||||
p.padM.style.left = '0';
|
||||
p.padM.style.top = '0';
|
||||
p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
|
||||
p.padM.style.height = p.box.style.height;
|
||||
p.padM.style.cursor = 'crosshair';
|
||||
|
||||
// slider image
|
||||
p.sld.style.overflow = 'hidden';
|
||||
p.sld.style.width = jscolor.images.sld[0]+'px';
|
||||
p.sld.style.height = jscolor.images.sld[1]+'px';
|
||||
|
||||
// slider border
|
||||
p.sldB.style.display = THIS.slider ? 'block' : 'none';
|
||||
p.sldB.style.position = 'absolute';
|
||||
p.sldB.style.right = THIS.pickerFace+'px';
|
||||
p.sldB.style.top = THIS.pickerFace+'px';
|
||||
p.sldB.style.border = THIS.pickerInset+'px solid';
|
||||
p.sldB.style.borderColor = THIS.pickerInsetColor;
|
||||
|
||||
// slider mouse area
|
||||
p.sldM.style.display = THIS.slider ? 'block' : 'none';
|
||||
p.sldM.style.position = 'absolute';
|
||||
p.sldM.style.right = '0';
|
||||
p.sldM.style.top = '0';
|
||||
p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
|
||||
p.sldM.style.height = p.box.style.height;
|
||||
try {
|
||||
p.sldM.style.cursor = 'pointer';
|
||||
} catch(eOldIE) {
|
||||
p.sldM.style.cursor = 'hand';
|
||||
}
|
||||
|
||||
// "close" button
|
||||
function setBtnBorder() {
|
||||
var insetColors = THIS.pickerInsetColor.split(/\s+/);
|
||||
var pickerOutsetColor = insetColors.length < 2 ? insetColors[0] : insetColors[1] + ' ' + insetColors[0] + ' ' + insetColors[0] + ' ' + insetColors[1];
|
||||
p.btn.style.borderColor = pickerOutsetColor;
|
||||
}
|
||||
p.btn.style.display = THIS.pickerClosable ? 'block' : 'none';
|
||||
p.btn.style.position = 'absolute';
|
||||
p.btn.style.left = THIS.pickerFace + 'px';
|
||||
p.btn.style.bottom = THIS.pickerFace + 'px';
|
||||
p.btn.style.padding = '0 15px';
|
||||
p.btn.style.height = '18px';
|
||||
p.btn.style.border = THIS.pickerInset + 'px solid';
|
||||
setBtnBorder();
|
||||
p.btn.style.color = THIS.pickerButtonColor;
|
||||
p.btn.style.font = '12px sans-serif';
|
||||
p.btn.style.textAlign = 'center';
|
||||
try {
|
||||
p.btn.style.cursor = 'pointer';
|
||||
} catch(eOldIE) {
|
||||
p.btn.style.cursor = 'hand';
|
||||
}
|
||||
p.btn.onmousedown = function () {
|
||||
THIS.hidePicker();
|
||||
};
|
||||
p.btnS.style.lineHeight = p.btn.style.height;
|
||||
|
||||
// load images in optimal order
|
||||
switch(modeID) {
|
||||
case 0: var padImg = 'hs.png'; break;
|
||||
case 1: var padImg = 'hv.png'; break;
|
||||
}
|
||||
p.padM.style.backgroundImage = "url('"+jscolor.getDir()+"cross.gif')";
|
||||
p.padM.style.backgroundRepeat = "no-repeat";
|
||||
p.sldM.style.backgroundImage = "url('"+jscolor.getDir()+"arrow.gif')";
|
||||
p.sldM.style.backgroundRepeat = "no-repeat";
|
||||
p.pad.style.backgroundImage = "url('"+jscolor.getDir()+padImg+"')";
|
||||
p.pad.style.backgroundRepeat = "no-repeat";
|
||||
p.pad.style.backgroundPosition = "0 0";
|
||||
|
||||
// place pointers
|
||||
redrawPad();
|
||||
redrawSld();
|
||||
|
||||
jscolor.picker.owner = THIS;
|
||||
document.getElementsByTagName('body')[0].appendChild(p.boxB);
|
||||
}
|
||||
|
||||
|
||||
function getPickerDims(o) {
|
||||
var dims = [
|
||||
2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[0] +
|
||||
(o.slider ? 2*o.pickerInset + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] : 0),
|
||||
o.pickerClosable ?
|
||||
4*o.pickerInset + 3*o.pickerFace + jscolor.images.pad[1] + o.pickerButtonHeight :
|
||||
2*o.pickerInset + 2*o.pickerFace + jscolor.images.pad[1]
|
||||
];
|
||||
return dims;
|
||||
}
|
||||
|
||||
|
||||
function redrawPad() {
|
||||
// redraw the pad pointer
|
||||
switch(modeID) {
|
||||
case 0: var yComponent = 1; break;
|
||||
case 1: var yComponent = 2; break;
|
||||
}
|
||||
var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
|
||||
var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
|
||||
jscolor.picker.padM.style.backgroundPosition =
|
||||
(THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
|
||||
(THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';
|
||||
|
||||
// redraw the slider image
|
||||
var seg = jscolor.picker.sld.childNodes;
|
||||
|
||||
switch(modeID) {
|
||||
case 0:
|
||||
var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
|
||||
for(var i=0; i<seg.length; i+=1) {
|
||||
seg[i].style.backgroundColor = 'rgb('+
|
||||
(rgb[0]*(1-i/seg.length)*100)+'%,'+
|
||||
(rgb[1]*(1-i/seg.length)*100)+'%,'+
|
||||
(rgb[2]*(1-i/seg.length)*100)+'%)';
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
|
||||
var i = Math.floor(THIS.hsv[0]);
|
||||
var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
|
||||
switch(i) {
|
||||
case 6:
|
||||
case 0: rgb=[0,1,2]; break;
|
||||
case 1: rgb=[1,0,2]; break;
|
||||
case 2: rgb=[2,0,1]; break;
|
||||
case 3: rgb=[2,1,0]; break;
|
||||
case 4: rgb=[1,2,0]; break;
|
||||
case 5: rgb=[0,2,1]; break;
|
||||
}
|
||||
for(var i=0; i<seg.length; i+=1) {
|
||||
s = 1 - 1/(seg.length-1)*i;
|
||||
c[1] = c[0] * (1 - s*f);
|
||||
c[2] = c[0] * (1 - s);
|
||||
seg[i].style.backgroundColor = 'rgb('+
|
||||
(c[rgb[0]]*100)+'%,'+
|
||||
(c[rgb[1]]*100)+'%,'+
|
||||
(c[rgb[2]]*100)+'%)';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function redrawSld() {
|
||||
// redraw the slider pointer
|
||||
switch(modeID) {
|
||||
case 0: var yComponent = 2; break;
|
||||
case 1: var yComponent = 1; break;
|
||||
}
|
||||
var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
|
||||
jscolor.picker.sldM.style.backgroundPosition =
|
||||
'0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
|
||||
}
|
||||
|
||||
|
||||
function isPickerOwner() {
|
||||
return jscolor.picker && jscolor.picker.owner === THIS;
|
||||
}
|
||||
|
||||
|
||||
function blurTarget() {
|
||||
if(valueElement === target) {
|
||||
THIS.importColor();
|
||||
}
|
||||
if(THIS.pickerOnfocus) {
|
||||
THIS.hidePicker();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function blurValue() {
|
||||
if(valueElement !== target) {
|
||||
THIS.importColor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setPad(e) {
|
||||
var mpos = jscolor.getRelMousePos(e);
|
||||
var x = mpos.x - THIS.pickerFace - THIS.pickerInset;
|
||||
var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
|
||||
switch(modeID) {
|
||||
case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break;
|
||||
case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setSld(e) {
|
||||
var mpos = jscolor.getRelMousePos(e);
|
||||
var y = mpos.y - THIS.pickerFace - THIS.pickerInset;
|
||||
switch(modeID) {
|
||||
case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break;
|
||||
case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function dispatchImmediateChange() {
|
||||
if (THIS.onImmediateChange) {
|
||||
var callback;
|
||||
if (typeof THIS.onImmediateChange === 'string') {
|
||||
callback = new Function (THIS.onImmediateChange);
|
||||
} else {
|
||||
callback = THIS.onImmediateChange;
|
||||
}
|
||||
callback.call(THIS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var THIS = this;
|
||||
var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
|
||||
var abortBlur = false;
|
||||
var
|
||||
valueElement = jscolor.fetchElement(this.valueElement),
|
||||
styleElement = jscolor.fetchElement(this.styleElement);
|
||||
var
|
||||
holdPad = false,
|
||||
holdSld = false;
|
||||
var
|
||||
leaveValue = 1<<0,
|
||||
leaveStyle = 1<<1,
|
||||
leavePad = 1<<2,
|
||||
leaveSld = 1<<3;
|
||||
|
||||
// target
|
||||
jscolor.addEvent(target, 'focus', function() {
|
||||
if(THIS.pickerOnfocus) { THIS.showPicker(); }
|
||||
});
|
||||
jscolor.addEvent(target, 'blur', function() {
|
||||
if(!abortBlur) {
|
||||
window.setTimeout(function(){ abortBlur || blurTarget(); abortBlur=false; }, 0);
|
||||
} else {
|
||||
abortBlur = false;
|
||||
}
|
||||
});
|
||||
|
||||
// valueElement
|
||||
if(valueElement) {
|
||||
var updateField = function() {
|
||||
THIS.fromString(valueElement.value, leaveValue);
|
||||
dispatchImmediateChange();
|
||||
};
|
||||
jscolor.addEvent(valueElement, 'keyup', updateField);
|
||||
jscolor.addEvent(valueElement, 'input', updateField);
|
||||
jscolor.addEvent(valueElement, 'blur', blurValue);
|
||||
valueElement.setAttribute('autocomplete', 'off');
|
||||
}
|
||||
|
||||
// styleElement
|
||||
if(styleElement) {
|
||||
styleElement.jscStyle = {
|
||||
backgroundImage : styleElement.style.backgroundImage,
|
||||
backgroundColor : styleElement.style.backgroundColor,
|
||||
color : styleElement.style.color
|
||||
};
|
||||
}
|
||||
|
||||
// require images
|
||||
switch(modeID) {
|
||||
case 0: jscolor.requireImage('hs.png'); break;
|
||||
case 1: jscolor.requireImage('hv.png'); break;
|
||||
}
|
||||
jscolor.requireImage('cross.gif');
|
||||
jscolor.requireImage('arrow.gif');
|
||||
|
||||
this.importColor();
|
||||
}
|
||||
|
||||
};
|