{"version":3,"file":"drawingboard.min.js","sources":["../src/drawingboard.js"],"sourcesContent":["define(['jquery'], function($) {\n\n// -- Original code starts here\n/* drawingboard.js v0.4.2 - https://github.com/Leimi/drawingboard.js\n* Copyright (c) 2013 Emmanuel Pelletier\n* Licensed MIT */\nvar DrawingBoard = {};\n/**\n * pass the id of the html element to put the drawing board into\n * and some options : {\n *\tcontrols: array of controls to initialize with the drawingboard. 'Colors', 'Size', and 'Navigation' by default\n *\t\tinstead of simple strings, you can pass an object to define a control opts\n *\t\tie ['Color', { Navigation: { reset: false }}]\n *\tcontrolsPosition: \"top left\" by default. Define where to put the controls: at the \"top\" or \"bottom\" of the canvas, aligned to \"left\"/\"right\"/\"center\"\n *\tbackground: background of the drawing board. Give a hex color or an image url \"#ffffff\" (white) by default\n *\tcolor: pencil color (\"#000000\" by default)\n *\tsize: pencil size (3 by default)\n *\twebStorage: 'session', 'local' or false ('session' by default). store the current drawing in session or local storage and restore it when you come back\n *\tdroppable: true or false (false by default). If true, dropping an image on the canvas will include it and allow you to draw on it,\n *\terrorMessage: html string to put in the board's element on browsers that don't support canvas.\n * }\n */\nDrawingBoard.Board = function (id, opts) {\n    this.opts = $.extend({}, DrawingBoard.Board.defaultOpts, opts);\n\n    this.ev = new DrawingBoard.Utils.MicroEvent();\n\n    this.id = id;\n    this.$el = $(document.getElementById(id));\n    if (!this.$el.length)\n        return false;\n\n    var tpl = '<div class=\"drawing-board-canvas-wrapper\"></canvas><canvas class=\"drawing-board-canvas\"></canvas><div class=\"drawing-board-cursor drawing-board-utils-hidden\"></div></div>';\n    if (this.opts.controlsPosition.indexOf(\"bottom\") > -1) tpl += '<div class=\"drawing-board-controls\"></div>';\n    else tpl = '<div class=\"drawing-board-controls\"></div>' + tpl;\n\n    this.$el.addClass('drawing-board').append(tpl);\n    this.dom = {\n        $canvasWrapper: this.$el.find('.drawing-board-canvas-wrapper'),\n        $canvas: this.$el.find('.drawing-board-canvas'),\n        $cursor: this.$el.find('.drawing-board-cursor'),\n        $controls: this.$el.find('.drawing-board-controls')\n    };\n\n    $.each(['left', 'right', 'center'], $.proxy(function (n, val) {\n        if (this.opts.controlsPosition.indexOf(val) > -1) {\n            this.dom.$controls.attr('data-align', val);\n            return false;\n        }\n    }, this));\n\n    this.canvas = this.dom.$canvas.get(0);\n    this.ctx = this.canvas && this.canvas.getContext && this.canvas.getContext('2d') ? this.canvas.getContext('2d') : null;\n    this.color = this.opts.color;\n\n    if (!this.ctx) {\n        if (this.opts.errorMessage)\n            this.$el.html(this.opts.errorMessage);\n        return false;\n    }\n\n    this.storage = this._getStorage();\n\n    this.initHistory();\n    //init default board values before controls are added (mostly pencil color and size)\n    this.reset({webStorage: false, history: false, background: false});\n    //init controls (they will need the default board values to work like pencil color and size)\n    this.initControls();\n    //set board's size after the controls div is added\n    this.resize();\n    //reset the board to take all resized space\n    this.reset({webStorage: false, history: true, background: true});\n    this.restoreWebStorage();\n    this.initDropEvents();\n    this.initDrawEvents();\n};\n\n\nDrawingBoard.Board.defaultOpts = {\n    controls: ['Color', 'DrawingMode', 'Size', 'Navigation'],\n    controlsPosition: \"top left\",\n    color: \"#000000\",\n    size: 1,\n    background: \"#fff\",\n    eraserColor: \"background\",\n    webStorage: 'session',\n    droppable: false,\n    enlargeYourContainer: false,\n    errorMessage: \"<p>It seems you use an obsolete browser. <a href=\\\"http://browsehappy.com/\\\" target=\\\"_blank\\\">Update it</a> to start drawing.</p>\"\n};\n\n\nDrawingBoard.Board.prototype = {\n\n    /**\n     * Canvas reset/resize methods: put back the canvas to its default values\n     *\n     * depending on options, can set color, size, background back to default values\n     * and store the reseted canvas in webstorage and history queue\n     *\n     * resize values depend on the `enlargeYourContainer` option\n     */\n\n    reset: function (opts) {\n        opts = $.extend({\n            color: this.opts.color,\n            size: this.opts.size,\n            webStorage: true,\n            history: true,\n            background: false\n        }, opts);\n\n        this.setMode('pencil');\n\n        if (opts.background) this.resetBackground(this.opts.background, false);\n\n        if (opts.color) this.setColor(opts.color);\n        if (opts.size) this.ctx.lineWidth = opts.size;\n\n        this.ctx.lineCap = \"round\";\n        this.ctx.lineJoin = \"round\";\n        // this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.width);\n\n        if (opts.webStorage) this.saveWebStorage();\n\n        if (opts.history) this.saveHistory();\n\n        this.blankCanvas = this.getImg();\n\n        this.ev.trigger('board:reset', opts);\n    },\n\n    resetBackground: function (background, historize) {\n        background = background || this.opts.background;\n        historize = typeof historize !== \"undefined\" ? historize : true;\n        var bgIsColor = DrawingBoard.Utils.isColor(background);\n        var prevMode = this.getMode();\n        this.setMode('pencil');\n        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.width);\n        if (bgIsColor) {\n            this.ctx.fillStyle = background;\n            this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n        } else if (background)\n            this.setImg(background);\n        this.setMode(prevMode);\n        if (historize) this.saveHistory();\n    },\n\n    resize: function () {\n        this.dom.$controls.toggleClass('drawing-board-controls-hidden', (!this.controls || !this.controls.length));\n\n        var canvasWidth, canvasHeight;\n        var widths = [\n            this.$el.width(),\n            DrawingBoard.Utils.boxBorderWidth(this.$el),\n            DrawingBoard.Utils.boxBorderWidth(this.dom.$canvasWrapper, true, true)\n        ];\n        var heights = [\n            this.$el.height(),\n            DrawingBoard.Utils.boxBorderHeight(this.$el),\n            this.dom.$controls.height(),\n            DrawingBoard.Utils.boxBorderHeight(this.dom.$controls, false, true),\n            DrawingBoard.Utils.boxBorderHeight(this.dom.$canvasWrapper, true, true)\n        ];\n        var that = this;\n        var sum = function (values, multiplier) { //make the sum of all array values\n            multiplier = multiplier || 1;\n            var res = values[0];\n            for (var i = 1; i < values.length; i++) {\n                res = res + (values[i] * multiplier);\n            }\n            return res;\n        };\n        var sub = function (values) {\n            return sum(values, -1);\n        }; //substract all array values from the first one\n\n        if (this.opts.enlargeYourContainer) {\n            canvasWidth = this.$el.width();\n            canvasHeight = this.$el.height();\n\n            this.$el.width(sum(widths));\n            this.$el.height(sum(heights));\n        } else {\n            canvasWidth = sub(widths);\n            canvasHeight = sub(heights);\n        }\n\n        this.dom.$canvasWrapper.css('width', canvasWidth + 'px');\n        this.dom.$canvasWrapper.css('height', canvasHeight + 'px');\n\n        this.dom.$canvas.css('width', canvasWidth + 'px');\n        this.dom.$canvas.css('height', canvasHeight + 'px');\n\n        this.canvas.width = canvasWidth;\n        this.canvas.height = canvasHeight;\n    },\n\n\n    /**\n     * Controls:\n     * the drawing board can has various UI elements to control it.\n     * one control is represented by a class in the namespace DrawingBoard.Control\n     * it must have a $el property (jQuery object), representing the html element to append on the drawing board at initialization.\n     *\n     */\n\n    initControls: function () {\n        this.controls = [];\n        if (!this.opts.controls.length || !DrawingBoard.Control) return false;\n        for (var i = 0; i < this.opts.controls.length; i++) {\n            var c = null;\n            if (typeof this.opts.controls[i] == \"string\")\n                c = new window['DrawingBoard']['Control'][this.opts.controls[i]](this);\n            else if (typeof this.opts.controls[i] == \"object\") {\n                for (var controlName in this.opts.controls[i]) break;\n                c = new window['DrawingBoard']['Control'][controlName](this, this.opts.controls[i][controlName]);\n            }\n            if (c) {\n                this.addControl(c);\n            }\n        }\n    },\n\n    //add a new control or an existing one at the position you want in the UI\n    //to add a totally new control, you can pass a string with the js class as 1st parameter and control options as 2nd ie \"addControl('Navigation', { reset: false }\"\n    //the last parameter (2nd or 3rd depending on the situation) is always the position you want to place the control at\n    addControl: function (control, optsOrPos, pos) {\n        if (typeof control !== \"string\" && (typeof control !== \"object\" || !control instanceof DrawingBoard.Control))\n            return false;\n\n        var opts = typeof optsOrPos == \"object\" ? optsOrPos : {};\n        pos = pos ? pos * 1 : (typeof optsOrPos == \"number\" ? optsOrPos : null);\n\n        if (typeof control == \"string\")\n            control = new window['DrawingBoard']['Control'][control](this, opts);\n\n        if (pos)\n            this.dom.$controls.children().eq(pos).before(control.$el);\n        else\n            this.dom.$controls.append(control.$el);\n\n        if (!this.controls)\n            this.controls = [];\n        this.controls.push(control);\n        this.dom.$controls.removeClass('drawing-board-controls-hidden');\n    },\n\n\n    /**\n     * History methods: undo and redo drawed lines\n     */\n\n    initHistory: function () {\n        this.history = {\n            values: [],\n            position: 0\n        };\n    },\n\n    saveHistory: function () {\n        while (this.history.values.length > 30) {\n            this.history.values.shift();\n            this.history.position--;\n        }\n        if (this.history.position !== 0 && this.history.position < this.history.values.length) {\n            this.history.values = this.history.values.slice(0, this.history.position);\n            this.history.position++;\n        } else {\n            this.history.position = this.history.values.length + 1;\n        }\n        this.history.values.push(this.getImg());\n        this.ev.trigger('historyNavigation', this.history.position);\n    },\n\n    _goThroughHistory: function (goForth) {\n        if ((goForth && this.history.position == this.history.values.length) ||\n            (!goForth && this.history.position == 1))\n            return;\n        var pos = goForth ? this.history.position + 1 : this.history.position - 1;\n        if (this.history.values.length && this.history.values[pos - 1] !== undefined) {\n            this.history.position = pos;\n            this.setImg(this.history.values[pos - 1]);\n        }\n        this.ev.trigger('historyNavigation', pos);\n        this.saveWebStorage();\n    },\n\n    goBackInHistory: function () {\n        this._goThroughHistory(false);\n    },\n\n    goForthInHistory: function () {\n        this._goThroughHistory(true);\n    },\n\n\n    /**\n     * Image methods: you can directly put an image on the canvas, get it in base64 data url or start a download\n     */\n\n    setImg: function (src) {\n        var ctx = this.ctx;\n        var img = new Image();\n        var oldGCO = ctx.globalCompositeOperation;\n        img.onload = function () {\n            ctx.globalCompositeOperation = \"source-over\";\n            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.width);\n            ctx.drawImage(img, 0, 0);\n            ctx.globalCompositeOperation = oldGCO;\n        };\n        img.src = src;\n    },\n\n    getImg: function () {\n        return this.canvas.toDataURL(\"image/png\");\n    },\n\n    downloadImg: function () {\n        var img = this.getImg();\n        img = img.replace(\"image/png\", \"image/octet-stream\");\n        window.location.href = img;\n    },\n\n\n    /**\n     * WebStorage handling : save and restore to local or session storage\n     */\n\n    saveWebStorage: function () {\n        if (window[this.storage]) {\n            window[this.storage].setItem('drawing-board-' + this.id, this.getImg());\n            this.ev.trigger('board:save' + this.storage.charAt(0).toUpperCase() + this.storage.slice(1), this.getImg());\n        }\n    },\n\n    restoreWebStorage: function () {\n        if (window[this.storage] && window[this.storage].getItem('drawing-board-' + this.id) !== null) {\n            this.setImg(window[this.storage].getItem('drawing-board-' + this.id));\n            this.ev.trigger('board:restore' + this.storage.charAt(0).toUpperCase() + this.storage.slice(1), window[this.storage].getItem('drawing-board-' + this.id));\n        }\n    },\n\n    clearWebStorage: function () {\n        if (window[this.storage] && window[this.storage].getItem('drawing-board-' + this.id) !== null) {\n            window[this.storage].removeItem('drawing-board-' + this.id);\n            this.ev.trigger('board:clear' + this.storage.charAt(0).toUpperCase() + this.storage.slice(1));\n        }\n    },\n\n    _getStorage: function () {\n        if (!this.opts.webStorage || !(this.opts.webStorage === 'session' || this.opts.webStorage === 'local')) return false;\n        return this.opts.webStorage + 'Storage';\n    },\n\n\n    /**\n     * Drop an image on the canvas to draw on it\n     */\n\n    initDropEvents: function () {\n        if (!this.opts.droppable)\n            return false;\n\n        this.dom.$canvas.on('dragover dragenter drop', function (e) {\n            e.stopPropagation();\n            e.preventDefault();\n        });\n\n        this.dom.$canvas.on('drop', $.proxy(this._onCanvasDrop, this));\n    },\n\n    _onCanvasDrop: function (e) {\n        e = e.originalEvent ? e.originalEvent : e;\n        var files = e.dataTransfer.files;\n        if (!files || !files.length || files[0].type.indexOf('image') == -1 || !window.FileReader)\n            return false;\n        var fr = new FileReader();\n        fr.readAsDataURL(files[0]);\n        fr.onload = $.proxy(function (ev) {\n            this.setImg(ev.target.result);\n            this.ev.trigger('board:imageDropped', ev.target.result);\n            this.ev.trigger('board:userAction');\n            this.saveHistory();\n        }, this);\n    },\n\n\n    /**\n     * set and get current drawing mode\n     *\n     * possible modes are \"pencil\" (draw normally), \"eraser\" (draw transparent, like, erase, you know), \"filler\" (paint can)\n     */\n\n    setMode: function (newMode, silent) {\n        silent = silent || false;\n        newMode = newMode || 'pencil';\n\n        this.ev.unbind('board:startDrawing', $.proxy(this.fill, this));\n\n        if (this.opts.eraserColor === \"transparent\")\n            this.ctx.globalCompositeOperation = newMode === \"eraser\" ? \"destination-out\" : \"source-over\";\n        else {\n            if (newMode === \"eraser\") {\n                if (this.opts.eraserColor === \"background\" && DrawingBoard.Utils.isColor(this.opts.background))\n                    this.ctx.strokeStyle = this.opts.background;\n                else if (DrawingBoard.Utils.isColor(this.opts.eraserColor))\n                    this.ctx.strokeStyle = this.opts.eraserColor;\n            } else if (!this.mode || this.mode === \"eraser\") {\n                this.ctx.strokeStyle = this.color;\n            }\n\n            if (newMode === \"filler\")\n                this.ev.bind('board:startDrawing', $.proxy(this.fill, this));\n        }\n        this.mode = newMode;\n        if (!silent)\n            this.ev.trigger('board:mode', this.mode);\n    },\n\n    getMode: function () {\n        return this.mode || \"pencil\";\n    },\n\n    setColor: function (color) {\n        var that = this;\n        color = color || this.color;\n        if (!DrawingBoard.Utils.isColor(color))\n            return false;\n        this.color = color;\n        if (this.opts.eraserColor !== \"transparent\" && this.mode === \"eraser\") {\n            var setStrokeStyle = function (mode) {\n                if (mode !== \"eraser\")\n                    that.strokeStyle = that.color;\n                that.ev.unbind('board:mode', setStrokeStyle);\n            };\n            this.ev.bind('board:mode', setStrokeStyle);\n        } else\n            this.ctx.strokeStyle = this.color;\n    },\n\n    /**\n     * Fills an area with the current stroke color.\n     */\n    fill: function (e) {\n        if (this.getImg() === this.blankCanvas) {\n            this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.width);\n            this.ctx.fillStyle = this.color;\n            this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);\n            return;\n        }\n\n        var img = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);\n\n        // constants identifying pixels components\n        var INDEX = 0, X = 1, Y = 2, COLOR = 3;\n\n        // target color components\n        var stroke = this.ctx.strokeStyle;\n        var r = parseInt(stroke.substr(1, 2), 16);\n        var g = parseInt(stroke.substr(3, 2), 16);\n        var b = parseInt(stroke.substr(5, 2), 16);\n\n        // starting point\n        var start = DrawingBoard.Utils.pixelAt(img, parseInt(e.coords.x, 10), parseInt(e.coords.y, 10));\n\n        // no need to continue if starting and target colors are the same\n        if (start[COLOR] === DrawingBoard.Utils.RGBToInt(r, g, b))\n            return;\n\n        // pixels to evaluate\n        var queue = [start];\n\n        // loop vars\n        var pixel, x, y;\n        var maxX = img.width - 1;\n        var maxY = img.height - 1;\n\n        while ((pixel = queue.pop())) {\n            if (pixel[COLOR] === start[COLOR]) {\n                img.data[pixel[INDEX]] = r;\n                img.data[pixel[INDEX] + 1] = g;\n                img.data[pixel[INDEX] + 2] = b;\n                if (pixel[X] > 0) // west\n                    queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X] - 1, pixel[Y]));\n                if (pixel[X] < maxX) // east\n                    queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X] + 1, pixel[Y]));\n                if (pixel[Y] > 0) // north\n                    queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X], pixel[Y] - 1));\n                if (pixel[Y] < maxY) // south\n                    queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X], pixel[Y] + 1));\n            }\n        }\n\n        this.ctx.putImageData(img, 0, 0);\n    },\n\n\n    /**\n     * Drawing handling, with mouse or touch\n     */\n\n    initDrawEvents: function () {\n        this.isDrawing = false;\n        this.isMouseHovering = false;\n        this.coords = {};\n        this.coords.old = this.coords.current = this.coords.oldMid = {x: 0, y: 0};\n\n        this.dom.$canvas.on('mousedown touchstart', $.proxy(function (e) {\n            this._onInputStart(e, this._getInputCoords(e));\n        }, this));\n\n        this.dom.$canvas.on('mousemove touchmove', $.proxy(function (e) {\n            this._onInputMove(e, this._getInputCoords(e));\n        }, this));\n\n        this.dom.$canvas.on('mousemove', $.proxy(function (e) {\n\n        }, this));\n\n        this.dom.$canvas.on('mouseup touchend', $.proxy(function (e) {\n            this._onInputStop(e, this._getInputCoords(e));\n        }, this));\n\n        this.dom.$canvas.on('mouseover', $.proxy(function (e) {\n            this._onMouseOver(e, this._getInputCoords(e));\n        }, this));\n\n        this.dom.$canvas.on('mouseout', $.proxy(function (e) {\n            this._onMouseOut(e, this._getInputCoords(e));\n\n        }, this));\n\n        $('body').on('mouseup touchend', $.proxy(function (e) {\n            this.isDrawing = false;\n        }, this));\n\n        if (window.requestAnimationFrame) requestAnimationFrame($.proxy(this.draw, this));\n    },\n\n    draw: function () {\n        //if the pencil size is big (>10), the small crosshair makes a friend: a circle of the size of the pencil\n        //todo: have the circle works on every browser - it currently should be added only when CSS pointer-events are supported\n        //we assume that if requestAnimationFrame is supported, pointer-events is too, but this is terribad.\n        if (window.requestAnimationFrame && this.ctx.lineWidth > 10 && this.isMouseHovering) {\n            this.dom.$cursor.css({width: this.ctx.lineWidth + 'px', height: this.ctx.lineWidth + 'px'});\n            var transform = DrawingBoard.Utils.tpl(\"translateX({{x}}px) translateY({{y}}px)\", {\n                x: this.coords.current.x - (this.ctx.lineWidth / 2),\n                y: this.coords.current.y - (this.ctx.lineWidth / 2)\n            });\n            this.dom.$cursor.css({'transform': transform, '-webkit-transform': transform, '-ms-transform': transform});\n            this.dom.$cursor.removeClass('drawing-board-utils-hidden');\n        } else {\n            this.dom.$cursor.addClass('drawing-board-utils-hidden');\n        }\n\n        if (this.isDrawing) {\n            var currentMid = this._getMidInputCoords(this.coords.current);\n            this.ctx.beginPath();\n            this.ctx.moveTo(currentMid.x, currentMid.y);\n            this.ctx.quadraticCurveTo(this.coords.old.x, this.coords.old.y, this.coords.oldMid.x, this.coords.oldMid.y);\n            this.ctx.stroke();\n\n            this.coords.old = this.coords.current;\n            this.coords.oldMid = currentMid;\n        }\n\n        if (window.requestAnimationFrame) requestAnimationFrame($.proxy(function () {\n            this.draw();\n        }, this));\n    },\n\n    _onInputStart: function (e, coords) {\n        this.coords.current = this.coords.old = coords;\n        this.coords.oldMid = this._getMidInputCoords(coords);\n        this.isDrawing = true;\n\n        if (!window.requestAnimationFrame) this.draw();\n\n        this.ev.trigger('board:startDrawing', {e: e, coords: coords});\n        e.preventDefault();\n    },\n\n    _onInputMove: function (e, coords) {\n        this.coords.current = coords;\n        this.ev.trigger('board:drawing', {e: e, coords: coords});\n\n        if (!window.requestAnimationFrame) this.draw();\n\n        e.preventDefault();\n    },\n\n    _onInputStop: function (e, coords) {\n        if (this.isDrawing && (!e.touches || e.touches.length === 0)) {\n            this.isDrawing = false;\n\n            this.saveWebStorage();\n            this.saveHistory();\n\n            this.ev.trigger('board:stopDrawing', {e: e, coords: coords});\n            this.ev.trigger('board:userAction');\n            e.preventDefault();\n        }\n    },\n\n    _onMouseOver: function (e, coords) {\n        this.isMouseHovering = true;\n        this.coords.old = this._getInputCoords(e);\n        this.coords.oldMid = this._getMidInputCoords(this.coords.old);\n\n        this.ev.trigger('board:mouseOver', {e: e, coords: coords});\n    },\n\n    _onMouseOut: function (e, coords) {\n        this.isMouseHovering = false;\n\n        this.ev.trigger('board:mouseOut', {e: e, coords: coords});\n    },\n\n    _getInputCoords: function (e) {\n        e = e.originalEvent ? e.originalEvent : e;\n        var x, y;\n        if (e.touches && e.touches.length == 1) {\n            x = e.touches[0].pageX;\n            y = e.touches[0].pageY;\n        } else {\n            x = e.pageX;\n            y = e.pageY;\n        }\n        return {\n            x: x - this.dom.$canvas.offset().left,\n            y: y - this.dom.$canvas.offset().top\n        };\n    },\n\n    _getMidInputCoords: function (coords) {\n        return {\n            x: this.coords.old.x + coords.x >> 1,\n            y: this.coords.old.y + coords.y >> 1\n        };\n    }\n};\n\nDrawingBoard.Control = function (drawingBoard, opts) {\n    this.board = drawingBoard;\n    this.opts = $.extend({}, this.defaults, opts);\n\n    this.$el = $(document.createElement('div')).addClass('drawing-board-control');\n    if (this.name)\n        this.$el.addClass('drawing-board-control-' + this.name);\n\n    this.board.ev.bind('board:reset', $.proxy(this.onBoardReset, this));\n\n    this.initialize.apply(this, arguments);\n    return this;\n};\n\nDrawingBoard.Control.prototype = {\n\n    name: '',\n\n    defaults: {},\n\n    initialize: function () {\n\n    },\n\n    addToBoard: function () {\n        this.board.addControl(this);\n    },\n\n    onBoardReset: function (opts) {\n\n    }\n\n};\n\n//extend directly taken from backbone.js\nDrawingBoard.Control.extend = function (protoProps, staticProps) {\n    var parent = this;\n    var child;\n    if (protoProps && protoProps.hasOwnProperty('constructor')) {\n        child = protoProps.constructor;\n    } else {\n        child = function () {\n            return parent.apply(this, arguments);\n        };\n    }\n    $.extend(child, parent, staticProps);\n    var Surrogate = function () {\n        this.constructor = child;\n    };\n    Surrogate.prototype = parent.prototype;\n    child.prototype = new Surrogate();\n    if (protoProps) $.extend(child.prototype, protoProps);\n    child.__super__ = parent.prototype;\n    return child;\n};\nDrawingBoard.Control.Color = DrawingBoard.Control.extend({\n    name: 'colors',\n\n    initialize: function () {\n        this.initTemplate();\n\n        var that = this;\n        this.$el.on('click', '.drawing-board-control-colors-picker', function (e) {\n            var color = $(this).attr('data-color');\n            that.board.setColor(color);\n            that.$el.find('.drawing-board-control-colors-current')\n                .css('background-color', color)\n                .attr('data-color', color);\n\n            that.board.ev.trigger('color:changed', color);\n            that.$el.find('.drawing-board-control-colors-rainbows').addClass('drawing-board-utils-hidden');\n\n            e.preventDefault();\n        });\n\n        this.$el.on('click', '.drawing-board-control-colors-current', function (e) {\n            that.$el.find('.drawing-board-control-colors-rainbows').toggleClass('drawing-board-utils-hidden');\n            e.preventDefault();\n        });\n\n        $('body').on('click', function (e) {\n            var $target = $(e.target);\n            var $relatedButton = $target.hasClass('drawing-board-control-colors-current') ? $target : $target.closest('.drawing-board-control-colors-current');\n            var $myButton = that.$el.find('.drawing-board-control-colors-current');\n            var $popup = that.$el.find('.drawing-board-control-colors-rainbows');\n            if ((!$relatedButton.length || $relatedButton.get(0) !== $myButton.get(0)) && !$popup.hasClass('drawing-board-utils-hidden'))\n                $popup.addClass('drawing-board-utils-hidden');\n        });\n    },\n\n    initTemplate: function () {\n        var tpl = '<div class=\"drawing-board-control-inner\">' +\n            '<div class=\"drawing-board-control-colors-current\" style=\"background-color: {{color}}\" data-color=\"{{color}}\"></div>' +\n            '<div class=\"drawing-board-control-colors-rainbows\">{{rainbows}}</div>' +\n            '</div>';\n        var oneColorTpl = '<div class=\"drawing-board-control-colors-picker\" data-color=\"{{color}}\" style=\"background-color: {{color}}\"></div>';\n        var rainbows = '';\n        $.each([0.75, 0.5, 0.25], $.proxy(function (key, val) {\n            var i = 0;\n            var additionalColor = null;\n            rainbows += '<div class=\"drawing-board-control-colors-rainbow\">';\n            if (val == 0.25) additionalColor = this._rgba(0, 0, 0, 1);\n            if (val == 0.5) additionalColor = this._rgba(150, 150, 150, 1);\n            if (val == 0.75) additionalColor = this._rgba(255, 255, 255, 1);\n            rainbows += DrawingBoard.Utils.tpl(oneColorTpl, {color: additionalColor.toString()});\n            while (i <= 330) {\n                rainbows += DrawingBoard.Utils.tpl(oneColorTpl, {color: this._hsl2Rgba(this._hsl(i - 60, 1, val)).toString()});\n                i += 30;\n            }\n            rainbows += '</div>';\n        }, this));\n\n        this.$el.append($(DrawingBoard.Utils.tpl(tpl, {color: this.board.color, rainbows: rainbows})));\n        this.$el.find('.drawing-board-control-colors-rainbows').addClass('drawing-board-utils-hidden');\n    },\n\n    onBoardReset: function (opts) {\n        this.board.setColor(this.$el.find('.drawing-board-control-colors-current').attr('data-color'));\n    },\n\n    _rgba: function (r, g, b, a) {\n        return {\n            r: r, g: g, b: b, a: a, toString: function () {\n                return \"rgba(\" + r + \", \" + g + \", \" + b + \", \" + a + \")\";\n            }\n        };\n    },\n\n    _hsl: function (h, s, l) {\n        return {\n            h: h, s: s, l: l, toString: function () {\n                return \"hsl(\" + h + \", \" + s * 100 + \"%, \" + l * 100 + \"%)\";\n            }\n        };\n    },\n\n    _hex2Rgba: function (hex) {\n        var num = parseInt(hex.substring(1), 16);\n        return this._rgba(num >> 16, num >> 8 & 255, num & 255, 1);\n    },\n\n    //conversion function (modified a bit) taken from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript\n    _hsl2Rgba: function (hsl) {\n        var h = hsl.h / 360, s = hsl.s, l = hsl.l, r, g, b;\n\n        function hue2rgb(p, q, t) {\n            if (t < 0) t += 1;\n            if (t > 1) t -= 1;\n            if (t < 1 / 6) return p + (q - p) * 6 * t;\n            if (t < 1 / 2) return q;\n            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n            return p;\n        }\n\n        if (s === 0) {\n            r = g = b = l; // achromatic\n        } else {\n            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n            var p = 2 * l - q;\n            r = Math.floor((hue2rgb(p, q, h + 1 / 3)) * 255);\n            g = Math.floor((hue2rgb(p, q, h)) * 255);\n            b = Math.floor((hue2rgb(p, q, h - 1 / 3)) * 255);\n        }\n        return this._rgba(r, g, b, 1);\n    }\n});\nDrawingBoard.Control.DrawingMode = DrawingBoard.Control.extend({\n\n    name: 'drawingmode',\n\n    defaults: {\n        pencil: true,\n        eraser: true,\n        filler: true\n    },\n\n    initialize: function () {\n\n        this.prevMode = this.board.getMode();\n\n        $.each([\"pencil\", \"eraser\", \"filler\"], $.proxy(function (k, value) {\n            if (this.opts[value]) {\n                this.$el.append('<button class=\"drawing-board-control-drawingmode-' + value + '-button\" data-mode=\"' + value + '\"></button>');\n            }\n        }, this));\n\n        this.$el.on('click', 'button[data-mode]', $.proxy(function (e) {\n            var value = $(e.currentTarget).attr('data-mode');\n            var mode = this.board.getMode();\n            if (mode !== value) this.prevMode = mode;\n            var newMode = mode === value ? this.prevMode : value;\n            this.board.setMode(newMode);\n            e.preventDefault();\n        }, this));\n\n        this.board.ev.bind('board:mode', $.proxy(function (mode) {\n            this.toggleButtons(mode);\n        }, this));\n\n        this.toggleButtons(this.board.getMode());\n    },\n\n    toggleButtons: function (mode) {\n        this.$el.find('button[data-mode]').each(function (k, item) {\n            var $item = $(item);\n            $item.toggleClass('active', mode === $item.attr('data-mode'));\n        });\n    }\n\n});\n\nDrawingBoard.Control.Navigation = DrawingBoard.Control.extend({\n\n    name: 'navigation',\n\n    defaults: {\n        back: true,\n        forward: true,\n        reset: true\n    },\n\n    initialize: function () {\n        var el = '';\n        if (this.opts.back) el += '<button class=\"drawing-board-control-navigation-back\">&larr;</button>';\n        if (this.opts.forward) el += '<button class=\"drawing-board-control-navigation-forward\">&rarr;</button>';\n        if (this.opts.reset) el += '<button class=\"drawing-board-control-navigation-reset\">&times;</button>';\n        this.$el.append(el);\n\n        if (this.opts.back) {\n            var $back = this.$el.find('.drawing-board-control-navigation-back');\n            this.board.ev.bind('historyNavigation', $.proxy(function (pos) {\n                if (pos === 1)\n                    $back.attr('disabled', 'disabled');\n                else\n                    $back.removeAttr('disabled');\n            }, this));\n            this.$el.on('click', '.drawing-board-control-navigation-back', $.proxy(function (e) {\n                this.board.goBackInHistory();\n                e.preventDefault();\n            }, this));\n        }\n\n        if (this.opts.forward) {\n            var $forward = this.$el.find('.drawing-board-control-navigation-forward');\n            this.board.ev.bind('historyNavigation', $.proxy(function (pos) {\n                if (pos === this.board.history.values.length)\n                    $forward.attr('disabled', 'disabled');\n                else\n                    $forward.removeAttr('disabled');\n            }, this));\n            this.$el.on('click', '.drawing-board-control-navigation-forward', $.proxy(function (e) {\n                this.board.goForthInHistory();\n                e.preventDefault();\n            }, this));\n        }\n\n        if (this.opts.reset) {\n            this.$el.on('click', '.drawing-board-control-navigation-reset', $.proxy(function (e) {\n                this.board.reset({background: true});\n                e.preventDefault();\n            }, this));\n        }\n    }\n});\nDrawingBoard.Control.Size = DrawingBoard.Control.extend({\n\n    name: 'size',\n\n    defaults: {\n        type: \"auto\",\n        dropdownValues: [1, 3, 6, 10, 20, 30, 40, 50]\n    },\n\n    types: ['dropdown', 'range'],\n\n    initialize: function () {\n        if (this.opts.type == \"auto\")\n            this.opts.type = this._iHasRangeInput() ? 'range' : 'dropdown';\n        var tpl = $.inArray(this.opts.type, this.types) > -1 ? this['_' + this.opts.type + 'Template']() : false;\n        if (!tpl) return false;\n\n        this.val = this.board.opts.size;\n\n        this.$el.append($(tpl));\n        this.$el.attr('data-drawing-board-type', this.opts.type);\n        this.updateView();\n\n        var that = this;\n\n        if (this.opts.type == \"range\") {\n            this.$el.on('change', '.drawing-board-control-size-range-input', function (e) {\n                that.val = $(this).val();\n                that.updateView();\n\n                that.board.ev.trigger('size:changed', that.val);\n\n                e.preventDefault();\n            });\n        }\n\n        if (this.opts.type == \"dropdown\") {\n            this.$el.on('click', '.drawing-board-control-size-dropdown-current', $.proxy(function (e) {\n                this.$el.find('.drawing-board-control-size-dropdown').toggleClass('drawing-board-utils-hidden');\n            }, this));\n\n            this.$el.on('click', '[data-size]', function (e) {\n                that.val = parseInt($(this).attr('data-size'), 0);\n                that.updateView();\n\n                that.board.ev.trigger('size:changed', that.val);\n\n                e.preventDefault();\n            });\n        }\n    },\n\n    _rangeTemplate: function () {\n        var tpl = '<div class=\"drawing-board-control-inner\" title=\"{{size}}\">' +\n            '<input type=\"range\" min=\"1\" max=\"50\" value=\"{{size}}\" step=\"1\" class=\"drawing-board-control-size-range-input\">' +\n            '<span class=\"drawing-board-control-size-range-current\"></span>' +\n            '</div>';\n        return DrawingBoard.Utils.tpl(tpl, {size: this.board.opts.size});\n    },\n\n    _dropdownTemplate: function () {\n        var tpl = '<div class=\"drawing-board-control-inner\" title=\"{{size}}\">' +\n            '<div class=\"drawing-board-control-size-dropdown-current\"><span></span></div>' +\n            '<ul class=\"drawing-board-control-size-dropdown\">';\n        $.each(this.opts.dropdownValues, function (i, size) {\n            tpl += DrawingBoard.Utils.tpl(\n                '<li data-size=\"{{size}}\"><span style=\"width: {{size}}px; height: {{size}}px; border-radius: {{size}}px;\"></span></li>',\n                {size: size}\n            );\n        });\n        tpl += '</ul></div>';\n        return tpl;\n    },\n\n    onBoardReset: function (opts) {\n        this.updateView();\n    },\n\n    updateView: function () {\n        var val = this.val;\n        this.board.ctx.lineWidth = val;\n\n        this.$el.find('.drawing-board-control-size-range-current, .drawing-board-control-size-dropdown-current span').css({\n            width: val + 'px',\n            height: val + 'px',\n            borderRadius: val + 'px',\n            marginLeft: -1 * val / 2 + 'px',\n            marginTop: -1 * val / 2 + 'px'\n        });\n\n        this.$el.find('.drawing-board-control-inner').attr('title', val);\n\n        if (this.opts.type == 'dropdown') {\n            var closest = null;\n            $.each(this.opts.dropdownValues, function (i, size) {\n                if (closest === null || Math.abs(size - val) < Math.abs(closest - val))\n                    closest = size;\n            });\n            this.$el.find('.drawing-board-control-size-dropdown').addClass('drawing-board-utils-hidden');\n        }\n    },\n\n    _iHasRangeInput: function () {\n        var inputElem = document.createElement('input'),\n            smile = ':)',\n            docElement = document.documentElement,\n            inputElemType = 'range',\n            available;\n        inputElem.setAttribute('type', inputElemType);\n        available = inputElem.type !== 'text';\n        inputElem.value = smile;\n        inputElem.style.cssText = 'position:absolute;visibility:hidden;';\n        if (/^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined) {\n            docElement.appendChild(inputElem);\n            defaultView = document.defaultView;\n            available = defaultView.getComputedStyle &&\n                defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&\n                (inputElem.offsetHeight !== 0);\n            docElement.removeChild(inputElem);\n        }\n        return !!available;\n    }\n});\nDrawingBoard.Control.Download = DrawingBoard.Control.extend({\n\n    name: 'download',\n\n    initialize: function () {\n        this.$el.append('<button class=\"drawing-board-control-download-button\"></button>');\n        this.$el.on('click', '.drawing-board-control-download-button', $.proxy(function (e) {\n            this.board.downloadImg();\n            e.preventDefault();\n        }, this));\n    }\n\n});\nDrawingBoard.Utils = {};\n\n/*!\n* Tim (lite)\n*   github.com/premasagar/tim\n*/\n/*\n\tA tiny, secure JavaScript micro-templating script.\n*/\nDrawingBoard.Utils.tpl = (function () {\n    \"use strict\";\n\n    var start = \"{{\",\n        end = \"}}\",\n        path = \"[a-z0-9_][\\\\.a-z0-9_]*\", // e.g. config.person.name\n        pattern = new RegExp(start + \"\\\\s*(\" + path + \")\\\\s*\" + end, \"gi\"),\n        undef;\n\n    return function (template, data) {\n        // Merge data into the template string\n        return template.replace(pattern, function (tag, token) {\n            var path = token.split(\".\"),\n                len = path.length,\n                lookup = data,\n                i = 0;\n\n            for (; i < len; i++) {\n                lookup = lookup[path[i]];\n\n                // Property not found\n                if (lookup === undef) {\n                    throw \"tim: '\" + path[i] + \"' not found in \" + tag;\n                }\n\n                // Return the required value\n                if (i === len - 1) {\n                    return lookup;\n                }\n            }\n        });\n    };\n}());\n\n/**\n * https://github.com/jeromeetienne/microevent.js\n * MicroEvent - to make any js object an event emitter (server or browser)\n *\n * - pure javascript - server compatible, browser compatible\n * - dont rely on the browser doms\n * - super simple - you get it immediatly, no mistery, no magic involved\n *\n * - create a MicroEventDebug with goodies to debug\n *   - make it safer to use\n */\nDrawingBoard.Utils.MicroEvent = function () {\n};\n\nDrawingBoard.Utils.MicroEvent.prototype = {\n    bind: function (event, fct) {\n        this._events = this._events || {};\n        this._events[event] = this._events[event] || [];\n        this._events[event].push(fct);\n    },\n    unbind: function (event, fct) {\n        this._events = this._events || {};\n        if (event in this._events === false) return;\n        this._events[event].splice(this._events[event].indexOf(fct), 1);\n    },\n    trigger: function (event /* , args... */) {\n        this._events = this._events || {};\n        if (event in this._events === false) return;\n        for (var i = 0; i < this._events[event].length; i++) {\n            this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));\n        }\n    }\n};\n\n//I know.\nDrawingBoard.Utils._boxBorderSize = function ($el, withPadding, withMargin, direction) {\n    withPadding = !!withPadding || true;\n    withMargin = !!withMargin || false;\n    var width = 0,\n        props;\n    if (direction == \"width\") {\n        props = ['border-left-width', 'border-right-width'];\n        if (withPadding) props.push('padding-left', 'padding-right');\n        if (withMargin) props.push('margin-left', 'margin-right');\n    } else {\n        props = ['border-top-width', 'border-bottom-width'];\n        if (withPadding) props.push('padding-top', 'padding-bottom');\n        if (withMargin) props.push('margin-top', 'margin-bottom');\n    }\n    for (var i = props.length - 1; i >= 0; i--)\n        width += parseInt($el.css(props[i]).replace('px', ''), 10);\n    return width;\n};\n\nDrawingBoard.Utils.boxBorderWidth = function ($el, withPadding, withMargin) {\n    return DrawingBoard.Utils._boxBorderSize($el, withPadding, withMargin, 'width');\n};\n\nDrawingBoard.Utils.boxBorderHeight = function ($el, withPadding, withMargin) {\n    return DrawingBoard.Utils._boxBorderSize($el, withPadding, withMargin, 'height');\n};\n\nDrawingBoard.Utils.isColor = function (string) {\n    if (!string || !string.length) return false;\n    return (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i).test(string) || $.inArray(string.substring(0, 3), ['rgb', 'hsl']) !== -1;\n};\n\n/**\n * Packs an RGB color into a single integer.\n */\nDrawingBoard.Utils.RGBToInt = function (r, g, b) {\n    var c = 0;\n    c |= (r & 255) << 16;\n    c |= (g & 255) << 8;\n    c |= (b & 255);\n    return c;\n};\n\n/**\n * Returns informations on the pixel located at (x,y).\n */\nDrawingBoard.Utils.pixelAt = function (image, x, y) {\n    var i = (y * image.width + x) * 4;\n    var c = DrawingBoard.Utils.RGBToInt(\n        image.data[i],\n        image.data[i + 1],\n        image.data[i + 2]\n    );\n\n    return [\n        i, // INDEX\n        x, // X\n        y, // Y\n        c  // COLOR\n    ];\n};\n\n(function () {\n    var lastTime = 0;\n    var vendors = ['ms', 'moz', 'webkit', 'o'];\n    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {\n        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];\n        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];\n    }\n}());\n//original code stops here\n    var g;\n    if (typeof window !== \"undefined\") {\n        g = window\n    } else if (typeof global !== \"undefined\") {\n        g = global\n    } else if (typeof self !== \"undefined\") {\n        g = self\n    } else {\n        g = this\n    }\n    g.DrawingBoard = DrawingBoard;\n\n  // This is our factory method. Return our module object here...\n  return DrawingBoard;\n\n});\n"],"names":["define","$","pattern","DrawingBoard","Board","id","opts","extend","defaultOpts","ev","Utils","MicroEvent","$el","document","getElementById","this","length","tpl","controlsPosition","indexOf","addClass","append","dom","$canvasWrapper","find","$canvas","$cursor","$controls","each","proxy","n","val","attr","canvas","get","ctx","getContext","color","errorMessage","html","storage","_getStorage","initHistory","reset","webStorage","history","background","initControls","resize","restoreWebStorage","initDropEvents","initDrawEvents","controls","size","eraserColor","droppable","enlargeYourContainer","prototype","setMode","resetBackground","setColor","lineWidth","lineCap","lineJoin","saveWebStorage","saveHistory","blankCanvas","getImg","trigger","historize","bgIsColor","isColor","prevMode","getMode","clearRect","width","fillStyle","fillRect","height","setImg","canvasWidth","canvasHeight","toggleClass","widths","boxBorderWidth","heights","boxBorderHeight","sum","values","multiplier","res","i","sub","css","Control","c","window","controlName","addControl","control","optsOrPos","pos","children","eq","before","push","removeClass","position","shift","slice","_goThroughHistory","goForth","undefined","goBackInHistory","goForthInHistory","src","img","Image","oldGCO","globalCompositeOperation","onload","drawImage","toDataURL","downloadImg","replace","location","href","setItem","charAt","toUpperCase","getItem","clearWebStorage","removeItem","on","e","stopPropagation","preventDefault","_onCanvasDrop","files","originalEvent","dataTransfer","type","FileReader","fr","readAsDataURL","target","result","newMode","silent","unbind","fill","strokeStyle","mode","bind","that","setStrokeStyle","getImageData","stroke","r","parseInt","substr","g","b","start","pixelAt","coords","x","y","RGBToInt","pixel","queue","maxX","maxY","pop","data","putImageData","isDrawing","isMouseHovering","old","current","oldMid","_onInputStart","_getInputCoords","_onInputMove","_onInputStop","_onMouseOver","_onMouseOut","requestAnimationFrame","draw","transform","currentMid","_getMidInputCoords","beginPath","moveTo","quadraticCurveTo","touches","pageX","pageY","offset","left","top","drawingBoard","board","defaults","createElement","name","onBoardReset","initialize","apply","arguments","addToBoard","protoProps","staticProps","child","parent","hasOwnProperty","constructor","Surrogate","__super__","Color","initTemplate","$target","$relatedButton","hasClass","closest","$myButton","$popup","oneColorTpl","rainbows","key","additionalColor","_rgba","toString","_hsl2Rgba","_hsl","a","h","s","l","_hex2Rgba","hex","num","substring","hsl","hue2rgb","p","q","t","Math","floor","DrawingMode","pencil","eraser","filler","k","value","currentTarget","toggleButtons","item","$item","Navigation","back","forward","el","$back","removeAttr","$forward","Size","dropdownValues","types","_iHasRangeInput","inArray","updateView","_rangeTemplate","_dropdownTemplate","borderRadius","marginLeft","marginTop","abs","available","inputElem","docElement","documentElement","setAttribute","style","cssText","test","WebkitAppearance","appendChild","defaultView","getComputedStyle","offsetHeight","removeChild","Download","RegExp","template","tag","token","path","split","len","lookup","undef","event","fct","_events","splice","Array","call","_boxBorderSize","withPadding","withMargin","direction","props","string","image","vendors","cancelAnimationFrame","global","self"],"mappings":"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"}