diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..af81ebae --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,21 @@ +## Expected Behavior + + +## Actual Behavior + + +## Steps to Reproduce the Problem + + 1. + 1. + 1. + +## Example Link +Please recreate your issue using [JSbin](https://www.jsbin.com), [JSFiddle](https://jsfiddle.net), or [Codepen](https://codepen.io). +* Link: + + +## Specifications + + - Browser: + - Version: diff --git a/README.md b/README.md index 989dd36c..9de01f9a 100755 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Download: [croppie.js](croppie.js) & [croppie.css](croppie.css) ## Adding croppie to your site -``` +```html ``` @@ -27,19 +27,25 @@ https://cdnjs.cloudflare.com/ajax/libs/croppie/{version}/croppie.min.js [Documentation](http://foliotek.github.io/Croppie#documentation) ## Related Libraries -* https://github.com/wem/croppie-dart -* https://github.com/allenRoyston/ngCroppie -* https://github.com/lpsBetty/angular-croppie - +* [croppie-dart](https://gitlab.com/michel.werren/croppie-dart) +* [ngCroppie](https://github.com/allenRoyston/ngCroppie) +* [angular-croppie](https://github.com/lpsBetty/angular-croppie) +* [django-croppie](https://github.com/dima-kov/django-croppie) +* [vue-croppie](https://github.com/jofftiquez/vue-croppie) ## Contributing -#### Static Server -`live-server` +First, thanks for contributing. This project is difficult to maintain with one person. Here's a "checklist" of things to remember when contributing to croppie. +* Don't forget to update the documentation. +* If you're adding a new option/event/method, try adding to an example on the documentation. Or create a new example, if you feel the need. +* We don't have tests for Croppie :( (if you want to create tests I'd be forever grateful), so please try to test the functionality you're changing on the demo page. I've tried to add as many use-cases as I can think of on there. Compare the functionality in your branch to the one on the official page. If they all still work, then great! + +If you're looking for a simple server to load the demo page, I use https://github.com/tapio/live-server. #### Minifying `uglifyjs croppie.js -c -m -r '$,require,exports' -o croppie.min.js` #### Releasing a new version +For the most part, you shouldn't worry about these steps unless you're the one handling the release. Please don't bump the release and don't minify/uglify in a PR. That just creates merge conflicts when merging. Those steps will be performed when the release is created. 1. Bump version in croppie.js 2. Minify/Uglify 3. Commit diff --git a/croppie.js b/croppie.js index 989202d2..94842853 100755 --- a/croppie.js +++ b/croppie.js @@ -1,29 +1,29 @@ /************************* * Croppie - * Copyright 2017 + * Copyright 2019 * Foliotek - * Version: 2.5.0 + * Version: 2.6.5 *************************/ (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. - define(['exports'], factory); + define(factory); } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') { // CommonJS - factory(exports); + module.exports = factory(); } else { // Browser globals - factory((root.commonJsStrict = {})); + root.Croppie = factory(); } -}(this, function (exports) { +}(typeof self !== 'undefined' ? self : this, function () { /* Polyfills */ if (typeof Promise !== 'function') { /*! promise-polyfill 3.1.0 */ - !function(a){function b(a,b){return function(){a.apply(b,arguments)}}function c(a){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof a)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],i(a,b(e,this),b(f,this))}function d(a){var b=this;return null===this._state?void this._deferreds.push(a):void k(function(){var c=b._state?a.onFulfilled:a.onRejected;if(null===c)return void(b._state?a.resolve:a.reject)(b._value);var d;try{d=c(b._value)}catch(e){return void a.reject(e)}a.resolve(d)})}function e(a){try{if(a===this)throw new TypeError("A promise cannot be resolved with itself.");if(a&&("object"==typeof a||"function"==typeof a)){var c=a.then;if("function"==typeof c)return void i(b(c,a),b(e,this),b(f,this))}this._state=!0,this._value=a,g.call(this)}catch(d){f.call(this,d)}}function f(a){this._state=!1,this._value=a,g.call(this)}function g(){for(var a=0,b=this._deferreds.length;b>a;a++)d.call(this,this._deferreds[a]);this._deferreds=null}function h(a,b,c,d){this.onFulfilled="function"==typeof a?a:null,this.onRejected="function"==typeof b?b:null,this.resolve=c,this.reject=d}function i(a,b,c){var d=!1;try{a(function(a){d||(d=!0,b(a))},function(a){d||(d=!0,c(a))})}catch(e){if(d)return;d=!0,c(e)}}var j=setTimeout,k="function"==typeof setImmediate&&setImmediate||function(a){j(a,1)},l=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};c.prototype["catch"]=function(a){return this.then(null,a)},c.prototype.then=function(a,b){var e=this;return new c(function(c,f){d.call(e,new h(a,b,c,f))})},c.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&l(arguments[0])?arguments[0]:arguments);return new c(function(b,c){function d(f,g){try{if(g&&("object"==typeof g||"function"==typeof g)){var h=g.then;if("function"==typeof h)return void h.call(g,function(a){d(f,a)},c)}a[f]=g,0===--e&&b(a)}catch(i){c(i)}}if(0===a.length)return b([]);for(var e=a.length,f=0;fd;d++)a[d].then(b,c)})},c._setImmediateFn=function(a){k=a},"undefined"!=typeof module&&module.exports?module.exports=c:a.Promise||(a.Promise=c)}(this); + !function(a){function b(a,b){return function(){a.apply(b,arguments)}}function c(a){if("object"!==typeof this)throw new TypeError("Promises must be constructed via new");if("function"!==typeof a)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],i(a,b(e,this),b(f,this))}function d(a){var b=this;return null===this._state?void this._deferreds.push(a):void k(function(){var c=b._state?a.onFulfilled:a.onRejected;if(null===c)return void(b._state?a.resolve:a.reject)(b._value);var d;try{d=c(b._value)}catch(e){return void a.reject(e)}a.resolve(d)})}function e(a){try{if(a===this)throw new TypeError("A promise cannot be resolved with itself.");if(a&&("object"===typeof a||"function"===typeof a)){var c=a.then;if("function"===typeof c)return void i(b(c,a),b(e,this),b(f,this))}this._state=!0,this._value=a,g.call(this)}catch(d){f.call(this,d)}}function f(a){this._state=!1,this._value=a,g.call(this)}function g(){for(var a=0,b=this._deferreds.length;b>a;a++)d.call(this,this._deferreds[a]);this._deferreds=null}function h(a,b,c,d){this.onFulfilled="function"===typeof a?a:null,this.onRejected="function"===typeof b?b:null,this.resolve=c,this.reject=d}function i(a,b,c){var d=!1;try{a(function(a){d||(d=!0,b(a))},function(a){d||(d=!0,c(a))})}catch(e){if(d)return;d=!0,c(e)}}var j=setTimeout,k="function"===typeof setImmediate&&setImmediate||function(a){j(a,1)},l=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)};c.prototype["catch"]=function(a){return this.then(null,a)},c.prototype.then=function(a,b){var e=this;return new c(function(c,f){d.call(e,new h(a,b,c,f))})},c.all=function(){var a=Array.prototype.slice.call(1===arguments.length&&l(arguments[0])?arguments[0]:arguments);return new c(function(b,c){function d(f,g){try{if(g&&("object"===typeof g||"function"===typeof g)){var h=g.then;if("function"===typeof h)return void h.call(g,function(a){d(f,a)},c)}a[f]=g,0===--e&&b(a)}catch(i){c(i)}}if(0===a.length)return b([]);for(var e=a.length,f=0;fd;d++)a[d].then(b,c)})},c._setImmediateFn=function(a){k=a},"undefined"!==typeof module&&module.exports?module.exports=c:a.Promise||(a.Promise=c)}(this); } - if ( typeof window.CustomEvent !== "function" ) { + if (typeof window !== 'undefined' && typeof window.CustomEvent !== "function") { (function(){ function CustomEvent ( event, params ) { params = params || { bubbles: false, cancelable: false, detail: undefined }; @@ -36,7 +36,7 @@ }()); } - if (!HTMLCanvasElement.prototype.toBlob) { + if (typeof HTMLCanvasElement !== 'undefined' && !HTMLCanvasElement.prototype.toBlob) { Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', { value: function (callback, type, quality) { var binStr = atob( this.toDataURL(type, quality).split(',')[1] ), @@ -54,7 +54,9 @@ /* End Polyfills */ var cssPrefixes = ['Webkit', 'Moz', 'ms'], - emptyStyles = document.createElement('div').style, + emptyStyles = typeof document !== 'undefined' ? document.createElement('div').style : {}, + EXIF_NORM = [1,8,3,6], + EXIF_FLIP = [2,7,4,5], CSS_TRANS_ORG, CSS_TRANSFORM, CSS_USERSELECT; @@ -79,6 +81,14 @@ CSS_TRANS_ORG = vendorPrefix('transformOrigin'); CSS_USERSELECT = vendorPrefix('userSelect'); + function getExifOffset(ornt, rotate) { + var arr = EXIF_NORM.indexOf(ornt) > -1 ? EXIF_NORM : EXIF_FLIP, + index = arr.indexOf(ornt), + offset = (rotate / 90) % arr.length;// 180 = 2%4 = 2 shift exif by 2 indexes + + return arr[(arr.length + index + (offset % arr.length)) % arr.length]; + } + // Credits to : Andrew Dupont - http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/ function deepExtend(destination, source) { destination = destination || {}; @@ -93,6 +103,10 @@ return destination; } + function clone(object) { + return deepExtend({}, object); + } + function debounce(func, wait, immediate) { var timeout; return function () { @@ -150,50 +164,60 @@ } } + function setAttributes(el, attrs) { + for (var key in attrs) { + el.setAttribute(key, attrs[key]); + } + } + function num(v) { return parseInt(v, 10); } /* Utilities */ - function loadImage(src, imageEl, doExif) { - var img = imageEl || new Image(); - img.style.opacity = 0; + function loadImage(src, doExif) { + if (!src) { throw 'Source image missing'; } - return new Promise(function (resolve) { + var img = new Image(); + img.style.opacity = '0'; + return new Promise(function (resolve, reject) { function _resolve() { - setTimeout(function(){ + img.style.opacity = '1'; + setTimeout(function () { resolve(img); }, 1); } - if (img.src === src) {// If image source hasn't changed resolve immediately - _resolve(); - return; - } - - img.exifdata = null; img.removeAttribute('crossOrigin'); if (src.match(/^https?:\/\/|^\/\//)) { img.setAttribute('crossOrigin', 'anonymous'); } + img.onload = function () { if (doExif) { EXIF.getData(img, function () { _resolve(); - }); + }); } else { _resolve(); } }; + img.onerror = function (ev) { + img.style.opacity = 1; + setTimeout(function () { + reject(ev); + }, 1); + }; img.src = src; }); } - function naturalImageDimensions(img) { + function naturalImageDimensions(img, ornt) { var w = img.naturalWidth; var h = img.naturalHeight; - if (img.exifdata && img.exifdata.Orientation >= 5) { + var orient = ornt || getExifOrientation(img); + if (orient && orient >= 5) { var x= w; w = h; h = x; @@ -268,7 +292,7 @@ }; function getExifOrientation (img) { - return img.exifdata.Orientation; + return img.exifdata && img.exifdata.Orientation ? num(img.exifdata.Orientation) : 1; } function drawCanvas(canvas, img, orientation) { @@ -351,10 +375,11 @@ self.elements.preview = self.elements.canvas; } else { - self.elements.preview = self.elements.img; + self.elements.preview = img; } addClass(boundary, 'cr-boundary'); + boundary.setAttribute('aria-dropeffect', 'none'); bw = self.options.boundary.width; bh = self.options.boundary.height; css(boundary, { @@ -373,6 +398,7 @@ viewport.setAttribute('tabindex', 0); addClass(self.elements.preview, 'cr-image'); + setAttributes(self.elements.preview, { 'alt': 'preview', 'aria-grabbed': 'false' }); addClass(overlay, 'cr-overlay'); self.element.appendChild(boundary); @@ -540,7 +566,7 @@ self.options.viewport.width += deltaX; css(self.elements.viewport, { width: self.options.viewport.width + 'px' - }); + }); } _updateOverlay.call(self); @@ -562,21 +588,48 @@ if (vr) { vr.addEventListener('mousedown', mouseDown); + vr.addEventListener('touchstart', mouseDown); } if (hr) { hr.addEventListener('mousedown', mouseDown); + hr.addEventListener('touchstart', mouseDown); } this.elements.boundary.appendChild(wrap); } + function _applyEasingToZoomValue(zoomer) { + var val = parseFloat(zoomer.value), + min = parseFloat(zoomer.min), + max = parseFloat(zoomer.max); + return _calculateQuadraticEasingWithOffset(min, max, val); + } + + function _calculateQuadraticEasingWithOffset(min, max, val) { + var A = .1, + c = (val - min) / (max - min); + // quadratic IN easing with offset A + return min + (Math.pow((A + (1 - A) * c), 2) - Math.pow(A, 2)) * (max - min); + } + + function _invertQuadraticEasingWithOffset(min, max, val) { + var A = .1; + // inversion of quadratic IN easing with offset A + return min + (Math.sqrt(Math.pow(A, 2) + (val - min) / (max - min)) - A) * (max - min) / (1 - A); + } + function _setZoomerVal(v) { if (this.options.enableZoom) { var z = this.elements.zoomer, - val = fix(v, 4); + val = fix(v, 4), + min = parseFloat(z.min), + max = parseFloat(z.max); + + val = Math.max(min, Math.min(max, val)); - z.value = Math.max(z.min, Math.min(z.max, val)); + // Inverting easing function + z.value = _invertQuadraticEasingWithOffset(min, max, val); } } @@ -589,8 +642,9 @@ addClass(zoomer, 'cr-slider'); zoomer.type = 'range'; zoomer.step = '0.0001'; - zoomer.value = 1; + zoomer.value = '1'; zoomer.style.display = self.options.showZoomer ? '' : 'none'; + zoomer.setAttribute('aria-label', 'zoom'); self.element.appendChild(wrap); wrap.appendChild(zoomer); @@ -599,7 +653,7 @@ function change() { _onZoom.call(self, { - value: parseFloat(zoomer.value), + value: _applyEasingToZoomValue(zoomer), origin: new TransformOrigin(self.elements.preview), viewportRect: self.elements.viewport.getBoundingClientRect(), transform: Transform.parse(self.elements.preview) @@ -609,7 +663,9 @@ function scroll(ev) { var delta, targetZoom; - if (ev.wheelDelta) { + if(self.options.mouseWheelZoom === 'ctrl' && ev.ctrlKey !== true){ + return 0; + } else if (ev.wheelDelta) { delta = ev.wheelDelta / 1200; //wheelDelta min: -120 max: 120 // max x 10 x 2 } else if (ev.deltaY) { delta = ev.deltaY / 1060; //deltaY min: -53 max: 53 // max x 10 x 2 @@ -650,6 +706,7 @@ self._currentZoom = ui ? ui.value : self._currentZoom; transform.scale = self._currentZoom; + self.elements.zoomer.setAttribute('aria-valuenow', self._currentZoom); applyCss(); if (self.options.enforceBoundary) { @@ -723,7 +780,7 @@ }; } - function _updateCenterPoint() { + function _updateCenterPoint(rotate) { var self = this, scale = self._currentZoom, data = self.elements.preview.getBoundingClientRect(), @@ -735,14 +792,27 @@ center = {}, adj = {}; - center.y = top / scale; - center.x = left / scale; + if (rotate) { + var cx = pc.x; + var cy = pc.y; + var tx = transform.x; + var ty = transform.y; - adj.y = (center.y - pc.y) * (1 - scale); - adj.x = (center.x - pc.x) * (1 - scale); + center.y = cx; + center.x = cy; + transform.y = tx; + transform.x = ty; + } + else { + center.y = top / scale; + center.x = left / scale; - transform.x -= adj.x; - transform.y -= adj.y; + adj.y = (center.y - pc.y) * (1 - scale); + adj.x = (center.x - pc.x) * (1 - scale); + + transform.x -= adj.x; + transform.y -= adj.y; + } var newCss = {}; newCss[CSS_TRANS_ORG] = center.x + 'px ' + center.y + 'px'; @@ -779,19 +849,24 @@ } } + function toggleGrabState(isDragging) { + self.elements.preview.setAttribute('aria-grabbed', isDragging); + self.elements.boundary.setAttribute('aria-dropeffect', isDragging? 'move': 'none'); + } + function keyDown(ev) { var LEFT_ARROW = 37, UP_ARROW = 38, RIGHT_ARROW = 39, DOWN_ARROW = 40; - if (ev.shiftKey && (ev.keyCode == UP_ARROW || ev.keyCode == DOWN_ARROW)) { - var zoom = 0.0; - if (ev.keyCode == UP_ARROW) { - zoom = parseFloat(self.elements.zoomer.value, 10) + parseFloat(self.elements.zoomer.step, 10) + if (ev.shiftKey && (ev.keyCode === UP_ARROW || ev.keyCode === DOWN_ARROW)) { + var zoom; + if (ev.keyCode === UP_ARROW) { + zoom = parseFloat(self.elements.zoomer.value) + parseFloat(self.elements.zoomer.step) } else { - zoom = parseFloat(self.elements.zoomer.value, 10) - parseFloat(self.elements.zoomer.step, 10) + zoom = parseFloat(self.elements.zoomer.value) - parseFloat(self.elements.zoomer.step) } self.setZoom(zoom); } @@ -803,7 +878,7 @@ document.body.style[CSS_USERSELECT] = 'none'; vpRect = self.elements.viewport.getBoundingClientRect(); keyMove(movement); - }; + } function parseKeyDown(key) { switch (key) { @@ -815,8 +890,8 @@ return [-1, 0]; case DOWN_ARROW: return [0, -1]; - }; - }; + } + } } function keyMove(movement) { @@ -849,7 +924,7 @@ originalX = touches.pageX; originalY = touches.pageY; } - + toggleGrabState(isDragging); transform = Transform.parse(self.elements.preview); window.addEventListener('mousemove', mouseMove); window.addEventListener('touchmove', mouseMove); @@ -874,7 +949,7 @@ deltaY = pageY - originalY, newCss = {}; - if (ev.type == 'touchmove') { + if (ev.type === 'touchmove') { if (ev.touches.length > 1) { var touch1 = ev.touches[0]; var touch2 = ev.touches[1]; @@ -903,6 +978,7 @@ function mouseUp() { isDragging = false; + toggleGrabState(isDragging); window.removeEventListener('mousemove', mouseMove); window.removeEventListener('touchmove', mouseMove); window.removeEventListener('mouseup', mouseUp); @@ -919,6 +995,7 @@ } function _updateOverlay() { + if (!this.elements) return; // since this is debounced, it can be fired after destroy var self = this, boundRect = self.elements.boundary.getBoundingClientRect(), imgData = self.elements.preview.getBoundingClientRect(); @@ -934,16 +1011,15 @@ function _triggerUpdate() { var self = this, - data = self.get(), - ev; + data = self.get(); if (!_isVisible.call(self)) { return; } self.options.update.call(self, data); - if (self.$ && typeof Prototype == 'undefined') { - self.$(self.element).trigger('update', data); + if (self.$ && typeof Prototype === 'undefined') { + self.$(self.element).trigger('update.croppie', data); } else { var ev; @@ -967,13 +1043,12 @@ initialZoom = 1, cssReset = {}, img = self.elements.preview, - imgData = self.elements.preview.getBoundingClientRect(), + imgData, transformReset = new Transform(0, 0, initialZoom), originReset = new TransformOrigin(), isVisible = _isVisible.call(self); - if (!isVisible || self.data.bound) { - // if the croppie isn't visible or it doesn't need binding + if (!isVisible || self.data.bound) {// if the croppie isn't visible or it doesn't need binding return; } @@ -983,8 +1058,11 @@ cssReset['opacity'] = 1; css(img, cssReset); + imgData = self.elements.preview.getBoundingClientRect(); + self._originalImageWidth = imgData.width; self._originalImageHeight = imgData.height; + self.data.orientation = _hasExif.call(self) ? getExifOrientation(self.elements.img) : self.data.orientation; if (self.options.enableZoom) { _updateZoomLimits.call(self, true); @@ -1010,21 +1088,20 @@ function _updateZoomLimits (initial) { var self = this, - minZoom = 0, - maxZoom = 1.5, + minZoom = Math.max(self.options.minZoom, 0) || 0, + maxZoom = self.options.maxZoom || 1.5, initialZoom, defaultInitialZoom, zoomer = self.elements.zoomer, scale = parseFloat(zoomer.value), boundaryData = self.elements.boundary.getBoundingClientRect(), - imgData = self.elements.preview.getBoundingClientRect(), + imgData = naturalImageDimensions(self.elements.img, self.data.orientation), vpData = self.elements.viewport.getBoundingClientRect(), minW, minH; - if (self.options.enforceBoundary) { - minW = vpData.width / (initial ? imgData.width : imgData.width / scale); - minH = vpData.height / (initial ? imgData.height : imgData.height / scale); + minW = vpData.width / imgData.width; + minH = vpData.height / imgData.height; minZoom = Math.max(minW, minH); } @@ -1035,7 +1112,10 @@ zoomer.min = fix(minZoom, 4); zoomer.max = fix(maxZoom, 4); - if (initial) { + if (!initial && (scale < zoomer.min || scale > zoomer.max)) { + _setZoomerVal.call(self, scale < zoomer.min ? zoomer.min : zoomer.max); + } + else if (initial) { defaultInitialZoom = Math.max((boundaryData.width / imgData.width), (boundaryData.height / imgData.height)); initialZoom = self.data.boundZoom !== null ? self.data.boundZoom : defaultInitialZoom; _setZoomerVal.call(self, initialZoom); @@ -1045,7 +1125,7 @@ } function _bindPoints(points) { - if (points.length != 4) { + if (points.length !== 4) { throw "Croppie - Invalid number of points supplied: " + points; } var self = this, @@ -1090,21 +1170,14 @@ var self = this, canvas = self.elements.canvas, img = self.elements.img, - ctx = canvas.getContext('2d'), - exif = _hasExif.call(self), - customOrientation = self.options.enableOrientation && customOrientation; + ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); canvas.width = img.width; canvas.height = img.height; - if (exif && !customOrientation) { - var orientation = getExifOrientation(img); - drawCanvas(canvas, img, num(orientation || 0, 10)); - } - else if (customOrientation) { - drawCanvas(canvas, img, customOrientation); - } + var orientation = self.options.enableOrientation && customOrientation || getExifOrientation(img); + drawCanvas(canvas, img, orientation); } function _getCanvas(data) { @@ -1119,62 +1192,71 @@ circle = data.circle, canvas = document.createElement('canvas'), ctx = canvas.getContext('2d'), - outWidth = width, - outHeight = height, startX = 0, startY = 0, - canvasWidth = outWidth, - canvasHeight = outHeight, - customDimensions = (data.outputWidth && data.outputHeight), - outputRatio = 1; - - if (customDimensions) { - canvasWidth = data.outputWidth; - canvasHeight = data.outputHeight; - outputRatio = canvasWidth / outWidth; - } + canvasWidth = data.outputWidth || width, + canvasHeight = data.outputHeight || height; canvas.width = canvasWidth; canvas.height = canvasHeight; if (data.backgroundColor) { ctx.fillStyle = data.backgroundColor; - ctx.fillRect(0, 0, outWidth, outHeight); + ctx.fillRect(0, 0, canvasWidth, canvasHeight); } - // start fixing data to send to draw image for enforceBoundary: false - if (!self.options.enforceBoundary) { - if (left < 0) { - startX = Math.abs(left); - left = 0; - } - if (top < 0) { - startY = Math.abs(top); - top = 0; - } - if (right > self._originalImageWidth) { - width = self._originalImageWidth - left; - outWidth = width; - } - if (bottom > self._originalImageHeight) { - height = self._originalImageHeight - top; - outHeight = height; - } + // By default assume we're going to draw the entire + // source image onto the destination canvas. + var sx = left, + sy = top, + sWidth = width, + sHeight = height, + dx = 0, + dy = 0, + dWidth = canvasWidth, + dHeight = canvasHeight; + + // + // Do not go outside of the original image's bounds along the x-axis. + // Handle translations when projecting onto the destination canvas. + // + + // The smallest possible source x-position is 0. + if (left < 0) { + sx = 0; + dx = (Math.abs(left) / width) * canvasWidth; + } + + // The largest possible source width is the original image's width. + if (sWidth + sx > self._originalImageWidth) { + sWidth = self._originalImageWidth - sx; + dWidth = (sWidth / width) * canvasWidth; } - if (outputRatio !== 1) { - startX *= outputRatio; - startY *= outputRatio; - outWidth *= outputRatio; - outHeight *= outputRatio; + // + // Do not go outside of the original image's bounds along the y-axis. + // + + // The smallest possible source y-position is 0. + if (top < 0) { + sy = 0; + dy = (Math.abs(top) / height) * canvasHeight; } - ctx.drawImage(this.elements.preview, left, top, Math.min(width, self._originalImageWidth), Math.min(height, self._originalImageHeight), startX, startY, outWidth, outHeight); + // The largest possible source height is the original image's height. + if (sHeight + sy > self._originalImageHeight) { + sHeight = self._originalImageHeight - sy; + dHeight = (sHeight / height) * canvasHeight; + } + + // console.table({ left, right, top, bottom, canvasWidth, canvasHeight, width, height, startX, startY, circle, sx, sy, dx, dy, sWidth, sHeight, dWidth, dHeight }); + + ctx.drawImage(this.elements.preview, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); if (circle) { ctx.fillStyle = '#fff'; ctx.globalCompositeOperation = 'destination-in'; ctx.beginPath(); - ctx.arc(outWidth / 2, outHeight / 2, outWidth / 2, 0, Math.PI * 2, true); + ctx.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); } @@ -1209,19 +1291,28 @@ function _getBlobResult(data) { var self = this; - return new Promise(function (resolve, reject) { + return new Promise(function (resolve) { _getCanvas.call(self, data).toBlob(function (blob) { resolve(blob); }, data.format, data.quality); }); } + function _replaceImage(img) { + if (this.elements.img.parentNode) { + Array.prototype.forEach.call(this.elements.img.classList, function(c) { img.classList.add(c); }); + this.elements.img.parentNode.replaceChild(img, this.elements.img); + this.elements.preview = img; // if the img is attached to the DOM, they're not using the canvas + } + this.elements.img = img; + } + function _bind(options, cb) { var self = this, url, points = [], zoom = null, - hasExif = _hasExif.call(self);; + hasExif = _hasExif.call(self); if (typeof (options) === 'string') { url = options; @@ -1230,7 +1321,7 @@ else if (Array.isArray(options)) { points = options.slice(); } - else if (typeof (options) == 'undefined' && self.data.url) { //refreshing + else if (typeof (options) === 'undefined' && self.data.url) { //refreshing _updatePropertiesFromImage.call(self); _triggerUpdate.call(self); return null; @@ -1245,7 +1336,8 @@ self.data.url = url || self.data.url; self.data.boundZoom = zoom; - return loadImage(url, self.elements.img, hasExif).then(function (img) { + return loadImage(url, hasExif).then(function (img) { + _replaceImage.call(self, img); if (!points.length) { var natDim = naturalImageDimensions(img); var rect = self.elements.viewport.getBoundingClientRect(); @@ -1259,16 +1351,15 @@ } else { width = natDim.width; - height = width / aspectRatio; + height = natDim.height / aspectRatio; } var x0 = (natDim.width - width) / 2; var y0 = (natDim.height - height) / 2; var x1 = x0 + width; var y1 = y0 + height; - self.data.points = [x0, y0, x1, y1]; - } + } else if (self.options.relative) { points = [ points[0] * img.naturalWidth / 100, @@ -1278,11 +1369,12 @@ ]; } + self.data.orientation = options.orientation || 1; self.data.points = points.map(function (p) { return parseFloat(p); }); if (self.options.useCanvas) { - _transferImageToCanvas.call(self, options.orientation || 1); + _transferImageToCanvas.call(self, self.data.orientation); } _updatePropertiesFromImage.call(self); _triggerUpdate.call(self); @@ -1318,7 +1410,8 @@ return { points: [fix(x1), fix(y1), fix(x2), fix(y2)], - zoom: scale + zoom: scale, + orientation: self.data.orientation }; } @@ -1332,7 +1425,7 @@ function _result(options) { var self = this, data = _get.call(self), - opts = deepExtend(RESULT_DEFAULTS, deepExtend({}, options)), + opts = deepExtend(clone(RESULT_DEFAULTS), clone(options)), resultType = (typeof (options) === 'string' ? options : (opts.type || 'base64')), size = opts.size || 'viewport', format = opts.format, @@ -1368,7 +1461,7 @@ data.url = self.data.url; data.backgroundColor = backgroundColor; - prom = new Promise(function (resolve, reject) { + prom = new Promise(function (resolve) { switch(resultType.toLowerCase()) { case 'rawcanvas': @@ -1394,27 +1487,25 @@ } function _rotate(deg) { - if (!this.options.useCanvas) { - throw 'Croppie: Cannot rotate without enableOrientation'; + if (!this.options.useCanvas || !this.options.enableOrientation) { + throw 'Croppie: Cannot rotate without enableOrientation && EXIF.js included'; } var self = this, - canvas = self.elements.canvas, - copy = document.createElement('canvas'), - ornt = 1; + canvas = self.elements.canvas; - copy.width = canvas.width; - copy.height = canvas.height; - var ctx = copy.getContext('2d'); - ctx.drawImage(canvas, 0, 0); + self.data.orientation = getExifOffset(self.data.orientation, deg); + drawCanvas(canvas, self.elements.img, self.data.orientation); + _updateCenterPoint.call(self, true); + _updateZoomLimits.call(self); - if (deg === 90 || deg === -270) ornt = 6; - if (deg === -90 || deg === 270) ornt = 8; - if (deg === 180 || deg === -180) ornt = 3; - - drawCanvas(canvas, copy, ornt); - _onZoom.call(self); - copy = null; + // Reverses image dimensions if the degrees of rotation is not divisible by 180. + if ((Math.abs(deg) / 90) % 2 === 1) { + var oldHeight = self._originalImageHeight; + var oldWidth = self._originalImageWidth; + self._originalImageWidth = oldHeight; + self._originalImageHeight = oldWidth; + } } function _destroy() { @@ -1427,7 +1518,7 @@ delete self.elements; } - if (window.jQuery) { + if (typeof window !== 'undefined' && window.jQuery) { var $ = window.jQuery; $.fn.croppie = function (opts) { var ot = typeof opts; @@ -1473,12 +1564,16 @@ } function Croppie(element, opts) { + if (element.className.indexOf('croppie-container') > -1) { + throw new Error("Croppie: Can't initialize croppie more than once"); + } this.element = element; - this.options = deepExtend(deepExtend({}, Croppie.defaults), opts); + this.options = deepExtend(clone(Croppie.defaults), opts); if (this.element.tagName.toLowerCase() === 'img') { var origImage = this.element; addClass(origImage, 'cr-original-image'); + setAttributes(origImage, {'aria-hidden' : 'true', 'alt' : '' }); var replacementDiv = document.createElement('div'); this.element.parentNode.appendChild(replacementDiv); replacementDiv.appendChild(origImage); @@ -1562,10 +1657,5 @@ return _destroy.call(this); } }); - - exports.Croppie = window.Croppie = Croppie; - - if (typeof module === 'object' && !!module.exports) { - module.exports = Croppie; - } + return Croppie; })); diff --git a/croppie.min.js b/croppie.min.js index 3b2092c8..6afcb01a 100644 --- a/croppie.min.js +++ b/croppie.min.js @@ -1 +1 @@ -!function(e,t){"function"==typeof define&&define.amd?define(["exports"],t):t("object"==typeof exports&&"string"!=typeof exports.nodeName?exports:e.commonJsStrict={})}(this,function(e){function t(e){if(e in q)return e;for(var t=e[0].toUpperCase()+e.slice(1),n=T.length;n--;)if(e=T[n]+t,e in q)return e}function n(e,t){e=e||{};for(var i in t)t[i]&&t[i].constructor&&t[i].constructor===Object?(e[i]=e[i]||{},n(e[i],t[i])):e[i]=t[i];return e}function i(e,t,n){var i;return function(){var o=this,r=arguments,a=function(){i=null,n||e.apply(o,r)},s=n&&!i;clearTimeout(i),i=setTimeout(a,t),s&&e.apply(o,r)}}function o(e){if("createEvent"in document){var t=document.createEvent("HTMLEvents");t.initEvent("change",!1,!0),e.dispatchEvent(t)}else e.fireEvent("onchange")}function r(e,t,n){if("string"==typeof t){var i=t;t={},t[i]=n}for(var o in t)e.style[o]=t[o]}function a(e,t){e.classList?e.classList.add(t):e.className+=" "+t}function s(e,t){e.classList?e.classList.remove(t):e.className=e.className.replace(t,"")}function l(e){return parseInt(e,10)}function u(e,t,n){var i=t||new Image;return i.style.opacity=0,new Promise(function(t){function o(){setTimeout(function(){t(i)},1)}return i.src===e?void o():(i.exifdata=null,i.removeAttribute("crossOrigin"),e.match(/^https?:\/\/|^\/\//)&&i.setAttribute("crossOrigin","anonymous"),i.onload=function(){n?EXIF.getData(i,function(){o()}):o()},void(i.src=e))})}function c(e){var t=e.naturalWidth,n=e.naturalHeight;if(e.exifdata&&e.exifdata.Orientation>=5){var i=t;t=n,n=i}return{width:t,height:n}}function h(e){return e.exifdata.Orientation}function p(e,t,n){var i=t.width,o=t.height,r=e.getContext("2d");switch(e.width=t.width,e.height=t.height,r.save(),n){case 2:r.translate(i,0),r.scale(-1,1);break;case 3:r.translate(i,o),r.rotate(180*Math.PI/180);break;case 4:r.translate(0,o),r.scale(1,-1);break;case 5:e.width=o,e.height=i,r.rotate(90*Math.PI/180),r.scale(1,-1);break;case 6:e.width=o,e.height=i,r.rotate(90*Math.PI/180),r.translate(0,-o);break;case 7:e.width=o,e.height=i,r.rotate(-90*Math.PI/180),r.translate(-i,o),r.scale(1,-1);break;case 8:e.width=o,e.height=i,r.translate(0,i),r.rotate(-90*Math.PI/180)}r.drawImage(t,0,0,i,o),r.restore()}function d(){var e,t,n,i,o,s,l=this,u="croppie-container",c=l.options.viewport.type?"cr-vp-"+l.options.viewport.type:null;l.options.useCanvas=l.options.enableOrientation||m.call(l),l.data={},l.elements={},e=l.elements.boundary=document.createElement("div"),n=l.elements.viewport=document.createElement("div"),t=l.elements.img=document.createElement("img"),i=l.elements.overlay=document.createElement("div"),l.options.useCanvas?(l.elements.canvas=document.createElement("canvas"),l.elements.preview=l.elements.canvas):l.elements.preview=l.elements.img,a(e,"cr-boundary"),o=l.options.boundary.width,s=l.options.boundary.height,r(e,{width:o+(isNaN(o)?"":"px"),height:s+(isNaN(s)?"":"px")}),a(n,"cr-viewport"),c&&a(n,c),r(n,{width:l.options.viewport.width+"px",height:l.options.viewport.height+"px"}),n.setAttribute("tabindex",0),a(l.elements.preview,"cr-image"),a(i,"cr-overlay"),l.element.appendChild(e),e.appendChild(l.elements.preview),e.appendChild(n),e.appendChild(i),a(l.element,u),l.options.customClass&&a(l.element,l.options.customClass),x.call(this),l.options.enableZoom&&g.call(l),l.options.enableResize&&f.call(l)}function m(){return this.options.enableExif&&window.EXIF}function f(){function e(e){if((void 0===e.button||0===e.button)&&(e.preventDefault(),!m)){var r=p.elements.overlay.getBoundingClientRect();if(m=!0,o=e.pageX,s=e.pageY,i=-1!==e.currentTarget.className.indexOf("vertical")?"v":"h",l=r.width,u=r.height,e.touches){var a=e.touches[0];o=a.pageX,s=a.pageY}window.addEventListener("mousemove",t),window.addEventListener("touchmove",t),window.addEventListener("mouseup",n),window.addEventListener("touchend",n),document.body.style[D]="none"}}function t(e){var t=e.pageX,n=e.pageY;if(e.preventDefault(),e.touches){var a=e.touches[0];t=a.pageX,n=a.pageY}var c=t-o,h=n-s,m=p.options.viewport.height+h,v=p.options.viewport.width+c;"v"===i&&m>=f&&u>=m?(r(d,{height:m+"px"}),p.options.boundary.height+=h,r(p.elements.boundary,{height:p.options.boundary.height+"px"}),p.options.viewport.height+=h,r(p.elements.viewport,{height:p.options.viewport.height+"px"})):"h"===i&&v>=f&&l>=v&&(r(d,{width:v+"px"}),p.options.boundary.width+=c,r(p.elements.boundary,{width:p.options.boundary.width+"px"}),p.options.viewport.width+=c,r(p.elements.viewport,{width:p.options.viewport.width+"px"})),C.call(p),B.call(p),b.call(p),E.call(p),s=n,o=t}function n(){m=!1,window.removeEventListener("mousemove",t),window.removeEventListener("touchmove",t),window.removeEventListener("mouseup",n),window.removeEventListener("touchend",n),document.body.style[D]=""}var i,o,s,l,u,c,h,p=this,d=document.createElement("div"),m=!1,f=50;a(d,"cr-resizer"),r(d,{width:this.options.viewport.width+"px",height:this.options.viewport.height+"px"}),this.options.resizeControls.height&&(c=document.createElement("div"),a(c,"cr-resizer-vertical"),d.appendChild(c)),this.options.resizeControls.width&&(h=document.createElement("div"),a(h,"cr-resizer-horisontal"),d.appendChild(h)),c&&c.addEventListener("mousedown",e),h&&h.addEventListener("mousedown",e),this.elements.boundary.appendChild(d)}function v(e){if(this.options.enableZoom){var t=this.elements.zoomer,n=F(e,4);t.value=Math.max(t.min,Math.min(t.max,n))}}function g(){function e(){w.call(n,{value:parseFloat(o.value),origin:new $(n.elements.preview),viewportRect:n.elements.viewport.getBoundingClientRect(),transform:K.parse(n.elements.preview)})}function t(t){var i,o;i=t.wheelDelta?t.wheelDelta/1200:t.deltaY?t.deltaY/1060:t.detail?t.detail/-60:0,o=n._currentZoom+i*n._currentZoom,t.preventDefault(),v.call(n,o),e.call(n)}var n=this,i=n.elements.zoomerWrap=document.createElement("div"),o=n.elements.zoomer=document.createElement("input");a(i,"cr-slider-wrap"),a(o,"cr-slider"),o.type="range",o.step="0.0001",o.value=1,o.style.display=n.options.showZoomer?"":"none",n.element.appendChild(i),i.appendChild(o),n._currentZoom=1,n.elements.zoomer.addEventListener("input",e),n.elements.zoomer.addEventListener("change",e),n.options.mouseWheelZoom&&(n.elements.boundary.addEventListener("mousewheel",t),n.elements.boundary.addEventListener("DOMMouseScroll",t))}function w(e){function t(){var e={};e[A]=i.toString(),e[P]=a.toString(),r(n.elements.preview,e)}var n=this,i=e?e.transform:K.parse(n.elements.preview),o=e?e.viewportRect:n.elements.viewport.getBoundingClientRect(),a=e?e.origin:new $(n.elements.preview);if(n._currentZoom=e?e.value:n._currentZoom,i.scale=n._currentZoom,t(),n.options.enforceBoundary){var s=y.call(n,o),l=s.translate,u=s.origin;i.x>=l.maxX&&(a.x=u.minX,i.x=l.maxX),i.x<=l.minX&&(a.x=u.maxX,i.x=l.minX),i.y>=l.maxY&&(a.y=u.minY,i.y=l.maxY),i.y<=l.minY&&(a.y=u.maxY,i.y=l.minY)}t(),Q.call(n),E.call(n)}function y(e){var t=this,n=t._currentZoom,i=e.width,o=e.height,r=t.elements.boundary.clientWidth/2,a=t.elements.boundary.clientHeight/2,s=t.elements.preview.getBoundingClientRect(),l=s.width,u=s.height,c=i/2,h=o/2,p=-1*(c/n-r),d=p-(l*(1/n)-i*(1/n)),m=-1*(h/n-a),f=m-(u*(1/n)-o*(1/n)),v=1/n*c,g=l*(1/n)-v,w=1/n*h,y=u*(1/n)-w;return{translate:{maxX:p,minX:d,maxY:m,minY:f},origin:{maxX:g,minX:v,maxY:y,minY:w}}}function b(){var e=this,t=e._currentZoom,n=e.elements.preview.getBoundingClientRect(),i=e.elements.viewport.getBoundingClientRect(),o=K.parse(e.elements.preview.style[A]),a=new $(e.elements.preview),s=i.top-n.top+i.height/2,l=i.left-n.left+i.width/2,u={},c={};u.y=s/t,u.x=l/t,c.y=(u.y-a.y)*(1-t),c.x=(u.x-a.x)*(1-t),o.x-=c.x,o.y-=c.y;var h={};h[P]=u.x+"px "+u.y+"px",h[A]=o.toString(),r(e.elements.preview,h)}function x(){function e(e,t){var n=d.elements.preview.getBoundingClientRect(),i=p.y+t,o=p.x+e;d.options.enforceBoundary?(h.top>n.top+t&&h.bottomn.left+e&&h.right=37&&e.keyCode<=40){e.preventDefault();var s=t(e.keyCode);p=K.parse(d.elements.preview),document.body.style[D]="none",h=d.elements.viewport.getBoundingClientRect(),n(s)}}else{var l=0;l=e.keyCode==o?parseFloat(d.elements.zoomer.value,10)+parseFloat(d.elements.zoomer.step,10):parseFloat(d.elements.zoomer.value,10)-parseFloat(d.elements.zoomer.step,10),d.setZoom(l)}}function n(t){var n=t[0],i=t[1],o={};e(n,i),o[A]=p.toString(),r(d.elements.preview,o),C.call(d),document.body.style[D]="",b.call(d),E.call(d),c=0}function i(e){if((void 0===e.button||0===e.button)&&(e.preventDefault(),!m)){if(m=!0,l=e.pageX,u=e.pageY,e.touches){var t=e.touches[0];l=t.pageX,u=t.pageY}p=K.parse(d.elements.preview),window.addEventListener("mousemove",a),window.addEventListener("touchmove",a),window.addEventListener("mouseup",s),window.addEventListener("touchend",s),document.body.style[D]="none",h=d.elements.viewport.getBoundingClientRect()}}function a(t){t.preventDefault();var n=t.pageX,i=t.pageY;if(t.touches){var a=t.touches[0];n=a.pageX,i=a.pageY}var s=n-l,h=i-u,m={};if("touchmove"==t.type&&t.touches.length>1){var f=t.touches[0],g=t.touches[1],w=Math.sqrt((f.pageX-g.pageX)*(f.pageX-g.pageX)+(f.pageY-g.pageY)*(f.pageY-g.pageY));c||(c=w/d._currentZoom);var y=w/c;return v.call(d,y),void o(d.elements.zoomer)}e(s,h),m[A]=p.toString(),r(d.elements.preview,m),C.call(d),u=i,l=n}function s(){m=!1,window.removeEventListener("mousemove",a),window.removeEventListener("touchmove",a),window.removeEventListener("mouseup",s),window.removeEventListener("touchend",s),document.body.style[D]="",b.call(d),E.call(d),c=0}var l,u,c,h,p,d=this,m=!1;d.elements.overlay.addEventListener("mousedown",i),d.elements.viewport.addEventListener("keydown",t),d.elements.overlay.addEventListener("touchstart",i)}function C(){var e=this,t=e.elements.boundary.getBoundingClientRect(),n=e.elements.preview.getBoundingClientRect();r(e.elements.overlay,{width:n.width+"px",height:n.height+"px",top:n.top-t.top+"px",left:n.left-t.left+"px"})}function E(){var e,t=this,n=t.get();if(_.call(t))if(t.options.update.call(t,n),t.$&&"undefined"==typeof Prototype)t.$(t.element).trigger("update",n);else{var e;window.CustomEvent?e=new CustomEvent("update",{detail:n}):(e=document.createEvent("CustomEvent"),e.initCustomEvent("update",!0,!0,n)),t.element.dispatchEvent(e)}}function _(){return this.elements.preview.offsetHeight>0&&this.elements.preview.offsetWidth>0}function L(){var e=this,t=1,n={},i=e.elements.preview,o=e.elements.preview.getBoundingClientRect(),a=new K(0,0,t),s=new $,l=_.call(e);l&&!e.data.bound&&(e.data.bound=!0,n[A]=a.toString(),n[P]=s.toString(),n.opacity=1,r(i,n),e._originalImageWidth=o.width,e._originalImageHeight=o.height,e.options.enableZoom?B.call(e,!0):e._currentZoom=t,a.scale=e._currentZoom,n[A]=a.toString(),r(i,n),e.data.points.length?R.call(e,e.data.points):I.call(e),b.call(e),C.call(e))}function B(e){var t,n,i,r,a=this,s=0,l=1.5,u=a.elements.zoomer,c=parseFloat(u.value),h=a.elements.boundary.getBoundingClientRect(),p=a.elements.preview.getBoundingClientRect(),d=a.elements.viewport.getBoundingClientRect();a.options.enforceBoundary&&(i=d.width/(e?p.width:p.width/c),r=d.height/(e?p.height:p.height/c),s=Math.max(i,r)),s>=l&&(l=s+1),u.min=F(s,4),u.max=F(l,4),e&&(n=Math.max(h.width/p.width,h.height/p.height),t=null!==a.data.boundZoom?a.data.boundZoom:n,v.call(a,t)),o(u)}function R(e){if(4!=e.length)throw"Croppie - Invalid number of points supplied: "+e;var t=this,n=e[2]-e[0],i=t.elements.viewport.getBoundingClientRect(),o=t.elements.boundary.getBoundingClientRect(),a={left:i.left-o.left,top:i.top-o.top},s=i.width/n,l=e[1],u=e[0],c=-1*e[1]+a.top,h=-1*e[0]+a.left,p={};p[P]=u+"px "+l+"px",p[A]=new K(h,c,s).toString(),r(t.elements.preview,p),v.call(t,s),t._currentZoom=s}function I(){var e=this,t=e.elements.preview.getBoundingClientRect(),n=e.elements.viewport.getBoundingClientRect(),i=e.elements.boundary.getBoundingClientRect(),o=n.left-i.left,a=n.top-i.top,s=o-(t.width-n.width)/2,l=a-(t.height-n.height)/2,u=new K(s,l,e._currentZoom);r(e.elements.preview,A,u.toString())}function M(e){var t=this,n=t.elements.canvas,i=t.elements.img,o=n.getContext("2d"),r=m.call(t),e=t.options.enableOrientation&&e;if(o.clearRect(0,0,n.width,n.height),n.width=i.width,n.height=i.height,r&&!e){var a=h(i);p(n,i,l(a||0,10))}else e&&p(n,i,e)}function Z(e){var t=this,n=e.points,i=l(n[0]),o=l(n[1]),r=l(n[2]),a=l(n[3]),s=r-i,u=a-o,c=e.circle,h=document.createElement("canvas"),p=h.getContext("2d"),d=s,m=u,f=0,v=0,g=d,w=m,y=e.outputWidth&&e.outputHeight,b=1;return y&&(g=e.outputWidth,w=e.outputHeight,b=g/d),h.width=g,h.height=w,e.backgroundColor&&(p.fillStyle=e.backgroundColor,p.fillRect(0,0,d,m)),t.options.enforceBoundary||(0>i&&(f=Math.abs(i),i=0),0>o&&(v=Math.abs(o),o=0),r>t._originalImageWidth&&(s=t._originalImageWidth-i,d=s),a>t._originalImageHeight&&(u=t._originalImageHeight-o,m=u)),1!==b&&(f*=b,v*=b,d*=b,m*=b),p.drawImage(this.elements.preview,i,o,Math.min(s,t._originalImageWidth),Math.min(u,t._originalImageHeight),f,v,d,m),c&&(p.fillStyle="#fff",p.globalCompositeOperation="destination-in",p.beginPath(),p.arc(d/2,m/2,d/2,0,2*Math.PI,!0),p.closePath(),p.fill()),h}function z(e){var t=e.points,n=document.createElement("div"),i=document.createElement("img"),o=t[2]-t[0],s=t[3]-t[1];return a(n,"croppie-result"),n.appendChild(i),r(i,{left:-1*t[0]+"px",top:-1*t[1]+"px"}),i.src=e.url,r(n,{width:o+"px",height:s+"px"}),n}function Y(e){return Z.call(this,e).toDataURL(e.format,e.quality)}function W(e){var t=this;return new Promise(function(n){Z.call(t,e).toBlob(function(e){n(e)},e.format,e.quality)})}function X(e,t){var n,i=this,o=[],r=null,a=m.call(i);if("string"==typeof e)n=e,e={};else if(Array.isArray(e))o=e.slice();else{if("undefined"==typeof e&&i.data.url)return L.call(i),E.call(i),null;n=e.url,o=e.points||[],r="undefined"==typeof e.zoom?null:e.zoom}return i.data.bound=!1,i.data.url=n||i.data.url,i.data.boundZoom=r,u(n,i.elements.img,a).then(function(n){if(o.length)i.options.relative&&(o=[o[0]*n.naturalWidth/100,o[1]*n.naturalHeight/100,o[2]*n.naturalWidth/100,o[3]*n.naturalHeight/100]);else{var r,a,s=c(n),l=i.elements.viewport.getBoundingClientRect(),u=l.width/l.height,h=s.width/s.height;h>u?(a=s.height,r=a*u):(r=s.width,a=r/u);var p=(s.width-r)/2,d=(s.height-a)/2,m=p+r,f=d+a;i.data.points=[p,d,m,f]}i.data.points=o.map(function(e){return parseFloat(e)}),i.options.useCanvas&&M.call(i,e.orientation||1),L.call(i),E.call(i),t&&t()})}function F(e,t){return parseFloat(e).toFixed(t||0)}function H(){var e=this,t=e.elements.preview.getBoundingClientRect(),n=e.elements.viewport.getBoundingClientRect(),i=n.left-t.left,o=n.top-t.top,r=(n.width-e.elements.viewport.offsetWidth)/2,a=(n.height-e.elements.viewport.offsetHeight)/2,s=i+e.elements.viewport.offsetWidth+r,l=o+e.elements.viewport.offsetHeight+a,u=e._currentZoom;(u===1/0||isNaN(u))&&(u=1);var c=e.options.enforceBoundary?0:Number.NEGATIVE_INFINITY;return i=Math.max(c,i/u),o=Math.max(c,o/u),s=Math.max(c,s/u),l=Math.max(c,l/u),{points:[F(i),F(o),F(s),F(l)],zoom:u}}function k(e){var t,i=this,o=H.call(i),r=n(G,n({},e)),a="string"==typeof e?e:r.type||"base64",s=r.size||"viewport",l=r.format,u=r.quality,c=r.backgroundColor,h="boolean"==typeof r.circle?r.circle:"circle"===i.options.viewport.type,p=i.elements.viewport.getBoundingClientRect(),d=p.width/p.height;return"viewport"===s?(o.outputWidth=p.width,o.outputHeight=p.height):"object"==typeof s&&(s.width&&s.height?(o.outputWidth=s.width,o.outputHeight=s.height):s.width?(o.outputWidth=s.width,o.outputHeight=s.width/d):s.height&&(o.outputWidth=s.height*d,o.outputHeight=s.height)),J.indexOf(l)>-1&&(o.format="image/"+l,o.quality=u),o.circle=h,o.url=i.data.url,o.backgroundColor=c,t=new Promise(function(e){switch(a.toLowerCase()){case"rawcanvas":e(Z.call(i,o));break;case"canvas":case"base64":e(Y.call(i,o));break;case"blob":W.call(i,o).then(e);break;default:e(z.call(i,o))}})}function j(){L.call(this)}function S(e){if(!this.options.useCanvas)throw"Croppie: Cannot rotate without enableOrientation";var t=this,n=t.elements.canvas,i=document.createElement("canvas"),o=1;i.width=n.width,i.height=n.height;var r=i.getContext("2d");r.drawImage(n,0,0),(90===e||-270===e)&&(o=6),(-90===e||270===e)&&(o=8),(180===e||-180===e)&&(o=3),p(n,i,o),w.call(t),i=null}function O(){var e=this;e.element.removeChild(e.elements.boundary),s(e.element,"croppie-container"),e.options.enableZoom&&e.element.removeChild(e.elements.zoomerWrap),delete e.elements}function N(e,t){if(this.element=e,this.options=n(n({},N.defaults),t),"img"===this.element.tagName.toLowerCase()){var i=this.element;a(i,"cr-original-image");var o=document.createElement("div");this.element.parentNode.appendChild(o),o.appendChild(i),this.element=o,this.options.url=this.options.url||i.src}if(d.call(this),this.options.url){var r={url:this.options.url,points:this.options.points};delete this.options.url,delete this.options.points,X.call(this,r)}}"function"!=typeof Promise&&!function(e){function t(e,t){return function(){e.apply(t,arguments)}}function n(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],l(e,t(o,this),t(r,this))}function i(e){var t=this;return null===this._state?void this._deferreds.push(e):void c(function(){var n=t._state?e.onFulfilled:e.onRejected;if(null===n)return void(t._state?e.resolve:e.reject)(t._value);var i;try{i=n(t._value)}catch(o){return void e.reject(o)}e.resolve(i)})}function o(e){try{if(e===this)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if("function"==typeof n)return void l(t(n,e),t(o,this),t(r,this))}this._state=!0,this._value=e,a.call(this)}catch(i){r.call(this,i)}}function r(e){this._state=!1,this._value=e,a.call(this)}function a(){for(var e=0,t=this._deferreds.length;t>e;e++)i.call(this,this._deferreds[e]);this._deferreds=null}function s(e,t,n,i){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.resolve=n,this.reject=i}function l(e,t,n){var i=!1;try{e(function(e){i||(i=!0,t(e))},function(e){i||(i=!0,n(e))})}catch(o){if(i)return;i=!0,n(o)}}var u=setTimeout,c="function"==typeof setImmediate&&setImmediate||function(e){u(e,1)},h=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};n.prototype["catch"]=function(e){return this.then(null,e)},n.prototype.then=function(e,t){var o=this;return new n(function(n,r){i.call(o,new s(e,t,n,r))})},n.all=function(){var e=Array.prototype.slice.call(1===arguments.length&&h(arguments[0])?arguments[0]:arguments);return new n(function(t,n){function i(r,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(e){i(r,e)},n)}e[r]=a,0===--o&&t(e)}catch(l){n(l)}}if(0===e.length)return t([]);for(var o=e.length,r=0;ri;i++)e[i].then(t,n)})},n._setImmediateFn=function(e){c=e},"undefined"!=typeof module&&module.exports?module.exports=n:e.Promise||(e.Promise=n)}(this),"function"!=typeof window.CustomEvent&&!function(){function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),n}e.prototype=window.Event.prototype,window.CustomEvent=e}(),HTMLCanvasElement.prototype.toBlob||Object.defineProperty(HTMLCanvasElement.prototype,"toBlob",{value:function(e,t,n){for(var i=atob(this.toDataURL(t,n).split(",")[1]),o=i.length,r=new Uint8Array(o),a=0;o>a;a++)r[a]=i.charCodeAt(a);e(new Blob([r],{type:t||"image/png"}))}});var P,A,D,T=["Webkit","Moz","ms"],q=document.createElement("div").style;A=t("transform"),P=t("transformOrigin"),D=t("userSelect");var U={translate3d:{suffix:", 0px"},translate:{suffix:""}},K=function(e,t,n){this.x=parseFloat(e),this.y=parseFloat(t),this.scale=parseFloat(n)};K.parse=function(e){return e.style?K.parse(e.style[A]):e.indexOf("matrix")>-1||e.indexOf("none")>-1?K.fromMatrix(e):K.fromString(e)},K.fromMatrix=function(e){var t=e.substring(7).split(",");return t.length&&"none"!==e||(t=[1,0,0,1,0,0]),new K(l(t[4]),l(t[5]),parseFloat(t[0]))},K.fromString=function(e){var t=e.split(") "),n=t[0].substring(N.globals.translate.length+1).split(","),i=t.length>1?t[1].substring(6):1,o=n.length>1?n[0]:0,r=n.length>1?n[1]:0;return new K(o,r,i)},K.prototype.toString=function(){var e=U[N.globals.translate].suffix||"";return N.globals.translate+"("+this.x+"px, "+this.y+"px"+e+") scale("+this.scale+")"};var $=function(e){if(!e||!e.style[P])return this.x=0,void(this.y=0);var t=e.style[P].split(" ");this.x=parseFloat(t[0]),this.y=parseFloat(t[1])};$.prototype.toString=function(){return this.x+"px "+this.y+"px"};var Q=i(C,500),G={type:"canvas",format:"png",quality:1},J=["jpeg","webp","png"];if(window.jQuery){var V=window.jQuery;V.fn.croppie=function(e){var t=typeof e;if("string"===t){var n=Array.prototype.slice.call(arguments,1),i=V(this).data("croppie");return"get"===e?i.get():"result"===e?i.result.apply(i,n):"bind"===e?i.bind.apply(i,n):this.each(function(){var t=V(this).data("croppie");if(t){var i=t[e];if(!V.isFunction(i))throw"Croppie "+e+" method not found";i.apply(t,n),"destroy"===e&&V(this).removeData("croppie")}})}return this.each(function(){var t=new N(this,e);t.$=V,V(this).data("croppie",t)})}}N.defaults={viewport:{width:100,height:100,type:"square"},boundary:{},orientationControls:{enabled:!0,leftClass:"",rightClass:""},resizeControls:{width:!0,height:!0},customClass:"",showZoomer:!0,enableZoom:!0,enableResize:!1,mouseWheelZoom:!0,enableExif:!1,enforceBoundary:!0,enableOrientation:!1,enableKeyMovement:!0,update:function(){}},N.globals={translate:"translate3d"},n(N.prototype,{bind:function(e,t){return X.call(this,e,t)},get:function(){var e=H.call(this),t=e.points;return this.options.relative&&(t[0]/=this.elements.img.naturalWidth/100,t[1]/=this.elements.img.naturalHeight/100,t[2]/=this.elements.img.naturalWidth/100,t[3]/=this.elements.img.naturalHeight/100),e},result:function(e){return k.call(this,e)},refresh:function(){return j.call(this)},setZoom:function(e){v.call(this,e),o(this.elements.zoomer)},rotate:function(e){S.call(this,e)},destroy:function(){return O.call(this)}}),e.Croppie=window.Croppie=N,"object"==typeof module&&module.exports&&(module.exports=N)}); \ No newline at end of file +!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports&&"string"!=typeof exports.nodeName?module.exports=t():e.Croppie=t()}("undefined"!=typeof self?self:this,function(){"function"!=typeof Promise&&function(e){function t(e,t){return function(){e.apply(t,arguments)}}function i(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=null,this._value=null,this._deferreds=[],s(e,t(o,this),t(r,this))}function n(e){var t=this;return null===this._state?void this._deferreds.push(e):void h(function(){var i=t._state?e.onFulfilled:e.onRejected;if(null!==i){var n;try{n=i(t._value)}catch(t){return void e.reject(t)}e.resolve(n)}else(t._state?e.resolve:e.reject)(t._value)})}function o(e){try{if(e===this)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var i=e.then;if("function"==typeof i)return void s(t(i,e),t(o,this),t(r,this))}this._state=!0,this._value=e,a.call(this)}catch(e){r.call(this,e)}}function r(e){this._state=!1,this._value=e,a.call(this)}function a(){for(var e=0,t=this._deferreds.length;t>e;e++)n.call(this,this._deferreds[e]);this._deferreds=null}function s(e,t,i){var n=!1;try{e(function(e){n||(n=!0,t(e))},function(e){n||(n=!0,i(e))})}catch(e){if(n)return;n=!0,i(e)}}var l=setTimeout,h="function"==typeof setImmediate&&setImmediate||function(e){l(e,1)},u=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};i.prototype.catch=function(e){return this.then(null,e)},i.prototype.then=function(e,t){var o=this;return new i(function(i,r){n.call(o,new function(e,t,i,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.resolve=i,this.reject=n}(e,t,i,r))})},i.all=function(){var e=Array.prototype.slice.call(1===arguments.length&&u(arguments[0])?arguments[0]:arguments);return new i(function(t,i){function n(r,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(e){n(r,e)},i)}e[r]=a,0==--o&&t(e)}catch(e){i(e)}}if(0===e.length)return t([]);for(var o=e.length,r=0;rn;n++)e[n].then(t,i)})},i._setImmediateFn=function(e){h=e},"undefined"!=typeof module&&module.exports?module.exports=i:e.Promise||(e.Promise=i)}(this),"undefined"!=typeof window&&"function"!=typeof window.CustomEvent&&function(){function e(e,t){t=t||{bubbles:!1,cancelable:!1,detail:void 0};var i=document.createEvent("CustomEvent");return i.initCustomEvent(e,t.bubbles,t.cancelable,t.detail),i}e.prototype=window.Event.prototype,window.CustomEvent=e}(),"undefined"==typeof HTMLCanvasElement||HTMLCanvasElement.prototype.toBlob||Object.defineProperty(HTMLCanvasElement.prototype,"toBlob",{value:function(e,t,i){for(var n=atob(this.toDataURL(t,i).split(",")[1]),o=n.length,r=new Uint8Array(o),a=0;a=5){var r=i;i=n,n=r}return{width:i,height:n}}t=s("transform"),e=s("transformOrigin"),i=s("userSelect");var v={translate3d:{suffix:", 0px"},translate:{suffix:""}},g=function(e,t,i){this.x=parseFloat(e),this.y=parseFloat(t),this.scale=parseFloat(i)};g.parse=function(e){return e.style?g.parse(e.style[t]):e.indexOf("matrix")>-1||e.indexOf("none")>-1?g.fromMatrix(e):g.fromString(e)},g.fromMatrix=function(e){var t=e.substring(7).split(",");return t.length&&"none"!==e||(t=[1,0,0,1,0,0]),new g(m(t[4]),m(t[5]),parseFloat(t[0]))},g.fromString=function(e){var t=e.split(") "),i=t[0].substring(T.globals.translate.length+1).split(","),n=t.length>1?t[1].substring(6):1,o=i.length>1?i[0]:0,r=i.length>1?i[1]:0;return new g(o,r,n)},g.prototype.toString=function(){var e=v[T.globals.translate].suffix||"";return T.globals.translate+"("+this.x+"px, "+this.y+"px"+e+") scale("+this.scale+")"};var w=function(t){if(!t||!t.style[e])return this.x=0,void(this.y=0);var i=t.style[e].split(" ");this.x=parseFloat(i[0]),this.y=parseFloat(i[1])};function y(e){return e.exifdata&&e.exifdata.Orientation?m(e.exifdata.Orientation):1}function b(e,t,i){var n=t.width,o=t.height,r=e.getContext("2d");switch(e.width=t.width,e.height=t.height,r.save(),i){case 2:r.translate(n,0),r.scale(-1,1);break;case 3:r.translate(n,o),r.rotate(180*Math.PI/180);break;case 4:r.translate(0,o),r.scale(1,-1);break;case 5:e.width=o,e.height=n,r.rotate(90*Math.PI/180),r.scale(1,-1);break;case 6:e.width=o,e.height=n,r.rotate(90*Math.PI/180),r.translate(0,-o);break;case 7:e.width=o,e.height=n,r.rotate(-90*Math.PI/180),r.translate(-n,o),r.scale(1,-1);break;case 8:e.width=o,e.height=n,r.translate(0,n),r.rotate(-90*Math.PI/180)}r.drawImage(t,0,0,n,o),r.restore()}function x(){var n,o,r,a,s,l,h=this.options.viewport.type?"cr-vp-"+this.options.viewport.type:null;this.options.useCanvas=this.options.enableOrientation||C.call(this),this.data={},this.elements={},n=this.elements.boundary=document.createElement("div"),r=this.elements.viewport=document.createElement("div"),o=this.elements.img=document.createElement("img"),a=this.elements.overlay=document.createElement("div"),this.options.useCanvas?(this.elements.canvas=document.createElement("canvas"),this.elements.preview=this.elements.canvas):this.elements.preview=o,p(n,"cr-boundary"),n.setAttribute("aria-dropeffect","none"),s=this.options.boundary.width,l=this.options.boundary.height,c(n,{width:s+(isNaN(s)?"":"px"),height:l+(isNaN(l)?"":"px")}),p(r,"cr-viewport"),h&&p(r,h),c(r,{width:this.options.viewport.width+"px",height:this.options.viewport.height+"px"}),r.setAttribute("tabindex",0),p(this.elements.preview,"cr-image"),d(this.elements.preview,{alt:"preview","aria-grabbed":"false"}),p(a,"cr-overlay"),this.element.appendChild(n),n.appendChild(this.elements.preview),n.appendChild(r),n.appendChild(a),p(this.element,"croppie-container"),this.options.customClass&&p(this.element,this.options.customClass),function(){var e,n,o,r,a,s=this,l=!1;function h(e,t){var i=s.elements.preview.getBoundingClientRect(),n=a.y+t,o=a.x+e;s.options.enforceBoundary?(r.top>i.top+t&&r.bottomi.left+e&&r.right1){var v=i.touches[0],g=i.touches[1],w=Math.sqrt((v.pageX-g.pageX)*(v.pageX-g.pageX)+(v.pageY-g.pageY)*(v.pageY-g.pageY));o||(o=w/s._currentZoom);var y=w/o;return E.call(s,y),void u(s.elements.zoomer)}h(d,m),f[t]=a.toString(),c(s.elements.preview,f),L.call(s),n=l,e=r}function f(){p(l=!1),window.removeEventListener("mousemove",m),window.removeEventListener("touchmove",m),window.removeEventListener("mouseup",f),window.removeEventListener("touchend",f),document.body.style[i]="",_.call(s),z.call(s),o=0}s.elements.overlay.addEventListener("mousedown",d),s.elements.viewport.addEventListener("keydown",function(e){var n=37,l=38,u=39,p=40;if(!e.shiftKey||e.keyCode!==l&&e.keyCode!==p){if(s.options.enableKeyMovement&&e.keyCode>=37&&e.keyCode<=40){e.preventDefault();var d=function(e){switch(e){case n:return[1,0];case l:return[0,1];case u:return[-1,0];case p:return[0,-1]}}(e.keyCode);a=g.parse(s.elements.preview),document.body.style[i]="none",r=s.elements.viewport.getBoundingClientRect(),function(e){var n=e[0],r=e[1],l={};h(n,r),l[t]=a.toString(),c(s.elements.preview,l),L.call(s),document.body.style[i]="",_.call(s),z.call(s),o=0}(d)}}else{var m;m=e.keyCode===l?parseFloat(s.elements.zoomer.value)+parseFloat(s.elements.zoomer.step):parseFloat(s.elements.zoomer.value)-parseFloat(s.elements.zoomer.step),s.setZoom(m)}}),s.elements.overlay.addEventListener("touchstart",d)}.call(this),this.options.enableZoom&&function(){var i=this,n=i.elements.zoomerWrap=document.createElement("div"),o=i.elements.zoomer=document.createElement("input");function r(){(function(i){var n=this,o=i?i.transform:g.parse(n.elements.preview),r=i?i.viewportRect:n.elements.viewport.getBoundingClientRect(),a=i?i.origin:new w(n.elements.preview);function s(){var i={};i[t]=o.toString(),i[e]=a.toString(),c(n.elements.preview,i)}if(n._currentZoom=i?i.value:n._currentZoom,o.scale=n._currentZoom,n.elements.zoomer.setAttribute("aria-valuenow",n._currentZoom),s(),n.options.enforceBoundary){var l=function(e){var t=this._currentZoom,i=e.width,n=e.height,o=this.elements.boundary.clientWidth/2,r=this.elements.boundary.clientHeight/2,a=this.elements.preview.getBoundingClientRect(),s=a.width,l=a.height,h=i/2,u=n/2,c=-1*(h/t-o),p=-1*(u/t-r),d=1/t*h,m=1/t*u;return{translate:{maxX:c,minX:c-(s*(1/t)-i*(1/t)),maxY:p,minY:p-(l*(1/t)-n*(1/t))},origin:{maxX:s*(1/t)-d,minX:d,maxY:l*(1/t)-m,minY:m}}}.call(n,r),h=l.translate,u=l.origin;o.x>=h.maxX&&(a.x=u.minX,o.x=h.maxX),o.x<=h.minX&&(a.x=u.maxX,o.x=h.minX),o.y>=h.maxY&&(a.y=u.minY,o.y=h.maxY),o.y<=h.minY&&(a.y=u.maxY,o.y=h.minY)}s(),M.call(n),z.call(n)}).call(i,{value:parseFloat(o.value),origin:new w(i.elements.preview),viewportRect:i.elements.viewport.getBoundingClientRect(),transform:g.parse(i.elements.preview)})}function a(e){var t,n;if("ctrl"===i.options.mouseWheelZoom&&!0!==e.ctrlKey)return 0;t=e.wheelDelta?e.wheelDelta/1200:e.deltaY?e.deltaY/1060:e.detail?e.detail/-60:0,n=i._currentZoom+t*i._currentZoom,e.preventDefault(),E.call(i,n),r.call(i)}p(n,"cr-slider-wrap"),p(o,"cr-slider"),o.type="range",o.step="0.0001",o.value="1",o.style.display=i.options.showZoomer?"":"none",o.setAttribute("aria-label","zoom"),i.element.appendChild(n),n.appendChild(o),i._currentZoom=1,i.elements.zoomer.addEventListener("input",r),i.elements.zoomer.addEventListener("change",r),i.options.mouseWheelZoom&&(i.elements.boundary.addEventListener("mousewheel",a),i.elements.boundary.addEventListener("DOMMouseScroll",a))}.call(this),this.options.enableResize&&function(){var e,t,n,o,r,a,s,l=this,h=document.createElement("div"),u=!1,d=50;p(h,"cr-resizer"),c(h,{width:this.options.viewport.width+"px",height:this.options.viewport.height+"px"}),this.options.resizeControls.height&&(p(a=document.createElement("div"),"cr-resizer-vertical"),h.appendChild(a));this.options.resizeControls.width&&(p(s=document.createElement("div"),"cr-resizer-horisontal"),h.appendChild(s));function m(a){if((void 0===a.button||0===a.button)&&(a.preventDefault(),!u)){var s=l.elements.overlay.getBoundingClientRect();if(u=!0,t=a.pageX,n=a.pageY,e=-1!==a.currentTarget.className.indexOf("vertical")?"v":"h",o=s.width,r=s.height,a.touches){var h=a.touches[0];t=h.pageX,n=h.pageY}window.addEventListener("mousemove",f),window.addEventListener("touchmove",f),window.addEventListener("mouseup",v),window.addEventListener("touchend",v),document.body.style[i]="none"}}function f(i){var a=i.pageX,s=i.pageY;if(i.preventDefault(),i.touches){var u=i.touches[0];a=u.pageX,s=u.pageY}var p=a-t,m=s-n,f=l.options.viewport.height+m,v=l.options.viewport.width+p;"v"===e&&f>=d&&f<=r?(c(h,{height:f+"px"}),l.options.boundary.height+=m,c(l.elements.boundary,{height:l.options.boundary.height+"px"}),l.options.viewport.height+=m,c(l.elements.viewport,{height:l.options.viewport.height+"px"})):"h"===e&&v>=d&&v<=o&&(c(h,{width:v+"px"}),l.options.boundary.width+=p,c(l.elements.boundary,{width:l.options.boundary.width+"px"}),l.options.viewport.width+=p,c(l.elements.viewport,{width:l.options.viewport.width+"px"})),L.call(l),X.call(l),_.call(l),z.call(l),n=s,t=a}function v(){u=!1,window.removeEventListener("mousemove",f),window.removeEventListener("touchmove",f),window.removeEventListener("mouseup",v),window.removeEventListener("touchend",v),document.body.style[i]=""}a&&(a.addEventListener("mousedown",m),a.addEventListener("touchstart",m));s&&(s.addEventListener("mousedown",m),s.addEventListener("touchstart",m));this.elements.boundary.appendChild(h)}.call(this)}function C(){return this.options.enableExif&&window.EXIF}function E(e){if(this.options.enableZoom){var t=this.elements.zoomer,i=O(e,4);t.value=Math.max(parseFloat(t.min),Math.min(parseFloat(t.max),i)).toString()}}function _(i){var n=this._currentZoom,o=this.elements.preview.getBoundingClientRect(),r=this.elements.viewport.getBoundingClientRect(),a=g.parse(this.elements.preview.style[t]),s=new w(this.elements.preview),l=r.top-o.top+r.height/2,h=r.left-o.left+r.width/2,u={},p={};if(i){var d=s.x,m=s.y,f=a.x,v=a.y;u.y=d,u.x=m,a.y=f,a.x=v}else u.y=l/n,u.x=h/n,p.y=(u.y-s.y)*(1-n),p.x=(u.x-s.x)*(1-n),a.x-=p.x,a.y-=p.y;var y={};y[e]=u.x+"px "+u.y+"px",y[t]=a.toString(),c(this.elements.preview,y)}function L(){if(this.elements){var e=this.elements.boundary.getBoundingClientRect(),t=this.elements.preview.getBoundingClientRect();c(this.elements.overlay,{width:t.width+"px",height:t.height+"px",top:t.top-e.top+"px",left:t.left-e.left+"px"})}}w.prototype.toString=function(){return this.x+"px "+this.y+"px"};var R,B,Z,I,M=(R=L,B=500,function(){var e=this,t=arguments,i=Z&&!I;clearTimeout(I),I=setTimeout(function(){I=null,Z||R.apply(e,t)},B),i&&R.apply(e,t)});function z(){var e,t=this.get();F.call(this)&&(this.options.update.call(this,t),this.$&&"undefined"==typeof Prototype?this.$(this.element).trigger("update.croppie",t):(window.CustomEvent?e=new CustomEvent("update",{detail:t}):(e=document.createEvent("CustomEvent")).initCustomEvent("update",!0,!0,t),this.element.dispatchEvent(e)))}function F(){return this.elements.preview.offsetHeight>0&&this.elements.preview.offsetWidth>0}function W(){var i,n={},o=this.elements.preview,r=new g(0,0,1),a=new w;F.call(this)&&!this.data.bound&&(this.data.bound=!0,n[t]=r.toString(),n[e]=a.toString(),n.opacity=1,c(o,n),i=this.elements.preview.getBoundingClientRect(),this._originalImageWidth=i.width,this._originalImageHeight=i.height,this.data.orientation=C.call(this)?y(this.elements.img):this.data.orientation,this.options.enableZoom?X.call(this,!0):this._currentZoom=1,r.scale=this._currentZoom,n[t]=r.toString(),c(o,n),this.data.points.length?function(i){if(4!==i.length)throw"Croppie - Invalid number of points supplied: "+i;var n=i[2]-i[0],o=this.elements.viewport.getBoundingClientRect(),r=this.elements.boundary.getBoundingClientRect(),a={left:o.left-r.left,top:o.top-r.top},s=o.width/n,l=i[1],h=i[0],u=-1*i[1]+a.top,p=-1*i[0]+a.left,d={};d[e]=h+"px "+l+"px",d[t]=new g(p,u,s).toString(),c(this.elements.preview,d),E.call(this,s),this._currentZoom=s}.call(this,this.data.points):function(){var e=this.elements.preview.getBoundingClientRect(),i=this.elements.viewport.getBoundingClientRect(),n=this.elements.boundary.getBoundingClientRect(),o=i.left-n.left,r=i.top-n.top,a=o-(e.width-i.width)/2,s=r-(e.height-i.height)/2,l=new g(a,s,this._currentZoom);c(this.elements.preview,t,l.toString())}.call(this),_.call(this),L.call(this))}function X(e){var t,i,n,o,r=Math.max(this.options.minZoom,0)||0,a=this.options.maxZoom||1.5,s=this.elements.zoomer,l=parseFloat(s.value),h=this.elements.boundary.getBoundingClientRect(),c=f(this.elements.img,this.data.orientation),p=this.elements.viewport.getBoundingClientRect();this.options.enforceBoundary&&(n=p.width/c.width,o=p.height/c.height,r=Math.max(n,o)),r>=a&&(a=r+1),s.min=O(r,4),s.max=O(a,4),!e&&(ls.max)?E.call(this,lthis._originalImageWidth&&(w=(d=this._originalImageWidth-c)/o*h),n<0&&(p=0,g=Math.abs(n)/r*u),f+p>this._originalImageHeight&&(y=(f=this._originalImageHeight-p)/r*u),l.drawImage(this.elements.preview,c,p,d,f,v,g,w,y),a&&(l.fillStyle="#fff",l.globalCompositeOperation="destination-in",l.beginPath(),l.arc(s.width/2,s.height/2,s.width/2,0,2*Math.PI,!0),l.closePath(),l.fill()),s}function H(e,t){var i,n=this,o=[],r=null,a=C.call(n);if("string"==typeof e)i=e,e={};else if(Array.isArray(e))o=e.slice();else{if(void 0===e&&n.data.url)return W.call(n),z.call(n),null;i=e.url,o=e.points||[],r=void 0===e.zoom?null:e.zoom}return n.data.bound=!1,n.data.url=i||n.data.url,n.data.boundZoom=r,function(e,t){if(!e)throw"Source image missing";var i=new Image;return i.style.opacity="0",new Promise(function(n,o){function r(){i.style.opacity="1",setTimeout(function(){n(i)},1)}i.removeAttribute("crossOrigin"),e.match(/^https?:\/\/|^\/\//)&&i.setAttribute("crossOrigin","anonymous"),i.onload=function(){t?EXIF.getData(i,function(){r()}):r()},i.onerror=function(e){i.style.opacity=1,setTimeout(function(){o(e)},1)},i.src=e})}(i,a).then(function(i){if(function(e){this.elements.img.parentNode&&(Array.prototype.forEach.call(this.elements.img.classList,function(t){e.classList.add(t)}),this.elements.img.parentNode.replaceChild(e,this.elements.img),this.elements.preview=e),this.elements.img=e}.call(n,i),o.length)n.options.relative&&(o=[o[0]*i.naturalWidth/100,o[1]*i.naturalHeight/100,o[2]*i.naturalWidth/100,o[3]*i.naturalHeight/100]);else{var r,a,s=f(i),l=n.elements.viewport.getBoundingClientRect(),h=l.width/l.height;s.width/s.height>h?r=(a=s.height)*h:(r=s.width,a=s.height/h);var u=(s.width-r)/2,c=(s.height-a)/2,p=u+r,d=c+a;n.data.points=[u,c,p,d]}n.data.orientation=e.orientation||1,n.data.points=o.map(function(e){return parseFloat(e)}),n.options.useCanvas&&function(e){var t=this.elements.canvas,i=this.elements.img;t.getContext("2d").clearRect(0,0,t.width,t.height),t.width=i.width,t.height=i.height,b(t,i,this.options.enableOrientation&&e||y(i))}.call(n,n.data.orientation),W.call(n),z.call(n),t&&t()})}function O(e,t){return parseFloat(e).toFixed(t||0)}function k(){var e=this.elements.preview.getBoundingClientRect(),t=this.elements.viewport.getBoundingClientRect(),i=t.left-e.left,n=t.top-e.top,o=(t.width-this.elements.viewport.offsetWidth)/2,r=(t.height-this.elements.viewport.offsetHeight)/2,a=i+this.elements.viewport.offsetWidth+o,s=n+this.elements.viewport.offsetHeight+r,l=this._currentZoom;(l===1/0||isNaN(l))&&(l=1);var h=this.options.enforceBoundary?0:Number.NEGATIVE_INFINITY;return i=Math.max(h,i/l),n=Math.max(h,n/l),a=Math.max(h,a/l),s=Math.max(h,s/l),{points:[O(i),O(n),O(a),O(s)],zoom:l,orientation:this.data.orientation}}var A={type:"canvas",format:"png",quality:1},S=["jpeg","webp","png"];function j(e){var t=this,i=k.call(t),n=l(h(A),h(e)),o="string"==typeof e?e:n.type||"base64",r=n.size||"viewport",a=n.format,s=n.quality,u=n.backgroundColor,d="boolean"==typeof n.circle?n.circle:"circle"===t.options.viewport.type,m=t.elements.viewport.getBoundingClientRect(),f=m.width/m.height;return"viewport"===r?(i.outputWidth=m.width,i.outputHeight=m.height):"object"==typeof r&&(r.width&&r.height?(i.outputWidth=r.width,i.outputHeight=r.height):r.width?(i.outputWidth=r.width,i.outputHeight=r.width/f):r.height&&(i.outputWidth=r.height*f,i.outputHeight=r.height)),S.indexOf(a)>-1&&(i.format="image/"+a,i.quality=s),i.circle=d,i.url=t.data.url,i.backgroundColor=u,new Promise(function(e){switch(o.toLowerCase()){case"rawcanvas":e(Y.call(t,i));break;case"canvas":case"base64":e(function(e){return Y.call(this,e).toDataURL(e.format,e.quality)}.call(t,i));break;case"blob":(function(e){var t=this;return new Promise(function(i){Y.call(t,e).toBlob(function(e){i(e)},e.format,e.quality)})}).call(t,i).then(e);break;default:e(function(e){var t=e.points,i=document.createElement("div"),n=document.createElement("img"),o=t[2]-t[0],r=t[3]-t[1];return p(i,"croppie-result"),i.appendChild(n),c(n,{left:-1*t[0]+"px",top:-1*t[1]+"px"}),n.src=e.url,c(i,{width:o+"px",height:r+"px"}),i}.call(t,i))}})}function N(e){if(!this.options.useCanvas||!this.options.enableOrientation)throw"Croppie: Cannot rotate without enableOrientation && EXIF.js included";var t,i,n,o,s,l=this.elements.canvas;if(this.data.orientation=(t=this.data.orientation,i=e,n=r.indexOf(t)>-1?r:a,o=n.indexOf(t),s=i/90%n.length,n[(n.length+o+s%n.length)%n.length]),b(l,this.elements.img,this.data.orientation),_.call(this,!0),X.call(this),Math.abs(e)/90%2==1){var h=this._originalImageHeight,u=this._originalImageWidth;this._originalImageWidth=h,this._originalImageHeight=u}}if("undefined"!=typeof window&&window.jQuery){var P=window.jQuery;P.fn.croppie=function(e){if("string"===typeof e){var t=Array.prototype.slice.call(arguments,1),i=P(this).data("croppie");return"get"===e?i.get():"result"===e?i.result.apply(i,t):"bind"===e?i.bind.apply(i,t):this.each(function(){var i=P(this).data("croppie");if(i){var n=i[e];if(!P.isFunction(n))throw"Croppie "+e+" method not found";n.apply(i,t),"destroy"===e&&P(this).removeData("croppie")}})}return this.each(function(){var t=new T(this,e);t.$=P,P(this).data("croppie",t)})}}function T(e,t){if(e.className.indexOf("croppie-container")>-1)throw new Error("Croppie: Can't initialize croppie more than once");if(this.element=e,this.options=l(h(T.defaults),t),"img"===this.element.tagName.toLowerCase()){var i=this.element;p(i,"cr-original-image"),d(i,{"aria-hidden":"true",alt:""});var n=document.createElement("div");this.element.parentNode.appendChild(n),n.appendChild(i),this.element=n,this.options.url=this.options.url||i.src}if(x.call(this),this.options.url){var o={url:this.options.url,points:this.options.points};delete this.options.url,delete this.options.points,H.call(this,o)}}return T.defaults={viewport:{width:100,height:100,type:"square"},boundary:{},orientationControls:{enabled:!0,leftClass:"",rightClass:""},resizeControls:{width:!0,height:!0},customClass:"",showZoomer:!0,enableZoom:!0,enableResize:!1,mouseWheelZoom:!0,enableExif:!1,enforceBoundary:!0,enableOrientation:!1,enableKeyMovement:!0,update:function(){}},T.globals={translate:"translate3d"},l(T.prototype,{bind:function(e,t){return H.call(this,e,t)},get:function(){var e=k.call(this),t=e.points;return this.options.relative&&(t[0]/=this.elements.img.naturalWidth/100,t[1]/=this.elements.img.naturalHeight/100,t[2]/=this.elements.img.naturalWidth/100,t[3]/=this.elements.img.naturalHeight/100),e},result:function(e){return j.call(this,e)},refresh:function(){return function(){W.call(this)}.call(this)},setZoom:function(e){E.call(this,e),u(this.elements.zoomer)},rotate:function(e){N.call(this,e)},destroy:function(){return function(){var e,t;this.element.removeChild(this.elements.boundary),e=this.element,t="croppie-container",e.classList?e.classList.remove(t):e.className=e.className.replace(t,""),this.options.enableZoom&&this.element.removeChild(this.elements.zoomerWrap),delete this.elements}.call(this)}}),T}); \ No newline at end of file diff --git a/demo/demo.css b/demo/demo.css index 8aba05a4..9807bb87 100644 --- a/demo/demo.css +++ b/demo/demo.css @@ -32,11 +32,17 @@ h1 { padding-top: 30px; margin: 15px 0; } - +h3 { + font-size: 18px; + font-weight: 400; + border-bottom: 1px solid #0C4648; + margin: 15px 0 10px; +} nav { position: absolute; top: 0; right: 0; + padding:15px; } nav a { @@ -171,12 +177,6 @@ h2 { margin: 0 0 5px 0; } -.documentation h3 { - font-size: 18px; - font-weight: 400; - border-bottom: 1px solid #0C4648; - margin: 15px 0 10px; -} .documentation ul { list-style: none; padding: 0; @@ -218,6 +218,10 @@ h2 { color: #777; } +.important-notes article { + margin-bottom: 2em; +} + .upload-demo .upload-demo-wrap, .upload-demo .upload-result, .upload-demo.ready .upload-msg { diff --git a/demo/demo.js b/demo/demo.js index f3eb2e28..c7a066b8 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -40,23 +40,24 @@ var Demo = (function() { viewport: { width: 150, height: 150, - type: 'square' + type: 'circle' }, boundary: { width: 300, height: 300 }, // url: 'demo/demo-1.jpg', - enforceBoundary: false + // enforceBoundary: false // mouseWheelZoom: false }); - mc.on('update', function (ev, data) { + mc.on('update.croppie', function (ev, data) { // console.log('jquery update', ev, data); }); $('.js-main-image').on('click', function (ev) { mc.croppie('result', { - type: 'rawcanvas', - // size: { width: 300, height: 300 }, + type: 'rawcanvas', + circle: true, + // size: { width: 300, height: 300 }, format: 'png' }).then(function (canvas) { popupResult({ @@ -93,7 +94,11 @@ var Demo = (function() { } basic.croppie('result', { type: 'canvas', - size: size + size: size, + resultSize: { + width: 50, + height: 50 + } }).then(function (resp) { popupResult({ src: resp @@ -105,7 +110,7 @@ var Demo = (function() { function demoVanilla() { var vEl = document.getElementById('vanilla-demo'), vanilla = new Croppie(vEl, { - viewport: { width: 100, height: 100 }, + viewport: { width: 200, height: 100 }, boundary: { width: 300, height: 300 }, showZoomer: false, enableOrientation: true @@ -116,7 +121,7 @@ var Demo = (function() { zoom: 0 }); vEl.addEventListener('update', function (ev) { - console.log('vanilla update', ev); + // console.log('vanilla update', ev); }); document.querySelector('.vanilla-result').addEventListener('click', function (ev) { vanilla.result({ @@ -140,7 +145,8 @@ var Demo = (function() { boundary: { width: 300, height: 300 }, showZoomer: false, enableResize: true, - enableOrientation: true + enableOrientation: true, + mouseWheelZoom: 'ctrl' }); resize.bind({ url: 'demo/demo-2.jpg', @@ -228,13 +234,13 @@ var Demo = (function() { } function bindNavigation () { - var $body = $('body'); + var $html = $('html'); $('nav a').on('click', function (ev) { var lnk = $(ev.currentTarget), href = lnk.attr('href'), targetTop = $('a[name=' + href.substring(1) + ']').offset().top; - $body.animate({ scrollTop: targetTop }); + $html.animate({ scrollTop: targetTop }); ev.preventDefault(); }); } diff --git a/index.html b/index.html index 79773720..928a04b5 100644 --- a/index.html +++ b/index.html @@ -25,12 +25,10 @@
@@ -129,6 +127,12 @@

