From 32d4f1c377fe7e16941225317b286426127ac83c Mon Sep 17 00:00:00 2001 From: grosbouddha Date: Mon, 27 May 2013 23:42:16 +0200 Subject: [PATCH 1/3] Activate jshint on JS codebase --- .gitignore | 3 +++ .jshintrc | 6 ------ Gruntfile.js | 15 +++++++++------ package.json | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 .jshintrc diff --git a/.gitignore b/.gitignore index 69858933..b54edf37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # mac artefacts *.DS_Store +# nodejs local installs +node_modules + # sublime text stuff (the -project should actually be shared, but then we'd have to share the same disk location) *.sublime-project *.sublime-workspace diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 1e98c389..00000000 --- a/.jshintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "evil": true, - "asi": true, - "smarttabs": true, - "eqnull": true -} \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js index b3fe6c29..b085f9b8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,15 +1,17 @@ module.exports = function(grunt) { grunt.initConfig({ jshint: { - options: { - jshintrc: '.jshintrc' - }, + /*options: { + "evil": true, + "asi": true, + "smarttabs": true, + "eqnull": true + },*/ files: [ 'Gruntfile.js', 'package.json', - // TODO(grosbouddha): change to js/**/*.js and fix the 10K jshint - // error messages or fine-tune .jshintrc file. - 'js/*.js' + 'js/**/*.js', + '!js/lib/**/*.js' // Exclude lib folder (note the leading !) ] }, connect: { @@ -41,6 +43,7 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-ghost'); + grunt.registerTask('lint', ['jshint']); grunt.registerTask('test', ['jshint', 'connect', 'ghost']); }; diff --git a/package.json b/package.json index 423bd727..c0ddfa95 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "test": "grunt test" }, "devDependencies": { - "grunt": "0.4.1", + "grunt": "~0.4.1", "grunt-contrib-connect": "0.3.0", "grunt-contrib-jshint": "0.5.4", "grunt-ghost": "1.0.12" } -} \ No newline at end of file +} From fba6693426738cee4f1f5625ff36b579748d8eae Mon Sep 17 00:00:00 2001 From: grosbouddha Date: Mon, 27 May 2013 23:42:53 +0200 Subject: [PATCH 2/3] Make jshint quiet now --- js/controller/AnimatedPreviewController.js | 120 ++--- js/controller/DrawingController.js | 2 +- js/controller/PreviewFilmController.js | 496 +++++++++--------- js/drawingtools/BaseTool.js | 40 +- js/drawingtools/Move.js | 108 ++-- js/drawingtools/VerticalMirrorPen.js | 4 +- js/drawingtools/selectiontools/BaseSelect.js | 2 +- .../selectiontools/RectangleSelect.js | 2 +- js/model/Frame.js | 6 +- js/model/FrameSheet.js | 32 +- js/rendering/CanvasRenderer.js | 2 +- js/rendering/DrawingLoop.js | 119 +++-- js/rendering/FrameRenderer.js | 34 +- js/rendering/SpritesheetRenderer.js | 4 +- js/selection/BaseSelection.js | 4 +- js/utils/CanvasUtils.js | 24 +- js/utils/PixelUtils.js | 9 +- 17 files changed, 506 insertions(+), 502 deletions(-) diff --git a/js/controller/AnimatedPreviewController.js b/js/controller/AnimatedPreviewController.js index b2825b00..9d7fe6b2 100644 --- a/js/controller/AnimatedPreviewController.js +++ b/js/controller/AnimatedPreviewController.js @@ -1,61 +1,61 @@ -(function () { - var ns = $.namespace("pskl.controller"); - ns.AnimatedPreviewController = function (framesheet, container, dpi) { - this.framesheet = framesheet; - this.container = container; - - this.elapsedTime = 0; - this.currentIndex = 0; - - this.fps = parseInt($("#preview-fps")[0].value, 10); - - 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 () { - $("#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; - $("#display-fps").html(this.fps + " 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.framesheet.hasFrameAtIndex(this.currentIndex)) { - this.currentIndex = 0; - this.elapsedTime = 0; - } - this.renderer.render(this.framesheet.getFrameByIndex(this.currentIndex)); - } - }; - - /** - * Calculate the preview DPI depending on the framesheet size - */ - ns.AnimatedPreviewController.prototype.calculateDPI_ = function () { - var framePixelHeight = this.framesheet.getCurrentFrame().getHeight(), - framePixelWidth = this.framesheet.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); - }; - - ns.AnimatedPreviewController.prototype.updateDPI_ = function () { - this.dpi = this.calculateDPI_(); - this.renderer.updateDPI(this.dpi); - } +(function () { + var ns = $.namespace("pskl.controller"); + ns.AnimatedPreviewController = function (framesheet, container, dpi) { + this.framesheet = framesheet; + this.container = container; + + this.elapsedTime = 0; + this.currentIndex = 0; + + this.fps = parseInt($("#preview-fps")[0].value, 10); + + 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 () { + $("#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; + $("#display-fps").html(this.fps + " 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.framesheet.hasFrameAtIndex(this.currentIndex)) { + this.currentIndex = 0; + this.elapsedTime = 0; + } + this.renderer.render(this.framesheet.getFrameByIndex(this.currentIndex)); + } + }; + + /** + * Calculate the preview DPI depending on the framesheet size + */ + ns.AnimatedPreviewController.prototype.calculateDPI_ = function () { + var framePixelHeight = this.framesheet.getCurrentFrame().getHeight(), + framePixelWidth = this.framesheet.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); + }; + + ns.AnimatedPreviewController.prototype.updateDPI_ = function () { + this.dpi = this.calculateDPI_(); + this.renderer.updateDPI(this.dpi); + }; })(); \ No newline at end of file diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index d66269da..22809a3a 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -173,7 +173,7 @@ */ ns.DrawingController.prototype.wrapEvtInfo_ = function (event) { var evtInfo = {}; - if (event.button == 0) { + if (event.button === 0) { evtInfo.button = Constants.LEFT_BUTTON; } else if (event.button == 2) { evtInfo.button = Constants.RIGHT_BUTTON; diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 469b0356..23eb6a31 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -1,249 +1,249 @@ -(function () { - var ns = $.namespace("pskl.controller"); - ns.PreviewFilmController = function (framesheet, container, dpi) { - - this.framesheet = framesheet; - this.container = container; - this.dpi = this.calculateDPI_(); - - this.redrawFlag = true; - - $.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this)); - $.subscribe(Events.FRAMESHEET_RESET, this.flagForRedraw_.bind(this)); - $.subscribe(Events.FRAMESHEET_RESET, this.refreshDPI_.bind(this)); - }; - - ns.PreviewFilmController.prototype.init = function() { - var addFrameButton = $('#add-frame-button')[0]; - addFrameButton.addEventListener('mousedown', this.addFrame.bind(this)); - }; - - ns.PreviewFilmController.prototype.addFrame = function () { - this.framesheet.addEmptyFrame(); - this.framesheet.setCurrentFrameIndex(this.framesheet.getFrameCount() - 1); - }; - - 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.createPreviews_ = function () { - - this.container.html(""); - // Manually remove tooltips since mouseout events were shortcut by the DOM refresh: - $(".tooltip").remove(); - - var frameCount = this.framesheet.getFrameCount(); - - for (var i = 0, l = frameCount; i < l ; i++) { - this.container.append(this.createInterstitialTile_(i)); - this.container.append(this.createPreviewTile_(i)); - } - this.container.append(this.createInterstitialTile_(frameCount)); - - var needDragndropBehavior = !!(frameCount > 1); - if(needDragndropBehavior) { - this.initDragndropBehavior_(); - } - }; - - /** - * @private - */ - ns.PreviewFilmController.prototype.createInterstitialTile_ = function (tileNumber) { - var interstitialTile = document.createElement("div"); - interstitialTile.className = "interstitial-tile" - interstitialTile.setAttribute("data-tile-type", "interstitial"); - interstitialTile.setAttribute("data-inject-drop-tile-at", tileNumber); - - return interstitialTile; - }; - - /** - * @private - */ - ns.PreviewFilmController.prototype.initDragndropBehavior_ = function () { - var tiles = $(".preview-tile"); - // Each preview film tile is draggable. - tiles.draggable( { - //containment: '.left-nav', - stack: '.preview-tile', - cursor: 'move', - revert: true, - start: function(event, ui) { - // We only show the fake interstitial tiles when starting the - // drag n drop interaction. We hide them when the DnD is done. - $('#preview-list').addClass("show-interstitial-tiles"); - }, - stop: function() { - $('#preview-list').removeClass("show-interstitial-tiles"); - } - }); - - - // Each preview film tile is a drop target. This allow us to swap two tiles. - // However, we want to be able to insert a tile between two other tiles. - // For that we created fake interstitial tiles that are used as drop targets as well. - var droppableTiles = $(".interstitial-tile"); - $.merge(droppableTiles, tiles); - - droppableTiles.droppable( { - accept: ".preview-tile", - tolerance: "pointer", - activeClass: "droppable-active", - hoverClass: "droppable-hover-active", - drop: $.proxy(this.onDrop_, this) - }); - }; - - /** - * @private - */ - ns.PreviewFilmController.prototype.onDrop_ = function( event, ui ) { - var activeFrame; - // When we drag from an element, the drag could start from a nested DOM element - // inside the drag target. We normalize that by taking the correct ancestor: - var originTile = $(event.srcElement).closest(".preview-tile"); - var originFrameId = parseInt(originTile.data("tile-number"), 10); - - var dropTarget = $(event.target); - if(dropTarget.data("tile-type") == "interstitial") { - var targetInsertionId = parseInt(dropTarget.data("inject-drop-tile-at"), 10); - // In case we drop outside of the tile container - if(isNaN(originFrameId) || isNaN(targetInsertionId)) { - return; - } - //console.log("origin-frame: "+originFrameId+" - targetInsertionId: "+ targetInsertionId) - this.framesheet.moveFrame(originFrameId, targetInsertionId); - - activeFrame = targetInsertionId; - // The last fake interstitial tile is outside of the framesheet array bound. - // It allow us to append after the very last element in this fake slot. - // However, when setting back the active frame, we have to make sure the - // frame does exist. - if(activeFrame > (this.framesheet.getFrameCount() - 1)) { - activeFrame = targetInsertionId - 1; - } - } else { - var targetSwapId = parseInt(dropTarget.data("tile-number"), 10); - // In case we drop outside of the tile container - if(isNaN(originFrameId) || isNaN(targetSwapId)) { - return; - } - //console.log("origin-frame: "+originFrameId+" - targetSwapId: "+ targetSwapId) - this.framesheet.swapFrames(originFrameId, targetSwapId); - activeFrame = targetSwapId; - } - - - $('#preview-list').removeClass("show-interstitial-tiles"); - - this.framesheet.setCurrentFrameIndex(activeFrame); - - // TODO(vincz): 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.framesheet.getFrameByIndex(tileNumber); - - var previewTileRoot = document.createElement("li"); - var classname = "preview-tile"; - previewTileRoot.setAttribute("data-tile-number", tileNumber); - - if (this.framesheet.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 actionContainer = document.createElement("DIV"); - actionContainer.className = "tile-action-container"; - - var canvasPreviewDuplicateAction = document.createElement("button"); - canvasPreviewDuplicateAction.setAttribute('rel', 'tooltip'); - canvasPreviewDuplicateAction.setAttribute('data-placement', 'right'); - canvasPreviewDuplicateAction.setAttribute('title', 'Duplicate this frame'); - canvasPreviewDuplicateAction.className = "tile-action duplicate-frame-action"; - actionContainer.appendChild(canvasPreviewDuplicateAction); - - canvasPreviewDuplicateAction.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.init(currentFrame); - - previewTileRoot.appendChild(canvasContainer); - - if(tileNumber > 0 || this.framesheet.getFrameCount() > 1) { - var canvasPreviewDeleteAction = document.createElement("button"); - canvasPreviewDeleteAction.setAttribute('rel', 'tooltip'); - canvasPreviewDeleteAction.setAttribute('data-placement', 'right'); - canvasPreviewDeleteAction.setAttribute('title', 'Delete this frame'); - canvasPreviewDeleteAction.className = "tile-action delete-frame-action" - canvasPreviewDeleteAction.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber)); - previewTileRoot.appendChild(canvasPreviewDeleteAction); - actionContainer.appendChild(canvasPreviewDeleteAction); - } - - previewTileRoot.appendChild(actionContainer); - - return previewTileRoot; - }; - - ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) { - // has not class tile-action: - if(!evt.target.classList.contains('tile-action')) { - this.framesheet.setCurrentFrameIndex(index); - } - }; - - ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) { - this.framesheet.removeFrameByIndex(index); - $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model - }; - - ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) { - this.framesheet.duplicateFrameByIndex(index); - $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model - this.framesheet.setCurrentFrameIndex(index + 1); - }; - - /** - * Calculate the preview DPI depending on the framesheet size - */ - ns.PreviewFilmController.prototype.calculateDPI_ = function () { - var previewSize = 128, - framePixelHeight = this.framesheet.getCurrentFrame().getHeight(), - framePixelWidth = this.framesheet.getCurrentFrame().getWidth(); - // TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?) - - return pskl.PixelUtils.calculateDPI(previewSize, previewSize, framePixelHeight, framePixelWidth); - }; +(function () { + var ns = $.namespace("pskl.controller"); + ns.PreviewFilmController = function (framesheet, container, dpi) { + + this.framesheet = framesheet; + this.container = container; + this.dpi = this.calculateDPI_(); + + this.redrawFlag = true; + + $.subscribe(Events.TOOL_RELEASED, this.flagForRedraw_.bind(this)); + $.subscribe(Events.FRAMESHEET_RESET, this.flagForRedraw_.bind(this)); + $.subscribe(Events.FRAMESHEET_RESET, this.refreshDPI_.bind(this)); + }; + + ns.PreviewFilmController.prototype.init = function() { + var addFrameButton = $('#add-frame-button')[0]; + addFrameButton.addEventListener('mousedown', this.addFrame.bind(this)); + }; + + ns.PreviewFilmController.prototype.addFrame = function () { + this.framesheet.addEmptyFrame(); + this.framesheet.setCurrentFrameIndex(this.framesheet.getFrameCount() - 1); + }; + + 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.createPreviews_ = function () { + + this.container.html(""); + // Manually remove tooltips since mouseout events were shortcut by the DOM refresh: + $(".tooltip").remove(); + + var frameCount = this.framesheet.getFrameCount(); + + for (var i = 0, l = frameCount; i < l ; i++) { + this.container.append(this.createInterstitialTile_(i)); + this.container.append(this.createPreviewTile_(i)); + } + this.container.append(this.createInterstitialTile_(frameCount)); + + var needDragndropBehavior = (frameCount > 1) ? true : false; + if(needDragndropBehavior) { + this.initDragndropBehavior_(); + } + }; + + /** + * @private + */ + ns.PreviewFilmController.prototype.createInterstitialTile_ = function (tileNumber) { + var interstitialTile = document.createElement("div"); + interstitialTile.className = "interstitial-tile"; + interstitialTile.setAttribute("data-tile-type", "interstitial"); + interstitialTile.setAttribute("data-inject-drop-tile-at", tileNumber); + + return interstitialTile; + }; + + /** + * @private + */ + ns.PreviewFilmController.prototype.initDragndropBehavior_ = function () { + var tiles = $(".preview-tile"); + // Each preview film tile is draggable. + tiles.draggable( { + //containment: '.left-nav', + stack: '.preview-tile', + cursor: 'move', + revert: true, + start: function(event, ui) { + // We only show the fake interstitial tiles when starting the + // drag n drop interaction. We hide them when the DnD is done. + $('#preview-list').addClass("show-interstitial-tiles"); + }, + stop: function() { + $('#preview-list').removeClass("show-interstitial-tiles"); + } + }); + + + // Each preview film tile is a drop target. This allow us to swap two tiles. + // However, we want to be able to insert a tile between two other tiles. + // For that we created fake interstitial tiles that are used as drop targets as well. + var droppableTiles = $(".interstitial-tile"); + $.merge(droppableTiles, tiles); + + droppableTiles.droppable( { + accept: ".preview-tile", + tolerance: "pointer", + activeClass: "droppable-active", + hoverClass: "droppable-hover-active", + drop: $.proxy(this.onDrop_, this) + }); + }; + + /** + * @private + */ + ns.PreviewFilmController.prototype.onDrop_ = function( event, ui ) { + var activeFrame; + // When we drag from an element, the drag could start from a nested DOM element + // inside the drag target. We normalize that by taking the correct ancestor: + var originTile = $(event.srcElement).closest(".preview-tile"); + var originFrameId = parseInt(originTile.data("tile-number"), 10); + + var dropTarget = $(event.target); + if(dropTarget.data("tile-type") == "interstitial") { + var targetInsertionId = parseInt(dropTarget.data("inject-drop-tile-at"), 10); + // In case we drop outside of the tile container + if(isNaN(originFrameId) || isNaN(targetInsertionId)) { + return; + } + //console.log("origin-frame: "+originFrameId+" - targetInsertionId: "+ targetInsertionId) + this.framesheet.moveFrame(originFrameId, targetInsertionId); + + activeFrame = targetInsertionId; + // The last fake interstitial tile is outside of the framesheet array bound. + // It allow us to append after the very last element in this fake slot. + // However, when setting back the active frame, we have to make sure the + // frame does exist. + if(activeFrame > (this.framesheet.getFrameCount() - 1)) { + activeFrame = targetInsertionId - 1; + } + } else { + var targetSwapId = parseInt(dropTarget.data("tile-number"), 10); + // In case we drop outside of the tile container + if(isNaN(originFrameId) || isNaN(targetSwapId)) { + return; + } + //console.log("origin-frame: "+originFrameId+" - targetSwapId: "+ targetSwapId) + this.framesheet.swapFrames(originFrameId, targetSwapId); + activeFrame = targetSwapId; + } + + + $('#preview-list').removeClass("show-interstitial-tiles"); + + this.framesheet.setCurrentFrameIndex(activeFrame); + + // TODO(vincz): 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.framesheet.getFrameByIndex(tileNumber); + + var previewTileRoot = document.createElement("li"); + var classname = "preview-tile"; + previewTileRoot.setAttribute("data-tile-number", tileNumber); + + if (this.framesheet.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 actionContainer = document.createElement("DIV"); + actionContainer.className = "tile-action-container"; + + var canvasPreviewDuplicateAction = document.createElement("button"); + canvasPreviewDuplicateAction.setAttribute('rel', 'tooltip'); + canvasPreviewDuplicateAction.setAttribute('data-placement', 'right'); + canvasPreviewDuplicateAction.setAttribute('title', 'Duplicate this frame'); + canvasPreviewDuplicateAction.className = "tile-action duplicate-frame-action"; + actionContainer.appendChild(canvasPreviewDuplicateAction); + + canvasPreviewDuplicateAction.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.init(currentFrame); + + previewTileRoot.appendChild(canvasContainer); + + if(tileNumber > 0 || this.framesheet.getFrameCount() > 1) { + var canvasPreviewDeleteAction = document.createElement("button"); + canvasPreviewDeleteAction.setAttribute('rel', 'tooltip'); + canvasPreviewDeleteAction.setAttribute('data-placement', 'right'); + canvasPreviewDeleteAction.setAttribute('title', 'Delete this frame'); + canvasPreviewDeleteAction.className = "tile-action delete-frame-action"; + canvasPreviewDeleteAction.addEventListener('click', this.onDeleteButtonClick_.bind(this, tileNumber)); + previewTileRoot.appendChild(canvasPreviewDeleteAction); + actionContainer.appendChild(canvasPreviewDeleteAction); + } + + previewTileRoot.appendChild(actionContainer); + + return previewTileRoot; + }; + + ns.PreviewFilmController.prototype.onPreviewClick_ = function (index, evt) { + // has not class tile-action: + if(!evt.target.classList.contains('tile-action')) { + this.framesheet.setCurrentFrameIndex(index); + } + }; + + ns.PreviewFilmController.prototype.onDeleteButtonClick_ = function (index, evt) { + this.framesheet.removeFrameByIndex(index); + $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model + }; + + ns.PreviewFilmController.prototype.onAddButtonClick_ = function (index, evt) { + this.framesheet.duplicateFrameByIndex(index); + $.publish(Events.LOCALSTORAGE_REQUEST); // Should come from model + this.framesheet.setCurrentFrameIndex(index + 1); + }; + + /** + * Calculate the preview DPI depending on the framesheet size + */ + ns.PreviewFilmController.prototype.calculateDPI_ = function () { + var previewSize = 128, + framePixelHeight = this.framesheet.getCurrentFrame().getHeight(), + framePixelWidth = this.framesheet.getCurrentFrame().getWidth(); + // TODO (julz) : should have a utility to get a Size from framesheet easily (what about empty framesheets though ?) + + return pskl.PixelUtils.calculateDPI(previewSize, previewSize, framePixelHeight, framePixelWidth); + }; })(); \ No newline at end of file diff --git a/js/drawingtools/BaseTool.js b/js/drawingtools/BaseTool.js index b0c1dba5..32524b68 100644 --- a/js/drawingtools/BaseTool.js +++ b/js/drawingtools/BaseTool.js @@ -46,27 +46,27 @@ 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; + var dy = Math.abs(y1-y0); + var sx = (x0 < x1) ? 1 : -1; + var sy = (y0 < y1) ? 1 : -1; + var err = dx-dy; - while(true){ + while(true){ - // Do what you need to for this - pixels.push({"col": x0, "row": y0}); + // 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; - }; + 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; + }; })(); diff --git a/js/drawingtools/Move.js b/js/drawingtools/Move.js index f24074f7..914123ce 100644 --- a/js/drawingtools/Move.js +++ b/js/drawingtools/Move.js @@ -1,54 +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); - }; -})(); +/* + * @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); + }; +})(); diff --git a/js/drawingtools/VerticalMirrorPen.js b/js/drawingtools/VerticalMirrorPen.js index c263653a..ea6ffef0 100644 --- a/js/drawingtools/VerticalMirrorPen.js +++ b/js/drawingtools/VerticalMirrorPen.js @@ -5,9 +5,9 @@ this.toolId = "tool-vertical-mirror-pen"; this.helpText = "vertical mirror pen tool"; - this.swap = null + this.swap = null; this.mirroredPreviousCol = null; - this.mirroredPreviousRow = null; + this.mirroredPreviousRow = null; }; pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen); diff --git a/js/drawingtools/selectiontools/BaseSelect.js b/js/drawingtools/selectiontools/BaseSelect.js index 7c2fe29c..2f2a75ee 100644 --- a/js/drawingtools/selectiontools/BaseSelect.js +++ b/js/drawingtools/selectiontools/BaseSelect.js @@ -103,7 +103,7 @@ } else { color = Constants.TRANSPARENT_COLOR; } - overlayFrame.setPixel(col, row, color) + overlayFrame.setPixel(col, row, color); } } }; diff --git a/js/drawingtools/selectiontools/RectangleSelect.js b/js/drawingtools/selectiontools/RectangleSelect.js index bd714747..9b32c133 100644 --- a/js/drawingtools/selectiontools/RectangleSelect.js +++ b/js/drawingtools/selectiontools/RectangleSelect.js @@ -45,7 +45,7 @@ * @override */ ns.RectangleSelect.prototype.onSelectEnd_ = function (col, row, color, frame, overlay) { - this.onSelect_(col, row, color, frame, overlay) + this.onSelect_(col, row, color, frame, overlay); }; })(); diff --git a/js/model/Frame.js b/js/model/Frame.js index f1624db0..ce73ca1c 100644 --- a/js/model/Frame.js +++ b/js/model/Frame.js @@ -8,7 +8,7 @@ }; ns.Frame.createEmpty = function (width, height) { - var pixels = ns.Frame.createEmptyPixelGrid_(width, height); + var pixels = ns.Frame.createEmptyPixelGrid_(width, height); return new ns.Frame(pixels); }; @@ -20,7 +20,7 @@ columnArray.push(Constants.TRANSPARENT_COLOR); } pixels[columnIndex] = columnArray; - } + } return pixels; }; @@ -36,7 +36,7 @@ * Returns a copy of the pixels used by the frame */ ns.Frame.prototype.getPixels = function () { - return this.clonePixels_(this.pixels) + return this.clonePixels_(this.pixels); }; /** diff --git a/js/model/FrameSheet.js b/js/model/FrameSheet.js index 1672c530..52c84c12 100644 --- a/js/model/FrameSheet.js +++ b/js/model/FrameSheet.js @@ -70,9 +70,9 @@ */ ns.FrameSheet.prototype.deserialize = function (serialized) { try { - this.load(JSON.parse(serialized)); + this.load(JSON.parse(serialized)); } catch (e) { - throw "Could not load serialized framesheet : " + e.message + throw "Could not load serialized framesheet : " + e.message; } }; @@ -83,20 +83,20 @@ * @param {String} serialized */ ns.FrameSheet.prototype.load = function (framesheet) { - this.frames = []; - for (var i = 0 ; i < framesheet.length ; i++) { - var frameCfg = framesheet[i]; - this.addFrame(new ns.Frame(frameCfg)); - } + this.frames = []; + for (var i = 0 ; i < framesheet.length ; i++) { + var frameCfg = framesheet[i]; + this.addFrame(new ns.Frame(frameCfg)); + } - if (this.hasFrameAtIndex(0)) { - this.height = this.getFrameByIndex(0).getHeight(); - this.width = this.getFrameByIndex(0).getWidth(); - this.setCurrentFrameIndex(0); - $.publish(Events.FRAME_SIZE_CHANGED); - } + if (this.hasFrameAtIndex(0)) { + this.height = this.getFrameByIndex(0).getHeight(); + this.width = this.getFrameByIndex(0).getWidth(); + this.setCurrentFrameIndex(0); + $.publish(Events.FRAME_SIZE_CHANGED); + } - $.publish(Events.FRAMESHEET_RESET); + $.publish(Events.FRAMESHEET_RESET); }; @@ -148,8 +148,8 @@ ns.FrameSheet.prototype.swapFrames = function(indexFrame1, indexFrame2) { if(isNaN(indexFrame1) || isNaN(indexFrame1) || - (!this.hasFrameAtIndex(indexFrame1) && !this.hasFrameAtIndex(indexFrame2))) { - throw "Bad indexes for swapFrames Framesheet function."; + (!this.hasFrameAtIndex(indexFrame1) && !this.hasFrameAtIndex(indexFrame2))) { + throw "Bad indexes for swapFrames Framesheet function."; } if(indexFrame1 == indexFrame2) { return; diff --git a/js/rendering/CanvasRenderer.js b/js/rendering/CanvasRenderer.js index c8539663..fb796798 100644 --- a/js/rendering/CanvasRenderer.js +++ b/js/rendering/CanvasRenderer.js @@ -33,4 +33,4 @@ var height = this.frame.getHeight() * this.dpi; return pskl.CanvasUtils.createCanvas(width, height); }; -})() \ No newline at end of file +})(); \ No newline at end of file diff --git a/js/rendering/DrawingLoop.js b/js/rendering/DrawingLoop.js index 9d13a239..672eb3de 100644 --- a/js/rendering/DrawingLoop.js +++ b/js/rendering/DrawingLoop.js @@ -1,58 +1,61 @@ -(function () { - var ns = $.namespace("pskl.rendering"); - - ns.DrawingLoop = function () { - this.requestAnimationFrame = this.getRequestAnimationFrameShim_(); - this.isRunning = false; - this.previousTime = 0; - this.callbacks = []; - }; - - ns.DrawingLoop.prototype.addCallback = function (callback, scope, args) { - var callbackObj = { - fn : callback, - scope : scope, - args : args - }; - this.callbacks.push(callbackObj); - return callbackObj; - }; - - ns.DrawingLoop.prototype.removeCallback = function (callbackObj) { - var index = this.callbacks.indexOf(callbackObj); - if (index != -1) { - this.callbacks.splice(index, 1); - } - }; - - ns.DrawingLoop.prototype.start = function () { - this.isRunning = true; - this.loop_(); - }; - - ns.DrawingLoop.prototype.loop_ = function () { - var currentTime = Date.now(); - var delta = currentTime - this.previousTime; - this.executeCallbacks_(delta); - this.previousTime = currentTime; - this.requestAnimationFrame.call(window, this.loop_.bind(this)); - }; - - ns.DrawingLoop.prototype.executeCallbacks_ = function (deltaTime) { - for (var i = 0 ; i < this.callbacks.length ; i++) { - var cb = this.callbacks[i]; - cb.fn.call(cb.scope, deltaTime, cb.args); - } - }; - - ns.DrawingLoop.prototype.stop = function () { - this.isRunning = false; - }; - - ns.DrawingLoop.prototype.getRequestAnimationFrameShim_ = function () { - var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {window.setTimeout(callback, 1000/60)}; - - return requestAnimationFrame; - } -})() \ No newline at end of file +(function () { + var ns = $.namespace("pskl.rendering"); + + ns.DrawingLoop = function () { + this.requestAnimationFrame = this.getRequestAnimationFrameShim_(); + this.isRunning = false; + this.previousTime = 0; + this.callbacks = []; + }; + + ns.DrawingLoop.prototype.addCallback = function (callback, scope, args) { + var callbackObj = { + fn : callback, + scope : scope, + args : args + }; + this.callbacks.push(callbackObj); + return callbackObj; + }; + + ns.DrawingLoop.prototype.removeCallback = function (callbackObj) { + var index = this.callbacks.indexOf(callbackObj); + if (index != -1) { + this.callbacks.splice(index, 1); + } + }; + + ns.DrawingLoop.prototype.start = function () { + this.isRunning = true; + this.loop_(); + }; + + ns.DrawingLoop.prototype.loop_ = function () { + var currentTime = Date.now(); + var delta = currentTime - this.previousTime; + this.executeCallbacks_(delta); + this.previousTime = currentTime; + this.requestAnimationFrame.call(window, this.loop_.bind(this)); + }; + + ns.DrawingLoop.prototype.executeCallbacks_ = function (deltaTime) { + for (var i = 0 ; i < this.callbacks.length ; i++) { + var cb = this.callbacks[i]; + cb.fn.call(cb.scope, deltaTime, cb.args); + } + }; + + ns.DrawingLoop.prototype.stop = function () { + this.isRunning = false; + }; + + ns.DrawingLoop.prototype.getRequestAnimationFrameShim_ = function () { + var requestAnimationFrame = window.requestAnimationFrame || + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + window.msRequestAnimationFrame || + function (callback) { window.setTimeout(callback, 1000/60); }; + + return requestAnimationFrame; + }; +})(); \ No newline at end of file diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index ff534347..e4fec384 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -8,7 +8,7 @@ }; renderingOptions = $.extend(true, {}, this.defaultRenderingOptions, renderingOptions); - if(container == undefined) { + if(container === undefined) { throw "Bad FrameRenderer initialization. undefined."; } @@ -28,7 +28,7 @@ if(this.hasGrid) { $.subscribe(Events.GRID_DISPLAY_STATE_CHANGED, $.proxy(this.showGrid, this)); - } + } }; ns.FrameRenderer.prototype.init = function (frame) { @@ -78,15 +78,15 @@ /** * Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered * frame) into a sprite coordinate in column and row. - * @public - */ - ns.FrameRenderer.prototype.convertPixelCoordinatesIntoSpriteCoordinate = function(coords) { - var cellSize = this.dpi + this.gridStrokeWidth; - return { - "col" : (coords.x - coords.x % cellSize) / cellSize, - "row" : (coords.y - coords.y % cellSize) / cellSize - }; - }; + * @public + */ + ns.FrameRenderer.prototype.convertPixelCoordinatesIntoSpriteCoordinate = function(coords) { + var cellSize = this.dpi + this.gridStrokeWidth; + return { + "col" : (coords.x - coords.x % cellSize) / cellSize, + "row" : (coords.y - coords.y % cellSize) / cellSize + }; + }; /** * @private @@ -103,15 +103,15 @@ ctx.lineWidth = Constants.GRID_STROKE_WIDTH; ctx.strokeStyle = Constants.GRID_STROKE_COLOR; for(var c=1; c < col; c++) { - ctx.moveTo(this.getFramePos_(c), 0); - ctx.lineTo(this.getFramePos_(c), height); - ctx.stroke(); + ctx.moveTo(this.getFramePos_(c), 0); + ctx.lineTo(this.getFramePos_(c), height); + ctx.stroke(); } for(var r=1; r < row; r++) { - ctx.moveTo(0, this.getFramePos_(r)); - ctx.lineTo(width, this.getFramePos_(r)); - ctx.stroke(); + ctx.moveTo(0, this.getFramePos_(r)); + ctx.lineTo(width, this.getFramePos_(r)); + ctx.stroke(); } }; diff --git a/js/rendering/SpritesheetRenderer.js b/js/rendering/SpritesheetRenderer.js index b3581c5a..d7d98191 100644 --- a/js/rendering/SpritesheetRenderer.js +++ b/js/rendering/SpritesheetRenderer.js @@ -19,7 +19,7 @@ }; /** - * TODO : (Julz) Mutualize with code already present in FrameRenderer + * TODO(juliandescottes): Mutualize with code already present in FrameRenderer */ ns.SpritesheetRenderer.prototype.drawFrameInCanvas_ = function (frame, canvas, offsetWidth, offsetHeight) { var context = canvas.getContext('2d'); @@ -41,7 +41,7 @@ var height = this.framesheet.getHeight(); return pskl.CanvasUtils.createCanvas(width, height); } else { - throw "Cannot render empty Spritesheet" + throw "Cannot render empty Spritesheet"; } }; diff --git a/js/selection/BaseSelection.js b/js/selection/BaseSelection.js index e0a1fc81..82583445 100644 --- a/js/selection/BaseSelection.js +++ b/js/selection/BaseSelection.js @@ -17,7 +17,7 @@ movedPixel = this.pixels[i]; movedPixel.col += colDiff; movedPixel.row += rowDiff; - movedPixels.push(movedPixel) + movedPixels.push(movedPixel); } this.pixels = movedPixels; }; @@ -27,7 +27,7 @@ for(var i=0, l=this.pixels.length; i 10 * cellCount) { - console.log("loop breaker called") + console.log("loop breaker called"); break; } } From ec996d80b495ed8ca037a5140c0334a83df82e36 Mon Sep 17 00:00:00 2001 From: grosbouddha Date: Mon, 27 May 2013 23:57:39 +0200 Subject: [PATCH 3/3] Adding notes to run Grunt tasks --- Gruntfile.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index b085f9b8..15a6ad5f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,3 +1,15 @@ +/** + * How to run grunt tasks: + * - At project root, run 'npm install' - It will install nodedependencies declared in package,json in /.node_modules + * - install grunt CLI tools globally, run 'npm install -g grunt-cli' + * - run a grunt target defined in Gruntfiles.js, ex: 'grunt lint' + * + * Note: The 'ghost' grunt task have special deps on CasperJS and phantomjs. + * For now, It's configured to run only on TravisCI where these deps are + * correctly defined. + * If you run this task locally, it may require some env set up first. + */ + module.exports = function(grunt) { grunt.initConfig({ jshint: { @@ -45,5 +57,4 @@ module.exports = function(grunt) { grunt.registerTask('lint', ['jshint']); grunt.registerTask('test', ['jshint', 'connect', 'ghost']); - };