Options

Default false +
  • + enableResizeboolean +

    Enable or disable support for resizing the viewport area.

    + Default + false +
  • enableZoomboolean

    Enable zooming functionality. If set to false - scrolling and pinching would not zoom.

    @@ -140,8 +144,8 @@

    Options

    Defaulttrue
  • - mouseWheelZoomboolean -

    Enable or disable the ability to use the mouse wheel to zoom in and out on a croppie instance

    + mouseWheelZoombool/string +

    Enable or disable the ability to use the mouse wheel to zoom in and out on a croppie instance. If 'ctrl' is passed mouse wheel will only work while control keyboard is pressed

    Defaulttrue
  • @@ -172,13 +176,13 @@

    Methods

  • bind({ url, points, orientation, zoom })Promise -

    Bind an image the croppie. Returns a promise to be resolved when the image has been loaded and the croppie has been initialized.

    +

    Bind an image to the croppie. Returns a promise to be resolved when the image has been loaded and the croppie has been initialized.

    Parameters
    • url URL to image
    • points Array of points that translate into [topLeftX, topLeftY, bottomRightX, bottomRightY]
    • - zoom Apply zoom after image has been bound +
    • zoom Apply zoom after image has been bound
    • orientation Custom orientation, applied after exif orientation (if enabled). Only works with enableOrientation option enabled (see 'Options').
      @@ -192,7 +196,6 @@

      Methods

    • 6 rotated clockwise by 90 degrees
    • 7 flipped horizontally, then rotated right by 90 degrees
    • 8 rotated counter-clockwise by 90 degrees
    • -
  • @@ -275,13 +278,19 @@

    Methods

    +

    Events

    • - update(croppe)Croppie + update(croppie)Croppie

      Triggered when a drag or zoom occurs

      +
      
      +$('.my-croppie').on('update.croppie', function(ev, cropData) {});
      +// or
      +document.getElementById('another-croppie').addEventListener('update', function(ev) { var cropData = ev.detail; });
      +                            
    @@ -370,7 +379,8 @@

    Demos

    boundary: { width: 300, height: 300 }, showZoomer: false, enableResize: true, - enableOrientation: true + enableOrientation: true, + mouseWheelZoom: 'ctrl' }); resize.bind({ url: 'demo/demo-2.jpg', @@ -447,6 +457,29 @@

    Demos

    +
    + +

    Important Notes

    +
    +
    + +

    Image Hosting & Cross Origin Errors

    +

    Croppie uses canvas.drawImage(...) to manipulate images. Thus, images must obey the CORS policy. More info can be found here.

    +
    +
    + +

    Visibility and Binding

    +

    Croppie is dependent on it's container being visible when the bind method is called. This can be an issue when your croppie component is inside a modal that isn't shown. Let's take the bootstrap modal for example..

    +
    
    +var myCroppie = $('#my-croppie').croppie(opts);
    +$('#my-modal').on('shown.bs.modal', function(){ 
    +    myCroppie.croppie('bind', bindOpts);
    +});
    +                    
    +

    If you are having issues getting the correct crop result, and your croppie instance is shown inside of a modal, try taking your croppie out of the modal and see if your issues persist. If they don't, then make sure that your bind method is called after the modal is done animating.

    +
    +
    +
    @@ -465,7 +498,6 @@

    Browser Support

  • iOS
  • Android
  • -

    IE9 may be supported, but it isn't tested. If you're able to test it and let us know, please do so on Github.

    diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..1d78d10e --- /dev/null +++ b/package-lock.json @@ -0,0 +1,424 @@ +{ + "name": "croppie", + "version": "2.6.5", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "collections": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/collections/-/collections-0.2.2.tgz", + "integrity": "sha1-HyMCay7zb5J+7MkB6ZxfDUj6M04=", + "dev": true, + "requires": { + "weak-map": "1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "gh-pages": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-0.11.0.tgz", + "integrity": "sha1-kzE8bcv8dNQmvIminr/2QgrMPBs=", + "dev": true, + "requires": { + "async": "1.5.2", + "commander": "2.9.0", + "globby": "^4.0.0", + "graceful-fs": "4.1.2", + "q": "1.4.1", + "q-io": "1.13.2", + "wrench": "1.5.8" + } + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globby": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", + "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^6.0.1", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.2.tgz", + "integrity": "sha1-/iI5t1dJcuZ+QfgIgj+b+kqZHjc=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mimeparse": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", + "integrity": "sha1-2vsCdSNw/SJgk64xUsJxrwGsJUo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.4.5.tgz", + "integrity": "sha1-FRdo3Sh161G8gpXpgAAm6fK7OY8=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0" + }, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "glob": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "~2.0.0", + "inherits": "2", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "q-io": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.13.2.tgz", + "integrity": "sha1-7qEw1IHdteGqG8WmaFX3OR0G8AM=", + "dev": true, + "requires": { + "collections": "^0.2.0", + "mime": "^1.2.11", + "mimeparse": "^0.1.4", + "q": "^1.0.1", + "qs": "^1.2.1", + "url2": "^0.0.0" + } + }, + "qs": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + }, + "uglify-js": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.15.tgz", + "integrity": "sha512-bqtBCAINYXX/OkdnqMGpbXr+OPWc00hsozRpk+dAtfnbdk2jjKiLmyOkQ7zamg648lVMnzATL8JrSN6LmaVpYA==", + "dev": true, + "requires": { + "commander": "~2.15.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + } + } + }, + "url2": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", + "integrity": "sha1-Tqq9HVw6yQ1iq0SFyZhCKGWgSxo=", + "dev": true + }, + "weak-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.0.tgz", + "integrity": "sha1-tm5Wqd8L0lp2u/G1FNsSkIBhSjc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "wrench": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.8.tgz", + "integrity": "sha1-ejHJf3hpJG12xc8vXJd6HEyOWrU=", + "dev": true + } + } +} diff --git a/package.json b/package.json index cb5f955c..d2ac5653 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,17 @@ { "name": "croppie", - "version": "2.5.0", + "version": "2.6.5", "description": "A simple javascript image cropper", "main": "croppie.js", "devDependencies": { "gh-pages": "^0.11.0", - "mocha": "2.4.5" + "mocha": "2.4.5", + "uglify-js": "3.3.15" }, "scripts": { "test": "mocha test/unit", - "deploy": "node deploy.js" + "deploy": "node deploy.js", + "uglify": "uglifyjs croppie.js -c -m -r '$,require,exports' -o croppie.min.js" }, "repository": { "type": "git",