summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorspider@dev <spiderr@bitweaver.org>2016-07-23 17:33:04 -0400
committerspider@dev <spiderr@bitweaver.org>2016-07-23 17:33:04 -0400
commitf63fbefabdd884bac1095cde5ca1291a11696af8 (patch)
treefabdcde7eb6d80f3254daf448057336520532427
parent1468e29c86adc9948ebecbb928adfe8cf8f36ba8 (diff)
downloadutil-f63fbefabdd884bac1095cde5ca1291a11696af8.tar.gz
util-f63fbefabdd884bac1095cde5ca1291a11696af8.tar.bz2
util-f63fbefabdd884bac1095cde5ca1291a11696af8.zip
update cropper from v0.7.9 to v1.0.0
-rw-r--r--javascript/jquery/plugins/cropper/cropper.css156
-rw-r--r--javascript/jquery/plugins/cropper/cropper.js2836
-rw-r--r--javascript/jquery/plugins/cropper/cropper.min.css10
-rw-r--r--javascript/jquery/plugins/cropper/cropper.min.js9
4 files changed, 1951 insertions, 1060 deletions
diff --git a/javascript/jquery/plugins/cropper/cropper.css b/javascript/jquery/plugins/cropper/cropper.css
index 9677011..6df89f1 100644
--- a/javascript/jquery/plugins/cropper/cropper.css
+++ b/javascript/jquery/plugins/cropper/cropper.css
@@ -1,34 +1,44 @@
/*!
- * Cropper v0.7.9
+ * Cropper v1.0.0
* https://github.com/fengyuanchen/cropper
*
- * Copyright 2014-2015 Fengyuan Chen
+ * Copyright (c) 2014-2015 Fengyuan Chen and contributors
* Released under the MIT license
+ *
+ * Date: 2015-10-10T02:10:06.999Z
*/
-
.cropper-container {
position: relative;
overflow: hidden;
+ font-size: 0;
+ line-height: 0;
+ -ms-touch-action: none;
+ touch-action: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
+ direction: ltr !important;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
-
.cropper-container img {
+ display: block;
width: 100%;
min-width: 0 !important;
max-width: none !important;
- height: 100%;
+ height: 100%;
min-height: 0 !important;
max-height: none !important;
+
+ image-orientation: 0deg !important;
}
-.cropper-modal,
-.cropper-canvas {
+.cropper-canvas,
+.cropper-drag-box,
+.cropper-crop-box,
+.cropper-modal {
position: absolute;
top: 0;
right: 0;
@@ -36,63 +46,81 @@
left: 0;
}
-.cropper-canvas {
+.cropper-drag-box {
background-color: #fff;
- filter: alpha(opacity=0);
+ filter: alpha(opacity=0);
opacity: 0;
}
.cropper-modal {
background-color: #000;
- filter: alpha(opacity=50);
+ filter: alpha(opacity=50);
opacity: .5;
}
-.cropper-dragger {
- position: absolute;
- top: 10%;
- left: 10%;
- width: 80%;
- height: 80%;
-}
-
-.cropper-viewer {
+.cropper-view-box {
display: block;
width: 100%;
- height: 100%;
+ height: 100%;
overflow: hidden;
- outline-width: 1px;
- outline-style: solid;
- outline-color: #69f;
- outline-color: rgba(51, 102, 255, .75);
+ outline: 1px solid #39f;
+ outline-color: rgba(51, 153, 255, .75);
}
.cropper-dashed {
position: absolute;
display: block;
- filter: alpha(opacity=50);
- border: 0 dashed #fff;
+ filter: alpha(opacity=50);
+ border: 0 dashed #eee;
opacity: .5;
}
-
.cropper-dashed.dashed-h {
- top: 33.3%;
+ top: 33.33333%;
left: 0;
width: 100%;
- height: 33.3%;
+ height: 33.33333%;
border-top-width: 1px;
border-bottom-width: 1px;
}
-
.cropper-dashed.dashed-v {
top: 0;
- left: 33.3%;
- width: 33.3%;
- height: 100%;
+ left: 33.33333%;
+ width: 33.33333%;
+ height: 100%;
border-right-width: 1px;
border-left-width: 1px;
}
+.cropper-center {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ display: block;
+ width: 0;
+ height: 0;
+ filter: alpha(opacity=75);
+ opacity: .75;
+}
+.cropper-center:before,
+ .cropper-center:after {
+ position: absolute;
+ display: block;
+ content: " ";
+ background-color: #eee;
+}
+.cropper-center:before {
+ top: 0;
+ left: -3px;
+ width: 7px;
+ height: 1px;
+}
+.cropper-center:after {
+ top: -3px;
+ left: 0;
+ width: 1px;
+ height: 7px;
+}
+
.cropper-face,
.cropper-line,
.cropper-point {
@@ -100,42 +128,37 @@
display: block;
width: 100%;
height: 100%;
- filter: alpha(opacity=10);
+ filter: alpha(opacity=10);
opacity: .1;
}
.cropper-face {
top: 0;
left: 0;
- cursor: move;
background-color: #fff;
}
.cropper-line {
- background-color: #69f;
+ background-color: #39f;
}
-
.cropper-line.line-e {
top: 0;
right: -3px;
width: 5px;
cursor: e-resize;
}
-
.cropper-line.line-n {
top: -3px;
left: 0;
height: 5px;
cursor: n-resize;
}
-
.cropper-line.line-w {
top: 0;
left: -3px;
width: 5px;
cursor: w-resize;
}
-
.cropper-line.line-s {
bottom: -3px;
left: 0;
@@ -146,67 +169,58 @@
.cropper-point {
width: 5px;
height: 5px;
- background-color: #69f;
- filter: alpha(opacity=75);
+ background-color: #39f;
+ filter: alpha(opacity=75);
opacity: .75;
}
-
.cropper-point.point-e {
top: 50%;
right: -3px;
margin-top: -3px;
cursor: e-resize;
}
-
.cropper-point.point-n {
top: -3px;
left: 50%;
margin-left: -3px;
cursor: n-resize;
}
-
.cropper-point.point-w {
top: 50%;
left: -3px;
margin-top: -3px;
cursor: w-resize;
}
-
.cropper-point.point-s {
bottom: -3px;
left: 50%;
margin-left: -3px;
cursor: s-resize;
}
-
.cropper-point.point-ne {
top: -3px;
right: -3px;
cursor: ne-resize;
}
-
.cropper-point.point-nw {
top: -3px;
left: -3px;
cursor: nw-resize;
}
-
.cropper-point.point-sw {
bottom: -3px;
left: -3px;
cursor: sw-resize;
}
-
.cropper-point.point-se {
right: -3px;
bottom: -3px;
width: 20px;
height: 20px;
cursor: se-resize;
- filter: alpha(opacity=100);
+ filter: alpha(opacity=100);
opacity: 1;
}
-
.cropper-point.point-se:before {
position: absolute;
right: -50%;
@@ -215,53 +229,51 @@
width: 200%;
height: 200%;
content: " ";
- background-color: #69f;
- filter: alpha(opacity=0);
+ background-color: #39f;
+ filter: alpha(opacity=0);
opacity: 0;
}
-
@media (min-width: 768px) {
.cropper-point.point-se {
width: 15px;
height: 15px;
}
}
-
@media (min-width: 992px) {
.cropper-point.point-se {
width: 10px;
height: 10px;
}
}
-
@media (min-width: 1200px) {
.cropper-point.point-se {
width: 5px;
height: 5px;
- filter: alpha(opacity=75);
+ filter: alpha(opacity=75);
opacity: .75;
}
}
-/* Helper classes for JavaScript */
-
-.cropper-hidden {
- display: none !important;
+.cropper-bg {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC");
}
.cropper-invisible {
- position: fixed;
- top: 0;
- left: 0;
- z-index: -1;
- width: auto !important;
- max-width: none !important;
- height: auto !important;
- max-height: none !important;
- filter: alpha(opacity=0);
+ filter: alpha(opacity=0);
opacity: 0;
}
+.cropper-hide {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+}
+
+.cropper-hidden {
+ display: none !important;
+}
+
.cropper-move {
cursor: move;
}
@@ -270,7 +282,7 @@
cursor: crosshair;
}
-.cropper-disabled .cropper-canvas,
+.cropper-disabled .cropper-drag-box,
.cropper-disabled .cropper-face,
.cropper-disabled .cropper-line,
.cropper-disabled .cropper-point {
diff --git a/javascript/jquery/plugins/cropper/cropper.js b/javascript/jquery/plugins/cropper/cropper.js
index 8c416a3..124fc63 100644
--- a/javascript/jquery/plugins/cropper/cropper.js
+++ b/javascript/jquery/plugins/cropper/cropper.js
@@ -1,995 +1,1130 @@
/*!
- * Cropper v0.7.9
+ * Cropper v1.0.0
* https://github.com/fengyuanchen/cropper
*
- * Copyright 2014-2015 Fengyuan Chen
+ * Copyright (c) 2014-2015 Fengyuan Chen and contributors
* Released under the MIT license
+ *
+ * Date: 2015-10-10T02:10:08.624Z
*/
(function (factory) {
- if (typeof define === "function" && define.amd) {
+ if (typeof define === 'function' && define.amd) {
// AMD. Register as anonymous module.
- define(["jquery"], factory);
- } else if (typeof exports === "object") {
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
// Node / CommonJS
- factory(require("jquery"));
+ factory(require('jquery'));
} else {
// Browser globals.
factory(jQuery);
}
})(function ($) {
- "use strict";
+ 'use strict';
- var $window = $(window),
- $document = $(document),
- location = window.location,
+ // Globals
+ var $window = $(window);
+ var $document = $(document);
+ var location = window.location;
- // Constants
- TRUE = true,
- FALSE = false,
- NULL = null,
- NAN = NaN,
- INFINITY = Infinity,
- STRING_UNDEFINED = "undefined",
- STRING_DIRECTIVE = "directive",
- CROPPER_NAMESPACE = ".cropper",
+ // Constants
+ var NAMESPACE = 'cropper';
- // RegExps
- REGEXP_DIRECTIVES = /^(e|n|w|s|ne|nw|sw|se|all|crop|move|zoom)$/,
- REGEXP_OPTIONS = /^(x|y|width|height)$/,
- REGEXP_PROPERTIES = /^(naturalWidth|naturalHeight|width|height|aspectRatio|ratio|rotate)$/,
+ // Classes
+ var CLASS_MODAL = 'cropper-modal';
+ var CLASS_HIDE = 'cropper-hide';
+ var CLASS_HIDDEN = 'cropper-hidden';
+ var CLASS_INVISIBLE = 'cropper-invisible';
+ var CLASS_MOVE = 'cropper-move';
+ var CLASS_CROP = 'cropper-crop';
+ var CLASS_DISABLED = 'cropper-disabled';
+ var CLASS_BG = 'cropper-bg';
- // Classes
- CLASS_MODAL = "cropper-modal",
- CLASS_HIDDEN = "cropper-hidden",
- CLASS_INVISIBLE = "cropper-invisible",
- CLASS_MOVE = "cropper-move",
- CLASS_CROP = "cropper-crop",
- CLASS_DISABLED = "cropper-disabled",
+ // Events
+ var EVENT_MOUSE_DOWN = 'mousedown touchstart pointerdown MSPointerDown';
+ var EVENT_MOUSE_MOVE = 'mousemove touchmove pointermove MSPointerMove';
+ var EVENT_MOUSE_UP = 'mouseup touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel';
+ var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll';
+ var EVENT_DBLCLICK = 'dblclick';
+ var EVENT_LOAD = 'load.' + NAMESPACE;
+ var EVENT_ERROR = 'error.' + NAMESPACE;
+ var EVENT_RESIZE = 'resize.' + NAMESPACE; // Bind to window with namespace
+ var EVENT_BUILD = 'build.' + NAMESPACE;
+ var EVENT_BUILT = 'built.' + NAMESPACE;
+ var EVENT_CROP_START = 'cropstart.' + NAMESPACE;
+ var EVENT_CROP_MOVE = 'cropmove.' + NAMESPACE;
+ var EVENT_CROP_END = 'cropend.' + NAMESPACE;
+ var EVENT_CROP = 'crop.' + NAMESPACE;
+ var EVENT_ZOOM = 'zoom.' + NAMESPACE;
- // Events
- EVENT_MOUSE_DOWN = "mousedown touchstart",
- EVENT_MOUSE_MOVE = "mousemove touchmove",
- EVENT_MOUSE_UP = "mouseup mouseleave touchend touchleave touchcancel",
- EVENT_WHEEL = "wheel mousewheel DOMMouseScroll",
- EVENT_RESIZE = "resize" + CROPPER_NAMESPACE, // Bind to window with namespace
- EVENT_DBLCLICK = "dblclick",
- EVENT_BUILD = "build" + CROPPER_NAMESPACE,
- EVENT_BUILT = "built" + CROPPER_NAMESPACE,
- EVENT_DRAG_START = "dragstart" + CROPPER_NAMESPACE,
- EVENT_DRAG_MOVE = "dragmove" + CROPPER_NAMESPACE,
- EVENT_DRAG_END = "dragend" + CROPPER_NAMESPACE,
+ // RegExps
+ var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/;
- // Functions
- isNumber = function (n) {
- return typeof n === "number";
- },
+ // Data keys
+ var DATA_PREVIEW = 'preview';
+ var DATA_ACTION = 'action';
- toArray = function (obj, offset) {
- var args = [];
+ // Actions
+ var ACTION_EAST = 'e';
+ var ACTION_WEST = 'w';
+ var ACTION_SOUTH = 's';
+ var ACTION_NORTH = 'n';
+ var ACTION_SOUTH_EAST = 'se';
+ var ACTION_SOUTH_WEST = 'sw';
+ var ACTION_NORTH_EAST = 'ne';
+ var ACTION_NORTH_WEST = 'nw';
+ var ACTION_ALL = 'all';
+ var ACTION_CROP = 'crop';
+ var ACTION_MOVE = 'move';
+ var ACTION_ZOOM = 'zoom';
+ var ACTION_NONE = 'none';
- if (isNumber(offset)) { // It's necessary for IE8
- args.push(offset);
- }
+ // Supports
+ var SUPPORT_CANVAS = $.isFunction($('<canvas>')[0].getContext);
- return args.slice.apply(obj, args);
- },
+ // Maths
+ var sqrt = Math.sqrt;
+ var min = Math.min;
+ var max = Math.max;
+ var abs = Math.abs;
+ var sin = Math.sin;
+ var cos = Math.cos;
+ var num = parseFloat;
- // Custom proxy to avoid jQuery's guid
- proxy = function (fn, context) {
- var args = toArray(arguments, 2);
+ // Prototype
+ var prototype = {
+ version: '1.0.0'
+ };
- return function () {
- return fn.apply(context, args.concat(toArray(arguments)));
- };
- },
+ function isNumber(n) {
+ return typeof n === 'number' && !isNaN(n);
+ }
- addTimestamp = function (url) {
- var timestamp = "timestamp=" + (new Date()).getTime();
+ function isUndefined(n) {
+ return typeof n === 'undefined';
+ }
- return (url + (url.indexOf("?") === -1 ? "?" : "&") + timestamp);
- },
+ function toArray(obj, offset) {
+ var args = [];
- // Constructor
- Cropper = function (element, options) {
- this.element = element;
- this.$element = $(element);
- this.defaults = $.extend({}, Cropper.DEFAULTS, $.isPlainObject(options) ? options : {});
- this.$original = NULL;
- this.ready = FALSE;
- this.built = FALSE;
- this.cropped = FALSE;
- this.rotated = FALSE;
- this.disabled = FALSE;
- this.replaced = FALSE;
- this.init();
- },
+ // This is necessary for IE8
+ if (isNumber(offset)) {
+ args.push(offset);
+ }
- // Others
- sqrt = Math.sqrt,
- min = Math.min,
- max = Math.max,
- abs = Math.abs,
- sin = Math.sin,
- cos = Math.cos,
- num = parseFloat;
+ return args.slice.apply(obj, args);
+ }
- Cropper.prototype = {
- constructor: Cropper,
+ // Custom proxy to avoid jQuery's guid
+ function proxy(fn, context) {
+ var args = toArray(arguments, 2);
- support: {
- canvas: $.isFunction($("<canvas>")[0].getContext)
- },
+ return function () {
+ return fn.apply(context, args.concat(toArray(arguments)));
+ };
+ }
- init: function () {
- var defaults = this.defaults;
+ function isCrossOriginURL(url) {
+ var parts = url.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);
- $.each(defaults, function (i, n) {
- switch (i) {
- case "aspectRatio":
- defaults[i] = abs(num(n)) || NAN; // 0 -> NaN
- break;
+ return parts && (
+ parts[1] !== location.protocol ||
+ parts[2] !== location.hostname ||
+ parts[3] !== location.port
+ );
+ }
- case "autoCropArea":
- defaults[i] = abs(num(n)) || 0.8; // 0 | NaN -> 0.8
- break;
+ function addTimestamp(url) {
+ var timestamp = 'timestamp=' + (new Date()).getTime();
- case "minWidth":
- case "minHeight":
- defaults[i] = abs(num(n)) || 0; // NaN -> 0
- break;
+ return (url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp);
+ }
- case "maxWidth":
- case "maxHeight":
- defaults[i] = abs(num(n)) || INFINITY; // 0 | NaN -> Infinity
- break;
+ function getCrossOrigin(crossOrigin) {
+ return crossOrigin ? ' crossOrigin="' + crossOrigin + '"' : '';
+ }
- // No default
- }
- });
+ function getImageSize(image, callback) {
+ var newImage;
- // Set default image data
- this.image = {
- rotate: 0
- };
+ // Modern browsers
+ if (image.naturalWidth) {
+ return callback(image.naturalWidth, image.naturalHeight);
+ }
- this.load();
- },
+ // IE8: Don't use `new Image()` here (#319)
+ newImage = document.createElement('img');
- load: function () {
- var _this = this,
- $this = this.$element,
- element = this.element,
- image = this.image,
- crossOrigin = "",
- $clone,
- url;
+ newImage.onload = function () {
+ callback(this.width, this.height);
+ };
- if ($this.is("img")) {
- url = $this.prop("src");
- } else if ($this.is("canvas") && this.support.canvas) {
- url = element.toDataURL();
- }
+ newImage.src = image.src;
+ }
- if (!url) {
- return;
- }
+ function getTransform(options) {
+ var transforms = [];
+ var rotate = options.rotate;
+ var scaleX = options.scaleX;
+ var scaleY = options.scaleY;
- // Reset image rotate degree
- if (this.replaced) {
- image.rotate = 0;
- }
+ if (isNumber(rotate)) {
+ transforms.push('rotate(' + rotate + 'deg)');
+ }
- if (this.defaults.checkImageOrigin && this.isCrossOriginURL(url)) {
- crossOrigin = " crossOrigin";
- url = addTimestamp(url); // Bust cache (#119, #148)
- }
+ if (isNumber(scaleX) && isNumber(scaleY)) {
+ transforms.push('scale(' + scaleX + ',' + scaleY + ')');
+ }
- this.$clone = ($clone = $("<img" + crossOrigin + ' src="' + url + '">'));
+ return transforms.length ? transforms.join(' ') : 'none';
+ }
- $clone.one("load", function () {
- image.naturalWidth = this.naturalWidth || $clone.width();
- image.naturalHeight = this.naturalHeight || $clone.height();
- image.aspectRatio = image.naturalWidth / image.naturalHeight;
+ function getRotatedSizes(data, reverse) {
+ var deg = abs(data.degree) % 180;
+ var arc = (deg > 90 ? (180 - deg) : deg) * Math.PI / 180;
+ var sinArc = sin(arc);
+ var cosArc = cos(arc);
+ var width = data.width;
+ var height = data.height;
+ var aspectRatio = data.aspectRatio;
+ var newWidth;
+ var newHeight;
- _this.url = url;
- _this.ready = TRUE;
- _this.build();
- });
+ if (!reverse) {
+ newWidth = width * cosArc + height * sinArc;
+ newHeight = width * sinArc + height * cosArc;
+ } else {
+ newWidth = width / (cosArc + sinArc / aspectRatio);
+ newHeight = newWidth / aspectRatio;
+ }
- // Hide and prepend the clone iamge to the document body (Don't append to).
- $clone.addClass(CLASS_INVISIBLE).prependTo("body");
- },
+ return {
+ width: newWidth,
+ height: newHeight
+ };
+ }
- isCrossOriginURL: function (url) {
- var parts = url.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);
+ function getSourceCanvas(image, data) {
+ var canvas = $('<canvas>')[0];
+ var context = canvas.getContext('2d');
+ var x = 0;
+ var y = 0;
+ var width = data.naturalWidth;
+ var height = data.naturalHeight;
+ var rotate = data.rotate;
+ var scaleX = data.scaleX;
+ var scaleY = data.scaleY;
+ var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1);
+ var rotatable = isNumber(rotate) && rotate !== 0;
+ var advanced = rotatable || scalable;
+ var canvasWidth = width;
+ var canvasHeight = height;
+ var translateX;
+ var translateY;
+ var rotated;
- if (parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port)) {
- return TRUE;
- }
+ if (scalable) {
+ translateX = width / 2;
+ translateY = height / 2;
+ }
- return FALSE;
- },
+ if (rotatable) {
+ rotated = getRotatedSizes({
+ width: width,
+ height: height,
+ degree: rotate
+ });
- build: function () {
- var $this = this.$element,
- defaults = this.defaults,
- buildEvent,
- $cropper;
+ canvasWidth = rotated.width;
+ canvasHeight = rotated.height;
+ translateX = rotated.width / 2;
+ translateY = rotated.height / 2;
+ }
- if (!this.ready) {
- return;
- }
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
- if (this.built) {
- this.unbuild();
- }
+ if (advanced) {
+ x = -width / 2;
+ y = -height / 2;
- $this.one(EVENT_BUILD, defaults.build); // Only trigger once
- buildEvent = $.Event(EVENT_BUILD);
- $this.trigger(buildEvent);
+ context.save();
+ context.translate(translateX, translateY);
+ }
- if (buildEvent.isDefaultPrevented()) {
- return;
- }
+ if (rotatable) {
+ context.rotate(rotate * Math.PI / 180);
+ }
- // Create cropper elements
- this.$cropper = ($cropper = $(Cropper.TEMPLATE));
+ // Should call `scale` after rotated
+ if (scalable) {
+ context.scale(scaleX, scaleY);
+ }
- // Hide the original image
- $this.addClass(CLASS_HIDDEN);
+ context.drawImage(image, x, y, width, height);
+
+ if (advanced) {
+ context.restore();
+ }
+
+ return canvas;
+ }
- // Show and prepend the clone iamge to the cropper
- this.$clone.removeClass(CLASS_INVISIBLE).prependTo($cropper);
+ function Cropper(element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, Cropper.DEFAULTS, $.isPlainObject(options) && options);
+ this.ready = false;
+ this.built = false;
+ this.complete = false;
+ this.rotated = false;
+ this.cropped = false;
+ this.disabled = false;
+ this.replaced = false;
+ this.isImg = false;
+ this.originalUrl = '';
+ this.crossOrigin = '';
+ this.canvas = null;
+ this.cropBox = null;
+ this.init();
+ }
- // Save original image for rotation
- if (!this.rotated) {
- this.$original = this.$clone.clone();
+ $.extend(prototype, {
+ init: function () {
+ var $this = this.$element;
+ var url;
- // Append the image to document to avoid "NS_ERROR_NOT_AVAILABLE" error on Firefox when call the "drawImage" method.
- this.$original.addClass(CLASS_HIDDEN).prependTo(this.$cropper);
+ if ($this.is('img')) {
+ this.isImg = true;
- this.originalImage = $.extend({}, this.image);
- }
+ // Should use `$.fn.attr` here. e.g.: "img/picture.jpg"
+ this.originalUrl = url = $this.attr('src');
- this.$container = $this.parent();
- this.$container.append($cropper);
+ // Stop when it's a blank image
+ if (!url) {
+ return;
+ }
- this.$canvas = $cropper.find(".cropper-canvas");
- this.$dragger = $cropper.find(".cropper-dragger");
- this.$viewer = $cropper.find(".cropper-viewer");
+ // Should use `$.fn.prop` here. e.g.: "http://example.com/img/picture.jpg"
+ url = $this.prop('src');
+ } else if ($this.is('canvas') && SUPPORT_CANVAS) {
+ url = $this[0].toDataURL();
+ }
- defaults.autoCrop ? (this.cropped = TRUE) : this.$dragger.addClass(CLASS_HIDDEN);
- defaults.modal && this.$canvas.addClass(CLASS_MODAL);
- !defaults.dashed && this.$dragger.find(".cropper-dashed").addClass(CLASS_HIDDEN);
- !defaults.movable && this.$dragger.find(".cropper-face").data(STRING_DIRECTIVE, "move");
- !defaults.resizable && this.$dragger.find(".cropper-line, .cropper-point").addClass(CLASS_HIDDEN);
+ this.load(url);
+ },
- this.addListeners();
- this.initPreview();
+ // A shortcut for triggering custom events
+ trigger: function (type, data) {
+ var e = $.Event(type, data);
- this.built = TRUE; // Set `true` before update
- defaults.dragCrop && this.setDragMode("crop"); // Set after built
- this.update();
- this.replaced = FALSE; // Reset to `false` after update
+ this.$element.trigger(e);
- $this.one(EVENT_BUILT, defaults.built); // Only trigger once
- $this.trigger(EVENT_BUILT);
+ return e;
},
- unbuild: function () {
- if (!this.built) {
+ load: function (url) {
+ var options = this.options;
+ var $this = this.$element;
+ var crossOrigin = '';
+ var bustCacheUrl;
+ var $clone;
+
+ if (!url) {
return;
}
- this.built = FALSE;
- this.removeListeners();
+ this.url = url;
- this.$preview.empty();
- this.$preview = NULL;
+ // Trigger build event first
+ $this.one(EVENT_BUILD, options.build);
- this.$dragger = NULL;
- this.$canvas = NULL;
- this.$container = NULL;
+ if (this.trigger(EVENT_BUILD).isDefaultPrevented()) {
+ return;
+ }
- this.$cropper.remove();
- this.$cropper = NULL;
- },
+ if (options.checkImageOrigin && isCrossOriginURL(url)) {
+ crossOrigin = $this.prop('crossOrigin');
- update: function (data) {
- this.initContainer();
- this.initCropper();
- this.initImage();
- this.initDragger();
+ // Bust cache (#148), only when there was not a "crossOrigin" property
+ if (!crossOrigin) {
+ crossOrigin = 'anonymous';
+ bustCacheUrl = addTimestamp(url);
+ }
+
+ this.crossOrigin = crossOrigin;
+ }
- if (data) {
- this.setData(data, TRUE);
- this.setDragMode("crop");
+ this.$clone = $clone = $('<img' + getCrossOrigin(crossOrigin) + ' src="' + (bustCacheUrl || url) + '">');
+
+ if (this.isImg) {
+ if ($this[0].complete) {
+ this.start();
+ } else {
+ $this.one(EVENT_LOAD, $.proxy(this.start, this));
+ }
} else {
- this.setData(this.defaults.data);
+ $clone.
+ one(EVENT_LOAD, $.proxy(this.start, this)).
+ one(EVENT_ERROR, $.proxy(this.stop, this)).
+ addClass(CLASS_HIDE).
+ insertAfter($this);
}
},
- resize: function () {
- clearTimeout(this.resizing);
- this.resizing = setTimeout($.proxy(this.update, this, this.getData()), 200);
- },
+ start: function () {
+ var $image = this.$element;
+ var $clone = this.$clone;
- preview: function () {
- var image = this.image,
- dragger = this.dragger,
- width = image.width,
- height = image.height,
- left = dragger.left - image.left,
- top = dragger.top - image.top;
+ if (!this.isImg) {
+ $clone.off(EVENT_ERROR, this.stop);
+ $image = $clone;
+ }
- this.$viewer.find("img").css({
- width: width,
- height: height,
- marginLeft: -left,
- marginTop: -top
- });
+ getImageSize($image[0], $.proxy(function (naturalWidth, naturalHeight) {
+ this.image = {
+ naturalWidth: naturalWidth,
+ naturalHeight: naturalHeight,
+ aspectRatio: naturalWidth / naturalHeight
+ };
- this.$preview.each(function () {
- var $this = $(this),
- data = $this.data(),
- ratio = data.width / dragger.width,
- newWidth = data.width,
- newHeight = dragger.height * ratio;
+ this.ready = true;
+ this.build();
+ }, this));
+ },
- if (newHeight > data.height) {
- ratio = data.height / dragger.height,
- newWidth = dragger.width * ratio;
- newHeight = data.height;
- }
+ stop: function () {
+ this.$clone.remove();
+ this.$clone = null;
+ }
+ });
- $this.width(newWidth).height(newHeight).find("img").css({
- width: width * ratio,
- height: height * ratio,
- marginLeft: -left * ratio,
- marginTop: -top * ratio
- });
- });
- },
+ $.extend(prototype, {
+ build: function () {
+ var options = this.options;
+ var $this = this.$element;
+ var $clone = this.$clone;
+ var $cropper;
+ var $cropBox;
+ var $face;
- addListeners: function () {
- var defaults = this.defaults;
+ if (!this.ready) {
+ return;
+ }
- this.$element.on(EVENT_DRAG_START, defaults.dragstart).on(EVENT_DRAG_MOVE, defaults.dragmove).on(EVENT_DRAG_END, defaults.dragend);
- this.$cropper.on(EVENT_MOUSE_DOWN, $.proxy(this.dragstart, this)).on(EVENT_DBLCLICK, $.proxy(this.dblclick, this));
+ // Unbuild first when replace
+ if (this.built) {
+ this.unbuild();
+ }
+
+ // Create cropper elements
+ this.$container = $this.parent();
+ this.$cropper = $cropper = $(Cropper.TEMPLATE);
+ this.$canvas = $cropper.find('.cropper-canvas').append($clone);
+ this.$dragBox = $cropper.find('.cropper-drag-box');
+ this.$cropBox = $cropBox = $cropper.find('.cropper-crop-box');
+ this.$viewBox = $cropper.find('.cropper-view-box');
+ this.$face = $face = $cropBox.find('.cropper-face');
+
+ // Hide the original image
+ $this.addClass(CLASS_HIDDEN).after($cropper);
- if (defaults.zoomable) {
- this.$cropper.on(EVENT_WHEEL, $.proxy(this.wheel, this));
+ // Show the clone image if is hidden
+ if (!this.isImg) {
+ $clone.removeClass(CLASS_HIDE);
}
- if (defaults.multiple) {
- this.$cropper.on(EVENT_MOUSE_MOVE, $.proxy(this.dragmove, this)).on(EVENT_MOUSE_UP, $.proxy(this.dragend, this));
+ this.initPreview();
+ this.bind();
+
+ // Format aspect ratio (0 -> NaN)
+ options.aspectRatio = num(options.aspectRatio) || NaN;
+
+ if (options.autoCrop) {
+ this.cropped = true;
+
+ if (options.modal) {
+ this.$dragBox.addClass(CLASS_MODAL);
+ }
} else {
- $document.on(EVENT_MOUSE_MOVE, (this._dragmove = proxy(this.dragmove, this))).on(EVENT_MOUSE_UP, (this._dragend = proxy(this.dragend, this)));
+ $cropBox.addClass(CLASS_HIDDEN);
}
- $window.on(EVENT_RESIZE, (this._resize = proxy(this.resize, this)));
- },
+ if (!options.guides) {
+ $cropBox.find('.cropper-dashed').addClass(CLASS_HIDDEN);
+ }
- removeListeners: function () {
- var defaults = this.defaults;
+ if (!options.center) {
+ $cropBox.find('.cropper-center').addClass(CLASS_HIDDEN);
+ }
- this.$element.off(EVENT_DRAG_START, defaults.dragstart).off(EVENT_DRAG_MOVE, defaults.dragmove).off(EVENT_DRAG_END, defaults.dragend);
- this.$cropper.off(EVENT_MOUSE_DOWN, this.dragstart).off(EVENT_DBLCLICK, this.dblclick);
+ if (options.cropBoxMovable) {
+ $face.addClass(CLASS_MOVE).data(DATA_ACTION, ACTION_ALL);
+ }
- if (defaults.zoomable) {
- this.$cropper.off(EVENT_WHEEL, this.wheel);
+ if (!options.highlight) {
+ $face.addClass(CLASS_INVISIBLE);
}
- if (defaults.multiple) {
- this.$cropper.off(EVENT_MOUSE_MOVE, this.dragmove).off(EVENT_MOUSE_UP, this.dragend);
- } else {
- $document.off(EVENT_MOUSE_MOVE, this._dragmove).off(EVENT_MOUSE_UP, this._dragend);
+ if (options.background) {
+ $cropper.addClass(CLASS_BG);
}
- $window.off(EVENT_RESIZE, this._resize);
+ if (!options.cropBoxResizable) {
+ $cropBox.find('.cropper-line, .cropper-point').addClass(CLASS_HIDDEN);
+ }
+
+ this.setDragMode(options.dragCrop ? ACTION_CROP : (options.movable ? ACTION_MOVE : ACTION_NONE));
+
+ this.render();
+ this.built = true;
+ this.setData(options.data);
+ $this.one(EVENT_BUILT, options.built);
+
+ // Trigger the built event asynchronously to keep `data('cropper')` is defined
+ setTimeout($.proxy(function () {
+ this.trigger(EVENT_BUILT);
+ this.complete = true;
+ }, this), 0);
},
- initPreview: function () {
- var url = this.url;
+ unbuild: function () {
+ if (!this.built) {
+ return;
+ }
- this.$preview = $(this.defaults.preview);
- this.$viewer.html('<img src="' + url + '">');
+ this.built = false;
+ this.initialImage = null;
- this.$preview.each(function () {
- var $this = $(this);
+ // Clear `initialCanvas` is necessary when replace
+ this.initialCanvas = null;
+ this.initialCropBox = null;
+ this.container = null;
+ this.canvas = null;
- $this.data({
- width: $this.width(),
- height: $this.height()
- }).html('<img src="' + url + '" style="display:block;width:100%;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;">');
- });
+ // Clear `cropBox` is necessary when replace
+ this.cropBox = null;
+ this.unbind();
+
+ this.resetPreview();
+ this.$preview = null;
+
+ this.$viewBox = null;
+ this.$cropBox = null;
+ this.$dragBox = null;
+ this.$canvas = null;
+ this.$container = null;
+
+ this.$cropper.remove();
+ this.$cropper = null;
+ }
+ });
+
+ $.extend(prototype, {
+ render: function () {
+ this.initContainer();
+ this.initCanvas();
+ this.initCropBox();
+
+ this.renderCanvas();
+
+ if (this.cropped) {
+ this.renderCropBox();
+ }
},
initContainer: function () {
- var $this = this.$element,
- $container = this.$container,
- $cropper = this.$cropper,
- defaults = this.defaults;
+ var options = this.options;
+ var $this = this.$element;
+ var $container = this.$container;
+ var $cropper = this.$cropper;
$cropper.addClass(CLASS_HIDDEN);
$this.removeClass(CLASS_HIDDEN);
- this.container = {
- width: max($container.width(), defaults.minContainerWidth),
- height: max($container.height(), defaults.minContainerHeight)
- };
+ $cropper.css((this.container = {
+ width: max($container.width(), num(options.minContainerWidth) || 200),
+ height: max($container.height(), num(options.minContainerHeight) || 100)
+ }));
$this.addClass(CLASS_HIDDEN);
$cropper.removeClass(CLASS_HIDDEN);
},
- initCropper: function () {
- var container = this.container,
- image = this.image,
- cropper;
-
- if (((image.naturalWidth * container.height / image.naturalHeight) - container.width) >= 0) {
- cropper = {
- width: container.width,
- height: container.width / image.aspectRatio,
- left: 0
- };
+ // Canvas (image wrapper)
+ initCanvas: function () {
+ var container = this.container;
+ var containerWidth = container.width;
+ var containerHeight = container.height;
+ var image = this.image;
+ var aspectRatio = image.aspectRatio;
+ var canvas = {
+ aspectRatio: aspectRatio,
+ width: containerWidth,
+ height: containerHeight
+ };
- cropper.top = (container.height - cropper.height) / 2;
+ if (containerHeight * aspectRatio > containerWidth) {
+ canvas.height = containerWidth / aspectRatio;
} else {
- cropper = {
- width: container.height * image.aspectRatio,
- height: container.height,
- top: 0
- };
-
- cropper.left = (container.width - cropper.width) / 2;
+ canvas.width = containerHeight * aspectRatio;
}
- this.$cropper.css({
- width: cropper.width,
- height: cropper.height,
- left: cropper.left,
- top: cropper.top
- });
+ canvas.oldLeft = canvas.left = (containerWidth - canvas.width) / 2;
+ canvas.oldTop = canvas.top = (containerHeight - canvas.height) / 2;
- this.cropper = cropper;
+ this.canvas = canvas;
+ this.limitCanvas(true, true);
+ this.initialImage = $.extend({}, image);
+ this.initialCanvas = $.extend({}, canvas);
},
- initImage: function () {
- var image = this.image,
- cropper = this.cropper,
- defaultImage = {
- _width: cropper.width,
- _height: cropper.height,
- width: cropper.width,
- height: cropper.height,
- left: 0,
- top: 0,
- ratio: cropper.width / image.naturalWidth
- };
+ limitCanvas: function (size, position) {
+ var options = this.options;
+ var strict = options.strict;
+ var container = this.container;
+ var containerWidth = container.width;
+ var containerHeight = container.height;
+ var canvas = this.canvas;
+ var aspectRatio = canvas.aspectRatio;
+ var cropBox = this.cropBox;
+ var cropped = this.cropped && cropBox;
+ var initialCanvas = this.initialCanvas || canvas;
+ var minCanvasWidth;
+ var minCanvasHeight;
- this.defaultImage = $.extend({}, image, defaultImage);
+ if (size) {
+ minCanvasWidth = num(options.minCanvasWidth) || 0;
+ minCanvasHeight = num(options.minCanvasHeight) || 0;
- if (image._width !== cropper.width || image._height !== cropper.height) {
- $.extend(image, defaultImage);
- } else {
- image = $.extend({}, defaultImage, image);
+ if (strict) {
+ if (minCanvasWidth) {
+ minCanvasWidth = max(minCanvasWidth, cropped ? cropBox.width : initialCanvas.width);
+ } else if (minCanvasHeight) {
+ minCanvasHeight = max(minCanvasHeight, cropped ? cropBox.height : initialCanvas.height);
+ } else if (cropped) {
+ minCanvasWidth = cropBox.width;
+ minCanvasHeight = cropBox.height;
- // Reset image ratio
- if (this.replaced) {
- image.ratio = defaultImage.ratio;
+ if (minCanvasHeight * aspectRatio > minCanvasWidth) {
+ minCanvasWidth = minCanvasHeight * aspectRatio;
+ } else {
+ minCanvasHeight = minCanvasWidth / aspectRatio;
+ }
+ }
}
- }
-
- this.image = image;
- this.renderImage();
- },
- renderImage: function (mode) {
- var image = this.image;
+ if (minCanvasWidth && minCanvasHeight) {
+ if (minCanvasHeight * aspectRatio > minCanvasWidth) {
+ minCanvasHeight = minCanvasWidth / aspectRatio;
+ } else {
+ minCanvasWidth = minCanvasHeight * aspectRatio;
+ }
+ } else if (minCanvasWidth) {
+ minCanvasHeight = minCanvasWidth / aspectRatio;
+ } else if (minCanvasHeight) {
+ minCanvasWidth = minCanvasHeight * aspectRatio;
+ }
- if (mode === "zoom") {
- image.left -= (image.width - image.oldWidth) / 2;
- image.top -= (image.height - image.oldHeight) / 2;
+ canvas.minWidth = minCanvasWidth;
+ canvas.minHeight = minCanvasHeight;
+ canvas.maxWidth = Infinity;
+ canvas.maxHeight = Infinity;
}
- image.left = min(max(image.left, image._width - image.width), 0);
- image.top = min(max(image.top, image._height - image.height), 0);
-
- this.$clone.css({
- width: image.width,
- height: image.height,
- marginLeft: image.left,
- marginTop: image.top
- });
-
- if (mode) {
- this.defaults.done(this.getData());
- this.preview();
+ if (position) {
+ if (strict) {
+ canvas.minLeft = cropped ?
+ min(cropBox.left, (cropBox.left + cropBox.width) - canvas.width) :
+ min(0, containerWidth - canvas.width);
+ canvas.minTop = cropped ?
+ min(cropBox.top, (cropBox.top + cropBox.height) - canvas.height) :
+ min(0, containerHeight - canvas.height);
+ canvas.maxLeft = cropped ? cropBox.left : max(0, containerWidth - canvas.width);
+ canvas.maxTop = cropped ? cropBox.top : max(0, containerHeight - canvas.height);
+ } else {
+ canvas.minLeft = -canvas.width;
+ canvas.minTop = -canvas.height;
+ canvas.maxLeft = containerWidth;
+ canvas.maxTop = containerHeight;
+ }
}
},
- initDragger: function () {
- var defaults = this.defaults,
- cropper = this.cropper,
- // If not set, use the original aspect ratio of the image.
- aspectRatio = defaults.aspectRatio || this.image.aspectRatio,
- ratio = this.image.ratio,
- autoCropDragger,
- dragger;
+ renderCanvas: function (changed) {
+ var options = this.options;
+ var canvas = this.canvas;
+ var image = this.image;
+ var aspectRatio;
+ var rotated;
- if (((cropper.height * aspectRatio) - cropper.width) >= 0) {
- dragger = {
- height: cropper.width / aspectRatio,
- width: cropper.width,
- left: 0,
- top: (cropper.height - (cropper.width / aspectRatio)) / 2,
- maxWidth: cropper.width,
- maxHeight: cropper.width / aspectRatio
- };
- } else {
- dragger = {
- height: cropper.height,
- width: cropper.height * aspectRatio,
- left: (cropper.width - (cropper.height * aspectRatio)) / 2,
- top: 0,
- maxWidth: cropper.height * aspectRatio,
- maxHeight: cropper.height
- };
- }
+ if (this.rotated) {
+ this.rotated = false;
- dragger.minWidth = 0;
- dragger.minHeight = 0;
+ // Computes rotated sizes with image sizes
+ rotated = getRotatedSizes({
+ width: image.width,
+ height: image.height,
+ degree: image.rotate
+ });
- if (defaults.aspectRatio) {
- if (isFinite(defaults.maxWidth)) {
- dragger.maxWidth = min(dragger.maxWidth, defaults.maxWidth * ratio);
- dragger.maxHeight = dragger.maxWidth / aspectRatio;
- } else if (isFinite(defaults.maxHeight)) {
- dragger.maxHeight = min(dragger.maxHeight, defaults.maxHeight * ratio);
- dragger.maxWidth = dragger.maxHeight * aspectRatio;
- }
+ aspectRatio = rotated.width / rotated.height;
- if (defaults.minWidth > 0) {
- dragger.minWidth = max(0, defaults.minWidth * ratio);
- dragger.minHeight = dragger.minWidth / aspectRatio;
- } else if (defaults.minHeight > 0) {
- dragger.minHeight = max(0, defaults.minHeight * ratio);
- dragger.minWidth = dragger.minHeight * aspectRatio;
+ if (aspectRatio !== canvas.aspectRatio) {
+ canvas.left -= (rotated.width - canvas.width) / 2;
+ canvas.top -= (rotated.height - canvas.height) / 2;
+ canvas.width = rotated.width;
+ canvas.height = rotated.height;
+ canvas.aspectRatio = aspectRatio;
+ this.limitCanvas(true, false);
}
- } else {
- dragger.maxWidth = min(dragger.maxWidth, defaults.maxWidth * ratio);
- dragger.maxHeight = min(dragger.maxHeight, defaults.maxHeight * ratio);
- dragger.minWidth = max(0, defaults.minWidth * ratio);
- dragger.minHeight = max(0, defaults.minHeight * ratio);
}
- // minWidth can't be greater than maxWidth, and minHeight too.
- dragger.minWidth = min(dragger.maxWidth, dragger.minWidth);
- dragger.minHeight = min(dragger.maxHeight, dragger.minHeight);
+ if (canvas.width > canvas.maxWidth || canvas.width < canvas.minWidth) {
+ canvas.left = canvas.oldLeft;
+ }
- // Center the dragger by default
- autoCropDragger = $.extend({}, dragger);
+ if (canvas.height > canvas.maxHeight || canvas.height < canvas.minHeight) {
+ canvas.top = canvas.oldTop;
+ }
- // The width of auto crop area must large than minWidth, and the height too. (#164)
- autoCropDragger.width = max(dragger.minWidth, dragger.width * defaults.autoCropArea);
- autoCropDragger.height = max(dragger.minHeight, dragger.height * defaults.autoCropArea);
- autoCropDragger.left = (cropper.width - autoCropDragger.width) / 2;
- autoCropDragger.top = (cropper.height - autoCropDragger.height) / 2;
+ canvas.width = min(max(canvas.width, canvas.minWidth), canvas.maxWidth);
+ canvas.height = min(max(canvas.height, canvas.minHeight), canvas.maxHeight);
- autoCropDragger.oldLeft = dragger.oldLeft = dragger.left;
- autoCropDragger.oldTop = dragger.oldTop = dragger.top;
+ this.limitCanvas(false, true);
- this.autoCropDragger = autoCropDragger;
- this.defaultDragger = $.extend({}, dragger);
- this.dragger = dragger;
- },
+ canvas.oldLeft = canvas.left = min(max(canvas.left, canvas.minLeft), canvas.maxLeft);
+ canvas.oldTop = canvas.top = min(max(canvas.top, canvas.minTop), canvas.maxTop);
- renderDragger: function () {
- var dragger = this.dragger,
- cropper = this.cropper;
+ this.$canvas.css({
+ width: canvas.width,
+ height: canvas.height,
+ left: canvas.left,
+ top: canvas.top
+ });
- if (dragger.width > dragger.maxWidth) {
- dragger.width = dragger.maxWidth;
- dragger.left = dragger.oldLeft;
- } else if (dragger.width < dragger.minWidth) {
- dragger.width = dragger.minWidth;
- dragger.left = dragger.oldLeft;
- }
+ this.renderImage();
- if (dragger.height > dragger.maxHeight) {
- dragger.height = dragger.maxHeight;
- dragger.top = dragger.oldTop;
- } else if (dragger.height < dragger.minHeight) {
- dragger.height = dragger.minHeight;
- dragger.top = dragger.oldTop;
+ if (this.cropped && options.strict) {
+ this.limitCropBox(true, true);
}
- dragger.left = min(max(dragger.left, 0), cropper.width - dragger.width);
- dragger.top = min(max(dragger.top, 0), cropper.height - dragger.height);
- dragger.oldLeft = dragger.left;
- dragger.oldTop = dragger.top;
+ if (changed) {
+ this.output();
+ }
+ },
- // Re-render the dragger
- this.dragger = dragger;
+ renderImage: function (changed) {
+ var canvas = this.canvas;
+ var image = this.image;
+ var reversed;
- // #186
- if (this.defaults.movable) {
- this.$dragger.find(".cropper-face").data(STRING_DIRECTIVE, (dragger.width === cropper.width && dragger.height === cropper.height) ? "move" : "all");
+ if (image.rotate) {
+ reversed = getRotatedSizes({
+ width: canvas.width,
+ height: canvas.height,
+ degree: image.rotate,
+ aspectRatio: image.aspectRatio
+ }, true);
}
- if (!this.disabled) {
- this.defaults.done(this.getData());
- }
+ $.extend(image, reversed ? {
+ width: reversed.width,
+ height: reversed.height,
+ left: (canvas.width - reversed.width) / 2,
+ top: (canvas.height - reversed.height) / 2
+ } : {
+ width: canvas.width,
+ height: canvas.height,
+ left: 0,
+ top: 0
+ });
- this.$dragger.css({
- width: dragger.width,
- height: dragger.height,
- left: dragger.left,
- top: dragger.top
+ this.$clone.css({
+ width: image.width,
+ height: image.height,
+ marginLeft: image.left,
+ marginTop: image.top,
+ transform: getTransform(image)
});
- this.preview();
+ if (changed) {
+ this.output();
+ }
},
- reset: function (deep) {
- if (!this.cropped || this.disabled) {
- return;
- }
+ initCropBox: function () {
+ var options = this.options;
+ var canvas = this.canvas;
+ var aspectRatio = options.aspectRatio;
+ var autoCropArea = num(options.autoCropArea) || 0.8;
+ var cropBox = {
+ width: canvas.width,
+ height: canvas.height
+ };
- if (deep) {
- this.defaults.data = {};
+ if (aspectRatio) {
+ if (canvas.height * aspectRatio > canvas.width) {
+ cropBox.height = cropBox.width / aspectRatio;
+ } else {
+ cropBox.width = cropBox.height * aspectRatio;
+ }
}
- this.image = $.extend({}, this.defaultImage);
- this.renderImage();
- this.dragger = $.extend({}, this.defaultDragger);
- this.setData(this.defaults.data);
- },
-
- clear: function () {
- if (!this.cropped || this.disabled) {
- return;
- }
+ this.cropBox = cropBox;
+ this.limitCropBox(true, true);
- this.cropped = FALSE;
+ // Initialize auto crop area
+ cropBox.width = min(max(cropBox.width, cropBox.minWidth), cropBox.maxWidth);
+ cropBox.height = min(max(cropBox.height, cropBox.minHeight), cropBox.maxHeight);
- this.setData({
- x: 0,
- y: 0,
- width: 0,
- height: 0
- });
+ // The width of auto crop area must large than "minWidth", and the height too. (#164)
+ cropBox.width = max(cropBox.minWidth, cropBox.width * autoCropArea);
+ cropBox.height = max(cropBox.minHeight, cropBox.height * autoCropArea);
+ cropBox.oldLeft = cropBox.left = canvas.left + (canvas.width - cropBox.width) / 2;
+ cropBox.oldTop = cropBox.top = canvas.top + (canvas.height - cropBox.height) / 2;
- this.$canvas.removeClass(CLASS_MODAL);
- this.$dragger.addClass(CLASS_HIDDEN);
+ this.initialCropBox = $.extend({}, cropBox);
},
- destroy: function () {
- var $this = this.$element;
+ limitCropBox: function (size, position) {
+ var options = this.options;
+ var strict = options.strict;
+ var container = this.container;
+ var containerWidth = container.width;
+ var containerHeight = container.height;
+ var canvas = this.canvas;
+ var cropBox = this.cropBox;
+ var aspectRatio = options.aspectRatio;
+ var minCropBoxWidth;
+ var minCropBoxHeight;
+ var maxCropBoxWidth;
+ var maxCropBoxHeight;
- if (!this.ready) {
- this.$clone.off("load").remove();
- }
+ if (size) {
+ minCropBoxWidth = num(options.minCropBoxWidth) || 0;
+ minCropBoxHeight = num(options.minCropBoxHeight) || 0;
- this.unbuild();
- $this.removeClass(CLASS_HIDDEN).removeData("cropper");
+ // The min/maxCropBoxWidth/Height must be less than containerWidth/Height
+ minCropBoxWidth = min(minCropBoxWidth, containerWidth);
+ minCropBoxHeight = min(minCropBoxHeight, containerHeight);
+ maxCropBoxWidth = min(containerWidth, strict ? canvas.width : containerWidth);
+ maxCropBoxHeight = min(containerHeight, strict ? canvas.height : containerHeight);
- if (this.rotated) {
- $this.attr("src", this.$original.attr("src"));
- }
- },
-
- replace: function (url, /*INTERNAL*/ rotated) {
- var _this = this,
- $this = this.$element,
- element = this.element,
- context;
+ if (aspectRatio) {
+ if (minCropBoxWidth && minCropBoxHeight) {
+ if (minCropBoxHeight * aspectRatio > minCropBoxWidth) {
+ minCropBoxHeight = minCropBoxWidth / aspectRatio;
+ } else {
+ minCropBoxWidth = minCropBoxHeight * aspectRatio;
+ }
+ } else if (minCropBoxWidth) {
+ minCropBoxHeight = minCropBoxWidth / aspectRatio;
+ } else if (minCropBoxHeight) {
+ minCropBoxWidth = minCropBoxHeight * aspectRatio;
+ }
- if (!this.disabled && url && url !== this.url && url !== $this.attr("src")) {
- if (!rotated) {
- this.rotated = FALSE;
- this.replaced = TRUE;
+ if (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) {
+ maxCropBoxHeight = maxCropBoxWidth / aspectRatio;
+ } else {
+ maxCropBoxWidth = maxCropBoxHeight * aspectRatio;
+ }
}
- if ($this.is("img")) {
- $this.attr("src", url);
- this.load();
- } else if ($this.is("canvas") && this.support.canvas) {
- context = element.getContext("2d");
+ // The minWidth/Height must be less than maxWidth/Height
+ cropBox.minWidth = min(minCropBoxWidth, maxCropBoxWidth);
+ cropBox.minHeight = min(minCropBoxHeight, maxCropBoxHeight);
+ cropBox.maxWidth = maxCropBoxWidth;
+ cropBox.maxHeight = maxCropBoxHeight;
+ }
- $('<img src="' + url + '">').one("load", function () {
- element.width = this.width;
- element.height = this.height;
- context.clearRect(0, 0, element.width, element.height);
- context.drawImage(this, 0, 0);
- _this.load();
- });
+ if (position) {
+ if (strict) {
+ cropBox.minLeft = max(0, canvas.left);
+ cropBox.minTop = max(0, canvas.top);
+ cropBox.maxLeft = min(containerWidth, canvas.left + canvas.width) - cropBox.width;
+ cropBox.maxTop = min(containerHeight, canvas.top + canvas.height) - cropBox.height;
+ } else {
+ cropBox.minLeft = 0;
+ cropBox.minTop = 0;
+ cropBox.maxLeft = containerWidth - cropBox.width;
+ cropBox.maxTop = containerHeight - cropBox.height;
}
}
},
- setData: function (data, /*INTERNAL*/ once) {
- var cropper = this.cropper,
- dragger = this.dragger,
- image = this.image,
- aspectRatio = this.defaults.aspectRatio;
+ renderCropBox: function () {
+ var options = this.options;
+ var container = this.container;
+ var containerWidth = container.width;
+ var containerHeight = container.height;
+ var cropBox = this.cropBox;
- if (!this.built || this.disabled || typeof data === STRING_UNDEFINED) {
- return;
+ if (cropBox.width > cropBox.maxWidth || cropBox.width < cropBox.minWidth) {
+ cropBox.left = cropBox.oldLeft;
}
- if (data === NULL || $.isEmptyObject(data)) {
- dragger = $.extend({}, this.autoCropDragger);
+ if (cropBox.height > cropBox.maxHeight || cropBox.height < cropBox.minHeight) {
+ cropBox.top = cropBox.oldTop;
}
- if ($.isPlainObject(data) && !$.isEmptyObject(data)) {
+ cropBox.width = min(max(cropBox.width, cropBox.minWidth), cropBox.maxWidth);
+ cropBox.height = min(max(cropBox.height, cropBox.minHeight), cropBox.maxHeight);
- if (!once) {
- this.defaults.data = data;
- }
+ this.limitCropBox(false, true);
- data = this.transformData(data);
+ cropBox.oldLeft = cropBox.left = min(max(cropBox.left, cropBox.minLeft), cropBox.maxLeft);
+ cropBox.oldTop = cropBox.top = min(max(cropBox.top, cropBox.minTop), cropBox.maxTop);
- if (isNumber(data.x) && data.x <= cropper.width - image.left) {
- dragger.left = data.x + image.left;
- }
+ if (options.movable && options.cropBoxMovable) {
- if (isNumber(data.y) && data.y <= cropper.height - image.top) {
- dragger.top = data.y + image.top;
- }
+ // Turn to move the canvas when the crop box is equal to the container
+ this.$face.data(DATA_ACTION, (cropBox.width === containerWidth && cropBox.height === containerHeight) ? ACTION_MOVE : ACTION_ALL);
+ }
- if (aspectRatio) {
- if (isNumber(data.width) && data.width <= dragger.maxWidth && data.width >= dragger.minWidth) {
- dragger.width = data.width;
- dragger.height = dragger.width / aspectRatio;
- } else if (isNumber(data.height) && data.height <= dragger.maxHeight && data.height >= dragger.minHeight) {
- dragger.height = data.height;
- dragger.width = dragger.height * aspectRatio;
- }
- } else {
- if (isNumber(data.width) && data.width <= dragger.maxWidth && data.width >= dragger.minWidth) {
- dragger.width = data.width;
- }
+ this.$cropBox.css({
+ width: cropBox.width,
+ height: cropBox.height,
+ left: cropBox.left,
+ top: cropBox.top
+ });
- if (isNumber(data.height) && data.height <= dragger.maxHeight && data.height >= dragger.minHeight) {
- dragger.height = data.height;
- }
- }
+ if (this.cropped && options.strict) {
+ this.limitCanvas(true, true);
}
- this.dragger = dragger;
- this.renderDragger();
+ if (!this.disabled) {
+ this.output();
+ }
},
- getData: function (rounded) {
- var dragger = this.dragger,
- image = this.image,
- data = {};
+ output: function () {
+ this.preview();
- if (this.built) {
- data = {
- x: dragger.left - image.left,
- y: dragger.top - image.top,
- width: dragger.width,
- height: dragger.height
- };
+ if (this.complete) {
+ this.trigger(EVENT_CROP, this.getData());
+ } else if (!this.built) {
- data = this.transformData(data, TRUE, rounded);
+ // Only trigger one crop event before complete
+ this.$element.one(EVENT_BUILT, $.proxy(function () {
+ this.trigger(EVENT_CROP, this.getData());
+ }, this));
}
+ }
+ });
- return data;
- },
+ $.extend(prototype, {
+ initPreview: function () {
+ var crossOrigin = getCrossOrigin(this.crossOrigin);
+ var url = this.url;
- transformData: function (data, reversed, rounded) {
- var ratio = this.image.ratio,
- result = {};
+ this.$preview = $(this.options.preview);
+ this.$viewBox.html('<img' + crossOrigin + ' src="' + url + '">');
+ this.$preview.each(function () {
+ var $this = $(this);
- $.each(data, function (i, n) {
- n = num(n);
+ // Save the original size for recover
+ $this.data(DATA_PREVIEW, {
+ width: $this.width(),
+ height: $this.height(),
+ original: $this.html()
+ });
- if (REGEXP_OPTIONS.test(i) && !isNaN(n)) {
- result[i] = reversed ? (rounded ? Math.round(n / ratio) : n / ratio) : n * ratio;
- }
+ /**
+ * Override img element styles
+ * Add `display:block` to avoid margin top issue
+ * (Occur only when margin-top <= -height)
+ */
+ $this.html(
+ '<img' + crossOrigin + ' src="' + url + '" style="' +
+ 'display:block;width:100%;height:auto;' +
+ 'min-width:0!important;min-height:0!important;' +
+ 'max-width:none!important;max-height:none!important;' +
+ 'image-orientation:0deg!important">'
+ );
});
+ },
- return result;
+ resetPreview: function () {
+ this.$preview.each(function () {
+ var $this = $(this);
+
+ $this.html($this.data(DATA_PREVIEW).original).removeData(DATA_PREVIEW);
+ });
},
- setAspectRatio: function (aspectRatio) {
- var freeRatio = aspectRatio === "auto";
+ preview: function () {
+ var image = this.image;
+ var canvas = this.canvas;
+ var cropBox = this.cropBox;
+ var cropBoxWidth = cropBox.width;
+ var cropBoxHeight = cropBox.height;
+ var width = image.width;
+ var height = image.height;
+ var left = cropBox.left - canvas.left - image.left;
+ var top = cropBox.top - canvas.top - image.top;
- if (this.disabled) {
+ if (!this.cropped || this.disabled) {
return;
}
- aspectRatio = num(aspectRatio);
+ this.$viewBox.find('img').css({
+ width: width,
+ height: height,
+ marginLeft: -left,
+ marginTop: -top,
+ transform: getTransform(image)
+ });
- if (freeRatio || (!isNaN(aspectRatio) && aspectRatio > 0)) {
- this.defaults.aspectRatio = freeRatio ? NAN : aspectRatio;
+ this.$preview.each(function () {
+ var $this = $(this);
+ var data = $this.data(DATA_PREVIEW);
+ var originalWidth = data.width;
+ var originalHeight = data.height;
+ var newWidth = originalWidth;
+ var newHeight = originalHeight;
+ var ratio = 1;
- if (this.built) {
- this.initDragger();
- this.renderDragger();
- this.setData(this.defaults.data); // Reset to initial state
+ if (cropBoxWidth) {
+ ratio = originalWidth / cropBoxWidth;
+ newHeight = cropBoxHeight * ratio;
}
- }
- },
- getImageData: function () {
- var data = {};
+ if (cropBoxHeight && newHeight > originalHeight) {
+ ratio = originalHeight / cropBoxHeight;
+ newWidth = cropBoxWidth * ratio;
+ newHeight = originalHeight;
+ }
- if (this.ready) {
- $.each(this.image, function (name, value) {
- if (REGEXP_PROPERTIES.test(name)) {
- data[name] = value;
- }
+ $this.width(newWidth).height(newHeight).find('img').css({
+ width: width * ratio,
+ height: height * ratio,
+ marginLeft: -left * ratio,
+ marginTop: -top * ratio,
+ transform: getTransform(image)
});
- }
-
- return data;
- },
+ });
+ }
+ });
- getDataURL: function (options, type, quality) {
- var canvas = $("<canvas>")[0],
- data = this.getData(),
- dataURL = "",
- context;
+ $.extend(prototype, {
+ bind: function () {
+ var options = this.options;
+ var $this = this.$element;
+ var $cropper = this.$cropper;
- if (!$.isPlainObject(options)) {
- quality = type;
- type = options;
- options = {};
+ if ($.isFunction(options.cropstart)) {
+ $this.on(EVENT_CROP_START, options.cropstart);
}
- options = $.extend({
- width: data.width,
- height: data.height
- }, options);
-
- if (this.cropped && this.support.canvas) {
- canvas.width = options.width;
- canvas.height = options.height;
- context = canvas.getContext("2d");
-
- if (type === "image/jpeg") {
- context.fillStyle = "#fff";
- context.fillRect(0, 0, options.width, options.height);
- }
-
- context.drawImage(this.$clone[0], data.x, data.y, data.width, data.height, 0, 0, options.width, options.height);
- dataURL = canvas.toDataURL(type, quality);
+ if ($.isFunction(options.cropmove)) {
+ $this.on(EVENT_CROP_MOVE, options.cropmove);
}
- return dataURL;
- },
-
- setDragMode: function (mode) {
- var $canvas = this.$canvas,
- defaults = this.defaults,
- cropable = FALSE,
- movable = FALSE;
-
- if (!this.built || this.disabled) {
- return;
+ if ($.isFunction(options.cropend)) {
+ $this.on(EVENT_CROP_END, options.cropend);
}
- switch (mode) {
- case "crop":
- if (defaults.dragCrop) {
- cropable = TRUE;
- $canvas.data(STRING_DIRECTIVE, mode);
- }
+ if ($.isFunction(options.crop)) {
+ $this.on(EVENT_CROP, options.crop);
+ }
- break;
+ if ($.isFunction(options.zoom)) {
+ $this.on(EVENT_ZOOM, options.zoom);
+ }
- case "move":
- movable = TRUE;
- $canvas.data(STRING_DIRECTIVE, mode);
+ $cropper.on(EVENT_MOUSE_DOWN, $.proxy(this.cropStart, this));
- break;
-
- default:
- $canvas.removeData(STRING_DIRECTIVE);
+ if (options.zoomable && options.mouseWheelZoom) {
+ $cropper.on(EVENT_WHEEL, $.proxy(this.wheel, this));
}
- $canvas.toggleClass(CLASS_CROP, cropable).toggleClass(CLASS_MOVE, movable);
- },
-
- enable: function () {
- if (this.built) {
- this.disabled = FALSE;
- this.$cropper.removeClass(CLASS_DISABLED);
+ if (options.doubleClickToggle) {
+ $cropper.on(EVENT_DBLCLICK, $.proxy(this.dblclick, this));
}
- },
- disable: function () {
- if (this.built) {
- this.disabled = TRUE;
- this.$cropper.addClass(CLASS_DISABLED);
+ $document.
+ on(EVENT_MOUSE_MOVE, (this._cropMove = proxy(this.cropMove, this))).
+ on(EVENT_MOUSE_UP, (this._cropEnd = proxy(this.cropEnd, this)));
+
+ if (options.responsive) {
+ $window.on(EVENT_RESIZE, (this._resize = proxy(this.resize, this)));
}
},
- rotate: function (degree) {
- var image = this.image;
-
- degree = num(degree) || 0;
+ unbind: function () {
+ var options = this.options;
+ var $this = this.$element;
+ var $cropper = this.$cropper;
- if (!this.built || degree === 0 || this.disabled || !this.defaults.rotatable || !this.support.canvas) {
- return;
+ if ($.isFunction(options.cropstart)) {
+ $this.off(EVENT_CROP_START, options.cropstart);
}
- this.rotated = TRUE;
- degree = (image.rotate = (image.rotate + degree) % 360);
-
- // replace with "true" to prevent to override the original image
- this.replace(this.getRotatedDataURL(degree), true);
- },
+ if ($.isFunction(options.cropmove)) {
+ $this.off(EVENT_CROP_MOVE, options.cropmove);
+ }
- getRotatedDataURL: function (degree) {
- var canvas = $("<canvas>")[0],
- context = canvas.getContext("2d"),
- originalImage = this.originalImage,
- naturalWidth = originalImage.naturalWidth,
- naturalHeight = originalImage.naturalHeight,
- deg = abs(degree) % 180,
- arc = (deg > 90 ? (180 - deg) : deg) * Math.PI / 180,
- width = naturalWidth * cos(arc) + naturalHeight * sin(arc),
- height = naturalWidth * sin(arc) + naturalHeight * cos(arc);
+ if ($.isFunction(options.cropend)) {
+ $this.off(EVENT_CROP_END, options.cropend);
+ }
- canvas.width = width;
- canvas.height = height;
- context.save();
- context.translate(width / 2, height / 2);
- context.rotate(degree * Math.PI / 180);
- context.drawImage(this.$original[0], -naturalWidth / 2, -naturalHeight / 2, naturalWidth, naturalHeight);
- context.restore();
+ if ($.isFunction(options.crop)) {
+ $this.off(EVENT_CROP, options.crop);
+ }
- return canvas.toDataURL();
- },
+ if ($.isFunction(options.zoom)) {
+ $this.off(EVENT_ZOOM, options.zoom);
+ }
- zoom: function (delta) {
- var image = this.image,
- width,
- height,
- range;
+ $cropper.off(EVENT_MOUSE_DOWN, this.cropStart);
- delta = num(delta);
+ if (options.zoomable && options.mouseWheelZoom) {
+ $cropper.off(EVENT_WHEEL, this.wheel);
+ }
- if (!this.built || !delta || this.disabled || !this.defaults.zoomable) {
- return;
+ if (options.doubleClickToggle) {
+ $cropper.off(EVENT_DBLCLICK, this.dblclick);
}
- width = image.width * (1 + delta);
- height = image.height * (1 + delta);
- range = width / image._width;
+ $document.
+ off(EVENT_MOUSE_MOVE, this._cropMove).
+ off(EVENT_MOUSE_UP, this._cropEnd);
- if (range > 10) {
- return;
+ if (options.responsive) {
+ $window.off(EVENT_RESIZE, this._resize);
}
+ }
+ });
- if (range < 1) {
- width = image._width;
- height = image._height;
- }
+ $.extend(prototype, {
+ resize: function () {
+ var $container = this.$container;
+ var container = this.container;
+ var canvasData;
+ var cropBoxData;
+ var ratio;
- if (range <= 1) {
- this.setDragMode("crop");
- } else {
- this.setDragMode("move");
+ // Check `container` is necessary for IE8
+ if (this.disabled || !container) {
+ return;
}
- image.oldWidth = image.width;
- image.oldHeight = image.height;
+ ratio = $container.width() / container.width;
- image.width = width;
- image.height = height;
- image.ratio = image.width / image.naturalWidth;
+ // Resize when width changed or height changed
+ if (ratio !== 1 || $container.height() !== container.height) {
+ canvasData = this.getCanvasData();
+ cropBoxData = this.getCropBoxData();
- this.renderImage("zoom");
+ this.render();
+ this.setCanvasData($.each(canvasData, function (i, n) {
+ canvasData[i] = n * ratio;
+ }));
+ this.setCropBoxData($.each(cropBoxData, function (i, n) {
+ cropBoxData[i] = n * ratio;
+ }));
+ }
},
dblclick: function () {
@@ -997,16 +1132,18 @@
return;
}
- if (this.$canvas.hasClass(CLASS_CROP)) {
- this.setDragMode("move");
+ if (this.$dragBox.hasClass(CLASS_CROP)) {
+ this.setDragMode(ACTION_MOVE);
} else {
- this.setDragMode("crop");
+ this.setDragMode(ACTION_CROP);
}
},
wheel: function (event) {
- var e = event.originalEvent,
- delta = 1;
+ var originalEvent = event.originalEvent;
+ var e = originalEvent;
+ var ratio = num(this.options.wheelZoomRatio) || 0.1;
+ var delta = 1;
if (this.disabled) {
return;
@@ -1022,15 +1159,16 @@
delta = e.detail > 0 ? 1 : -1;
}
- this.zoom(delta * 0.1);
+ this.zoom(-delta * ratio, originalEvent);
},
- dragstart: function (event) {
- var touches = event.originalEvent.touches,
- e = event,
- directive,
- dragStartEvent,
- touchesLength;
+ cropStart: function (event) {
+ var options = this.options;
+ var originalEvent = event.originalEvent;
+ var touches = originalEvent && originalEvent.touches;
+ var e = event;
+ var touchesLength;
+ var action;
if (this.disabled) {
return;
@@ -1040,11 +1178,11 @@
touchesLength = touches.length;
if (touchesLength > 1) {
- if (this.defaults.zoomable && touchesLength === 2) {
+ if (options.zoomable && options.touchDragZoom && touchesLength === 2) {
e = touches[1];
this.startX2 = e.pageX;
this.startY2 = e.pageY;
- directive = "zoom";
+ action = ACTION_ZOOM;
} else {
return;
}
@@ -1053,35 +1191,40 @@
e = touches[0];
}
- directive = directive || $(e.target).data(STRING_DIRECTIVE);
-
- if (REGEXP_DIRECTIVES.test(directive)) {
- event.preventDefault();
-
- dragStartEvent = $.Event(EVENT_DRAG_START);
- this.$element.trigger(dragStartEvent);
+ action = action || $(e.target).data(DATA_ACTION);
- if (dragStartEvent.isDefaultPrevented()) {
+ if (REGEXP_ACTIONS.test(action)) {
+ if (this.trigger(EVENT_CROP_START, {
+ originalEvent: originalEvent,
+ action: action
+ }).isDefaultPrevented()) {
return;
}
- this.directive = directive;
- this.cropping = FALSE;
- this.startX = e.pageX;
- this.startY = e.pageY;
+ event.preventDefault();
+
+ this.action = action;
+ this.cropping = false;
+
+ // IE8 has `event.pageX/Y`, but not `event.originalEvent.pageX/Y`
+ // IE10 has `event.originalEvent.pageX/Y`, but not `event.pageX/Y`
+ this.startX = e.pageX || originalEvent && originalEvent.pageX;
+ this.startY = e.pageY || originalEvent && originalEvent.pageY;
- if (directive === "crop") {
- this.cropping = TRUE;
- this.$canvas.addClass(CLASS_MODAL);
+ if (action === ACTION_CROP) {
+ this.cropping = true;
+ this.$dragBox.addClass(CLASS_MODAL);
}
}
},
- dragmove: function (event) {
- var touches = event.originalEvent.touches,
- e = event,
- dragMoveEvent,
- touchesLength;
+ cropMove: function (event) {
+ var options = this.options;
+ var originalEvent = event.originalEvent;
+ var touches = originalEvent && originalEvent.touches;
+ var e = event;
+ var action = this.action;
+ var touchesLength;
if (this.disabled) {
return;
@@ -1091,7 +1234,7 @@
touchesLength = touches.length;
if (touchesLength > 1) {
- if (this.defaults.zoomable && touchesLength === 2) {
+ if (options.zoomable && options.touchDragZoom && touchesLength === 2) {
e = touches[1];
this.endX2 = e.pageX;
this.endY2 = e.pageY;
@@ -1103,87 +1246,106 @@
e = touches[0];
}
- if (this.directive) {
- event.preventDefault();
-
- dragMoveEvent = $.Event(EVENT_DRAG_MOVE);
- this.$element.trigger(dragMoveEvent);
-
- if (dragMoveEvent.isDefaultPrevented()) {
+ if (action) {
+ if (this.trigger(EVENT_CROP_MOVE, {
+ originalEvent: originalEvent,
+ action: action
+ }).isDefaultPrevented()) {
return;
}
- this.endX = e.pageX;
- this.endY = e.pageY;
+ event.preventDefault();
+
+ this.endX = e.pageX || originalEvent && originalEvent.pageX;
+ this.endY = e.pageY || originalEvent && originalEvent.pageY;
- this.dragging();
+ this.change(e.shiftKey, action === ACTION_ZOOM ? originalEvent : null);
}
},
- dragend: function (event) {
- var dragEndEvent;
+ cropEnd: function (event) {
+ var originalEvent = event.originalEvent;
+ var action = this.action;
if (this.disabled) {
return;
}
- if (this.directive) {
+ if (action) {
event.preventDefault();
- dragEndEvent = $.Event(EVENT_DRAG_END);
- this.$element.trigger(dragEndEvent);
-
- if (dragEndEvent.isDefaultPrevented()) {
- return;
- }
-
if (this.cropping) {
- this.cropping = FALSE;
- this.$canvas.toggleClass(CLASS_MODAL, this.cropped && this.defaults.modal);
+ this.cropping = false;
+ this.$dragBox.toggleClass(CLASS_MODAL, this.cropped && this.options.modal);
}
- this.directive = "";
+ this.action = '';
+
+ this.trigger(EVENT_CROP_END, {
+ originalEvent: originalEvent,
+ action: action
+ });
+ }
+ }
+ });
+
+ $.extend(prototype, {
+ change: function (shiftKey, originalEvent) {
+ var options = this.options;
+ var aspectRatio = options.aspectRatio;
+ var action = this.action;
+ var container = this.container;
+ var canvas = this.canvas;
+ var cropBox = this.cropBox;
+ var width = cropBox.width;
+ var height = cropBox.height;
+ var left = cropBox.left;
+ var top = cropBox.top;
+ var right = left + width;
+ var bottom = top + height;
+ var minLeft = 0;
+ var minTop = 0;
+ var maxWidth = container.width;
+ var maxHeight = container.height;
+ var renderable = true;
+ var offset;
+ var range;
+
+ // Locking aspect ratio in "free mode" by holding shift key (#259)
+ if (!aspectRatio && shiftKey) {
+ aspectRatio = width && height ? width / height : 1;
}
- },
- dragging: function () {
- var directive = this.directive,
- image = this.image,
- cropper = this.cropper,
- maxWidth = cropper.width,
- maxHeight = cropper.height,
- dragger = this.dragger,
- width = dragger.width,
- height = dragger.height,
- left = dragger.left,
- top = dragger.top,
- right = left + width,
- bottom = top + height,
- renderable = TRUE,
- aspectRatio = this.defaults.aspectRatio,
- range = {
- x: this.endX - this.startX,
- y: this.endY - this.startY
- },
- offset;
+ if (options.strict) {
+ minLeft = cropBox.minLeft;
+ minTop = cropBox.minTop;
+ maxWidth = minLeft + min(container.width, canvas.width);
+ maxHeight = minTop + min(container.height, canvas.height);
+ }
+
+ range = {
+ x: this.endX - this.startX,
+ y: this.endY - this.startY
+ };
if (aspectRatio) {
range.X = range.y * aspectRatio;
range.Y = range.x / aspectRatio;
}
- switch (directive) {
- // Move dragger
- case "all":
+ switch (action) {
+ // Move crop box
+ case ACTION_ALL:
left += range.x;
top += range.y;
-
break;
- // Resize dragger
- case "e":
- if (range.x >= 0 && (right >= maxWidth || aspectRatio && (top <= 0 || bottom >= maxHeight))) {
- renderable = FALSE;
+ // Resize crop box
+ case ACTION_EAST:
+ if (range.x >= 0 && (right >= maxWidth || aspectRatio &&
+ (top <= minTop || bottom >= maxHeight))) {
+
+ renderable = false;
break;
}
@@ -1195,15 +1357,17 @@
}
if (width < 0) {
- directive = "w";
+ action = ACTION_WEST;
width = 0;
}
break;
- case "n":
- if (range.y <= 0 && (top <= 0 || aspectRatio && (left <= 0 || right >= maxWidth))) {
- renderable = FALSE;
+ case ACTION_NORTH:
+ if (range.y <= 0 && (top <= minTop || aspectRatio &&
+ (left <= minLeft || right >= maxWidth))) {
+
+ renderable = false;
break;
}
@@ -1216,15 +1380,17 @@
}
if (height < 0) {
- directive = "s";
+ action = ACTION_SOUTH;
height = 0;
}
break;
- case "w":
- if (range.x <= 0 && (left <= 0 || aspectRatio && (top <= 0 || bottom >= maxHeight))) {
- renderable = FALSE;
+ case ACTION_WEST:
+ if (range.x <= 0 && (left <= minLeft || aspectRatio &&
+ (top <= minTop || bottom >= maxHeight))) {
+
+ renderable = false;
break;
}
@@ -1237,15 +1403,17 @@
}
if (width < 0) {
- directive = "e";
+ action = ACTION_EAST;
width = 0;
}
break;
- case "s":
- if (range.y >= 0 && (bottom >= maxHeight || aspectRatio && (left <= 0 || right >= maxWidth))) {
- renderable = FALSE;
+ case ACTION_SOUTH:
+ if (range.y >= 0 && (bottom >= maxHeight || aspectRatio &&
+ (left <= minLeft || right >= maxWidth))) {
+
+ renderable = false;
break;
}
@@ -1257,16 +1425,16 @@
}
if (height < 0) {
- directive = "n";
+ action = ACTION_NORTH;
height = 0;
}
break;
- case "ne":
+ case ACTION_NORTH_EAST:
if (aspectRatio) {
- if (range.y <= 0 && (top <= 0 || right >= maxWidth)) {
- renderable = FALSE;
+ if (range.y <= 0 && (top <= minTop || right >= maxWidth)) {
+ renderable = false;
break;
}
@@ -1277,15 +1445,15 @@
if (range.x >= 0) {
if (right < maxWidth) {
width += range.x;
- } else if (range.y <= 0 && top <= 0) {
- renderable = FALSE;
+ } else if (range.y <= 0 && top <= minTop) {
+ renderable = false;
}
} else {
width += range.x;
}
if (range.y <= 0) {
- if (top > 0) {
+ if (top > minTop) {
height -= range.y;
top += range.y;
}
@@ -1296,23 +1464,23 @@
}
if (width < 0 && height < 0) {
- directive = "sw";
+ action = ACTION_SOUTH_WEST;
height = 0;
width = 0;
} else if (width < 0) {
- directive = "nw";
+ action = ACTION_NORTH_WEST;
width = 0;
} else if (height < 0) {
- directive = "se";
+ action = ACTION_SOUTH_EAST;
height = 0;
}
break;
- case "nw":
+ case ACTION_NORTH_WEST:
if (aspectRatio) {
- if (range.y <= 0 && (top <= 0 || left <= 0)) {
- renderable = FALSE;
+ if (range.y <= 0 && (top <= minTop || left <= minLeft)) {
+ renderable = false;
break;
}
@@ -1322,11 +1490,11 @@
left += range.X;
} else {
if (range.x <= 0) {
- if (left > 0) {
+ if (left > minLeft) {
width -= range.x;
left += range.x;
- } else if (range.y <= 0 && top <= 0) {
- renderable = FALSE;
+ } else if (range.y <= 0 && top <= minTop) {
+ renderable = false;
}
} else {
width -= range.x;
@@ -1334,7 +1502,7 @@
}
if (range.y <= 0) {
- if (top > 0) {
+ if (top > minTop) {
height -= range.y;
top += range.y;
}
@@ -1345,23 +1513,23 @@
}
if (width < 0 && height < 0) {
- directive = "se";
+ action = ACTION_SOUTH_EAST;
height = 0;
width = 0;
} else if (width < 0) {
- directive = "ne";
+ action = ACTION_NORTH_EAST;
width = 0;
} else if (height < 0) {
- directive = "sw";
+ action = ACTION_SOUTH_WEST;
height = 0;
}
break;
- case "sw":
+ case ACTION_SOUTH_WEST:
if (aspectRatio) {
- if (range.x <= 0 && (left <= 0 || bottom >= maxHeight)) {
- renderable = FALSE;
+ if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) {
+ renderable = false;
break;
}
@@ -1370,11 +1538,11 @@
height = width / aspectRatio;
} else {
if (range.x <= 0) {
- if (left > 0) {
+ if (left > minLeft) {
width -= range.x;
left += range.x;
} else if (range.y >= 0 && bottom >= maxHeight) {
- renderable = FALSE;
+ renderable = false;
}
} else {
width -= range.x;
@@ -1391,23 +1559,23 @@
}
if (width < 0 && height < 0) {
- directive = "ne";
+ action = ACTION_NORTH_EAST;
height = 0;
width = 0;
} else if (width < 0) {
- directive = "se";
+ action = ACTION_SOUTH_EAST;
width = 0;
} else if (height < 0) {
- directive = "nw";
+ action = ACTION_NORTH_WEST;
height = 0;
}
break;
- case "se":
+ case ACTION_SOUTH_EAST:
if (aspectRatio) {
if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) {
- renderable = FALSE;
+ renderable = false;
break;
}
@@ -1418,7 +1586,7 @@
if (right < maxWidth) {
width += range.x;
} else if (range.y >= 0 && bottom >= maxHeight) {
- renderable = FALSE;
+ renderable = false;
}
} else {
width += range.x;
@@ -1434,76 +1602,74 @@
}
if (width < 0 && height < 0) {
- directive = "nw";
+ action = ACTION_NORTH_WEST;
height = 0;
width = 0;
} else if (width < 0) {
- directive = "sw";
+ action = ACTION_SOUTH_WEST;
width = 0;
} else if (height < 0) {
- directive = "ne";
+ action = ACTION_NORTH_EAST;
height = 0;
}
break;
- // Move image
- case "move":
- image.left += range.x;
- image.top += range.y;
- this.renderImage("move");
- renderable = FALSE;
+ // Move canvas
+ case ACTION_MOVE:
+ this.move(range.x, range.y);
+ renderable = false;
break;
- // Scale image
- case "zoom":
- this.zoom(function (x, y, x1, y1, x2, y2) {
- return (sqrt(x2 * x2 + y2 * y2) - sqrt(x1 * x1 + y1 * y1)) / sqrt(x * x + y * y);
- }(
- image.width,
- image.height,
+ // Zoom canvas
+ case ACTION_ZOOM:
+ this.zoom((function (x1, y1, x2, y2) {
+ var z1 = sqrt(x1 * x1 + y1 * y1);
+ var z2 = sqrt(x2 * x2 + y2 * y2);
+
+ return (z2 - z1) / z1;
+ })(
abs(this.startX - this.startX2),
abs(this.startY - this.startY2),
abs(this.endX - this.endX2),
abs(this.endY - this.endY2)
- ));
-
- this.endX2 = this.startX2;
- this.endY2 = this.startY2;
- renderable = FALSE;
+ ), originalEvent);
+ this.startX2 = this.endX2;
+ this.startY2 = this.endY2;
+ renderable = false;
break;
- // Crop image
- case "crop":
+ // Create crop box
+ case ACTION_CROP:
if (range.x && range.y) {
offset = this.$cropper.offset();
left = this.startX - offset.left;
top = this.startY - offset.top;
- width = dragger.minWidth;
- height = dragger.minHeight;
+ width = cropBox.minWidth;
+ height = cropBox.minHeight;
if (range.x > 0) {
if (range.y > 0) {
- directive = "se";
+ action = ACTION_SOUTH_EAST;
} else {
- directive = "ne";
+ action = ACTION_NORTH_EAST;
top -= height;
}
} else {
if (range.y > 0) {
- directive = "sw";
+ action = ACTION_SOUTH_WEST;
left -= width;
} else {
- directive = "nw";
+ action = ACTION_NORTH_WEST;
left -= width;
top -= height;
}
}
- // Show the dragger if is hidden
+ // Show the crop box if is hidden
if (!this.cropped) {
- this.cropped = TRUE;
- this.$dragger.removeClass(CLASS_HIDDEN);
+ this.cropped = true;
+ this.$cropBox.removeClass(CLASS_HIDDEN);
}
}
@@ -1513,121 +1679,832 @@
}
if (renderable) {
- dragger.width = width;
- dragger.height = height;
- dragger.left = left;
- dragger.top = top;
- this.directive = directive;
+ cropBox.width = width;
+ cropBox.height = height;
+ cropBox.left = left;
+ cropBox.top = top;
+ this.action = action;
- this.renderDragger();
+ this.renderCropBox();
}
// Override
this.startX = this.endX;
this.startY = this.endY;
}
- };
+ });
- // Use the string compressor: Strmin (https://github.com/fengyuanchen/strmin)
- Cropper.TEMPLATE = (function (source, words) {
- words = words.split(",");
- return source.replace(/\d+/g, function (i) {
- return words[i];
- });
- })('<0 6="5-container"><0 6="5-canvas"></0><0 6="5-dragger"><1 6="5-viewer"></1><1 6="5-8 8-h"></1><1 6="5-8 8-v"></1><1 6="5-face" 3-2="all"></1><1 6="5-7 7-e" 3-2="e"></1><1 6="5-7 7-n" 3-2="n"></1><1 6="5-7 7-w" 3-2="w"></1><1 6="5-7 7-s" 3-2="s"></1><1 6="5-4 4-e" 3-2="e"></1><1 6="5-4 4-n" 3-2="n"></1><1 6="5-4 4-w" 3-2="w"></1><1 6="5-4 4-s" 3-2="s"></1><1 6="5-4 4-ne" 3-2="ne"></1><1 6="5-4 4-nw" 3-2="nw"></1><1 6="5-4 4-sw" 3-2="sw"></1><1 6="5-4 4-se" 3-2="se"></1></0></0>', "div,span,directive,data,point,cropper,class,line,dashed");
+ $.extend(prototype, {
- /* Template source:
- <div class="cropper-container">
- <div class="cropper-canvas"></div>
- <div class="cropper-dragger">
- <span class="cropper-viewer"></span>
- <span class="cropper-dashed dashed-h"></span>
- <span class="cropper-dashed dashed-v"></span>
- <span class="cropper-face" data-directive="all"></span>
- <span class="cropper-line line-e" data-directive="e"></span>
- <span class="cropper-line line-n" data-directive="n"></span>
- <span class="cropper-line line-w" data-directive="w"></span>
- <span class="cropper-line line-s" data-directive="s"></span>
- <span class="cropper-point point-e" data-directive="e"></span>
- <span class="cropper-point point-n" data-directive="n"></span>
- <span class="cropper-point point-w" data-directive="w"></span>
- <span class="cropper-point point-s" data-directive="s"></span>
- <span class="cropper-point point-ne" data-directive="ne"></span>
- <span class="cropper-point point-nw" data-directive="nw"></span>
- <span class="cropper-point point-sw" data-directive="sw"></span>
- <span class="cropper-point point-se" data-directive="se"></span>
- </div>
- </div>
- */
+ // Show the crop box manually
+ crop: function () {
+ if (!this.built || this.disabled) {
+ return;
+ }
- Cropper.DEFAULTS = {
- // Basic
- aspectRatio: "auto",
- autoCropArea: 0.8, // 80%
- data: {
- // x: 0,
- // y: 0,
- // width: 300,
- // height: 150
+ if (!this.cropped) {
+ this.cropped = true;
+ this.limitCropBox(true, true);
+
+ if (this.options.modal) {
+ this.$dragBox.addClass(CLASS_MODAL);
+ }
+
+ this.$cropBox.removeClass(CLASS_HIDDEN);
+ }
+
+ this.setCropBoxData(this.initialCropBox);
},
- done: $.noop,
- preview: "",
- // Toggles
- multiple: FALSE,
- autoCrop: TRUE,
- dragCrop: TRUE,
- dashed: TRUE,
- modal: TRUE,
- movable: TRUE,
- resizable: TRUE,
- zoomable: TRUE,
- rotatable: TRUE,
- checkImageOrigin: TRUE,
+ // Reset the image and crop box to their initial states
+ reset: function () {
+ if (!this.built || this.disabled) {
+ return;
+ }
+
+ this.image = $.extend({}, this.initialImage);
+ this.canvas = $.extend({}, this.initialCanvas);
+
+ // Required for strict mode
+ this.cropBox = $.extend({}, this.initialCropBox);
- // Dimensions
- minWidth: 0,
- minHeight: 0,
- maxWidth: INFINITY,
- maxHeight: INFINITY,
- minContainerWidth: 300,
- minContainerHeight: 150,
+ this.renderCanvas();
+
+ if (this.cropped) {
+ this.renderCropBox();
+ }
+ },
+
+ // Clear the crop box
+ clear: function () {
+ if (!this.cropped || this.disabled) {
+ return;
+ }
+
+ $.extend(this.cropBox, {
+ left: 0,
+ top: 0,
+ width: 0,
+ height: 0
+ });
- // Events
- build: NULL,
- built: NULL,
- dragstart: NULL,
- dragmove: NULL,
- dragend: NULL
+ this.cropped = false;
+ this.renderCropBox();
+
+ this.limitCanvas(true, true);
+
+ // Render canvas after crop box rendered
+ this.renderCanvas();
+
+ this.$dragBox.removeClass(CLASS_MODAL);
+ this.$cropBox.addClass(CLASS_HIDDEN);
+ },
+
+ /**
+ * Replace the image's src and rebuild the cropper
+ *
+ * @param {String} url
+ */
+ replace: function (url) {
+ if (!this.disabled && url) {
+ if (this.isImg) {
+ this.replaced = true;
+ this.$element.attr('src', url);
+ }
+
+ // Clear previous data
+ this.options.data = null;
+ this.load(url);
+ }
+ },
+
+ // Enable (unfreeze) the cropper
+ enable: function () {
+ if (this.built) {
+ this.disabled = false;
+ this.$cropper.removeClass(CLASS_DISABLED);
+ }
+ },
+
+ // Disable (freeze) the cropper
+ disable: function () {
+ if (this.built) {
+ this.disabled = true;
+ this.$cropper.addClass(CLASS_DISABLED);
+ }
+ },
+
+ // Destroy the cropper and remove the instance from the image
+ destroy: function () {
+ var $this = this.$element;
+
+ if (this.ready) {
+ if (this.isImg && this.replaced) {
+ $this.attr('src', this.originalUrl);
+ }
+
+ this.unbuild();
+ $this.removeClass(CLASS_HIDDEN);
+ } else {
+ if (this.isImg) {
+ $this.off(EVENT_LOAD, this.start);
+ } else if (this.$clone) {
+ this.$clone.remove();
+ }
+ }
+
+ $this.removeData(NAMESPACE);
+ },
+
+ /**
+ * Move the canvas
+ *
+ * @param {Number} offsetX
+ * @param {Number} offsetY (optional)
+ */
+ move: function (offsetX, offsetY) {
+ var canvas = this.canvas;
+
+ // If "offsetY" is not present, its default value is "offsetX"
+ if (isUndefined(offsetY)) {
+ offsetY = offsetX;
+ }
+
+ offsetX = num(offsetX);
+ offsetY = num(offsetY);
+
+ if (this.built && !this.disabled && this.options.movable) {
+ canvas.left += isNumber(offsetX) ? offsetX : 0;
+ canvas.top += isNumber(offsetY) ? offsetY : 0;
+ this.renderCanvas(true);
+ }
+ },
+
+ /**
+ * Zoom the canvas
+ *
+ * @param {Number} ratio
+ * @param {Event} _originalEvent (private)
+ */
+ zoom: function (ratio, _originalEvent) {
+ var canvas = this.canvas;
+ var width;
+ var height;
+
+ ratio = num(ratio);
+
+ if (ratio && this.built && !this.disabled && this.options.zoomable) {
+ if (this.trigger(EVENT_ZOOM, {
+ originalEvent: _originalEvent,
+ ratio: ratio
+ }).isDefaultPrevented()) {
+ return;
+ }
+
+ if (ratio < 0) {
+ ratio = 1 / (1 - ratio);
+ } else {
+ ratio = 1 + ratio;
+ }
+
+ width = canvas.width * ratio;
+ height = canvas.height * ratio;
+ canvas.left -= (width - canvas.width) / 2;
+ canvas.top -= (height - canvas.height) / 2;
+ canvas.width = width;
+ canvas.height = height;
+ this.renderCanvas(true);
+ this.setDragMode(ACTION_MOVE);
+ }
+ },
+
+ /**
+ * Rotate the canvas
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate()
+ *
+ * @param {Number} degree
+ */
+ rotate: function (degree) {
+ var image = this.image;
+ var rotate = image.rotate || 0;
+
+ degree = num(degree) || 0;
+
+ if (this.built && !this.disabled && this.options.rotatable) {
+ image.rotate = (rotate + degree) % 360;
+ this.rotated = true;
+ this.renderCanvas(true);
+ }
+ },
+
+ /**
+ * Scale the image
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale()
+ *
+ * @param {Number} scaleX
+ * @param {Number} scaleY (optional)
+ */
+ scale: function (scaleX, scaleY) {
+ var image = this.image;
+
+ // If "scaleY" is not present, its default value is "scaleX"
+ if (isUndefined(scaleY)) {
+ scaleY = scaleX;
+ }
+
+ scaleX = num(scaleX);
+ scaleY = num(scaleY);
+
+ if (this.built && !this.disabled && this.options.scalable) {
+ image.scaleX = isNumber(scaleX) ? scaleX : 1;
+ image.scaleY = isNumber(scaleY) ? scaleY : 1;
+ this.renderImage(true);
+ }
+ },
+
+ /**
+ * Get the cropped area position and size data (base on the original image)
+ *
+ * @param {Boolean} rounded (optional)
+ * @return {Object} data
+ */
+ getData: function (rounded) {
+ var options = this.options;
+ var image = this.image;
+ var canvas = this.canvas;
+ var cropBox = this.cropBox;
+ var ratio;
+ var data;
+
+ if (this.built && this.cropped) {
+ data = {
+ x: cropBox.left - canvas.left,
+ y: cropBox.top - canvas.top,
+ width: cropBox.width,
+ height: cropBox.height
+ };
+
+ ratio = image.width / image.naturalWidth;
+
+ $.each(data, function (i, n) {
+ n = n / ratio;
+ data[i] = rounded ? Math.round(n) : n;
+ });
+
+ } else {
+ data = {
+ x: 0,
+ y: 0,
+ width: 0,
+ height: 0
+ };
+ }
+
+ if (options.rotatable) {
+ data.rotate = image.rotate || 0;
+ }
+
+ if (options.scalable) {
+ data.scaleX = image.scaleX || 1;
+ data.scaleY = image.scaleY || 1;
+ }
+
+ return data;
+ },
+
+ /**
+ * Set the cropped area position and size with new data
+ *
+ * @param {Object} data
+ */
+ setData: function (data) {
+ var options = this.options;
+ var image = this.image;
+ var canvas = this.canvas;
+ var cropBoxData = {};
+ var rotated;
+ var scaled;
+ var ratio;
+
+ if ($.isFunction(data)) {
+ data = data.call(this.element);
+ }
+
+ if (this.built && !this.disabled && $.isPlainObject(data)) {
+ if (options.rotatable) {
+ if (isNumber(data.rotate) && data.rotate !== image.rotate) {
+ image.rotate = data.rotate;
+ this.rotated = rotated = true;
+ }
+ }
+
+ if (options.scalable) {
+ if (isNumber(data.scaleX) && data.scaleX !== image.scaleX) {
+ image.scaleX = data.scaleX;
+ scaled = true;
+ }
+
+ if (isNumber(data.scaleY) && data.scaleY !== image.scaleY) {
+ image.scaleY = data.scaleY;
+ scaled = true;
+ }
+ }
+
+ if (rotated) {
+ this.renderCanvas();
+ } else if (scaled) {
+ this.renderImage();
+ }
+
+ ratio = image.width / image.naturalWidth;
+
+ if (isNumber(data.x)) {
+ cropBoxData.left = data.x * ratio + canvas.left;
+ }
+
+ if (isNumber(data.y)) {
+ cropBoxData.top = data.y * ratio + canvas.top;
+ }
+
+ if (isNumber(data.width)) {
+ cropBoxData.width = data.width * ratio;
+ }
+
+ if (isNumber(data.height)) {
+ cropBoxData.height = data.height * ratio;
+ }
+
+ this.setCropBoxData(cropBoxData);
+ }
+ },
+
+ /**
+ * Get the container size data
+ *
+ * @return {Object} data
+ */
+ getContainerData: function () {
+ return this.built ? this.container : {};
+ },
+
+ /**
+ * Get the image position and size data
+ *
+ * @return {Object} data
+ */
+ getImageData: function () {
+ return this.ready ? this.image : {};
+ },
+
+ /**
+ * Get the canvas position and size data
+ *
+ * @return {Object} data
+ */
+ getCanvasData: function () {
+ var canvas = this.canvas;
+ var data;
+
+ if (this.built) {
+ data = {
+ left: canvas.left,
+ top: canvas.top,
+ width: canvas.width,
+ height: canvas.height
+ };
+ }
+
+ return data || {};
+ },
+
+ /**
+ * Set the canvas position and size with new data
+ *
+ * @param {Object} data
+ */
+ setCanvasData: function (data) {
+ var canvas = this.canvas;
+ var aspectRatio = canvas.aspectRatio;
+
+ if ($.isFunction(data)) {
+ data = data.call(this.$element);
+ }
+
+ if (this.built && !this.disabled && $.isPlainObject(data)) {
+ if (isNumber(data.left)) {
+ canvas.left = data.left;
+ }
+
+ if (isNumber(data.top)) {
+ canvas.top = data.top;
+ }
+
+ if (isNumber(data.width)) {
+ canvas.width = data.width;
+ canvas.height = data.width / aspectRatio;
+ } else if (isNumber(data.height)) {
+ canvas.height = data.height;
+ canvas.width = data.height * aspectRatio;
+ }
+
+ this.renderCanvas(true);
+ }
+ },
+
+ /**
+ * Get the crop box position and size data
+ *
+ * @return {Object} data
+ */
+ getCropBoxData: function () {
+ var cropBox = this.cropBox;
+ var data;
+
+ if (this.built && this.cropped) {
+ data = {
+ left: cropBox.left,
+ top: cropBox.top,
+ width: cropBox.width,
+ height: cropBox.height
+ };
+ }
+
+ return data || {};
+ },
+
+ /**
+ * Set the crop box position and size with new data
+ *
+ * @param {Object} data
+ */
+ setCropBoxData: function (data) {
+ var cropBox = this.cropBox;
+ var aspectRatio = this.options.aspectRatio;
+ var widthChanged;
+ var heightChanged;
+
+ if ($.isFunction(data)) {
+ data = data.call(this.$element);
+ }
+
+ if (this.built && this.cropped && !this.disabled && $.isPlainObject(data)) {
+
+ if (isNumber(data.left)) {
+ cropBox.left = data.left;
+ }
+
+ if (isNumber(data.top)) {
+ cropBox.top = data.top;
+ }
+
+ if (isNumber(data.width) && data.width !== cropBox.width) {
+ widthChanged = true;
+ cropBox.width = data.width;
+ }
+
+ if (isNumber(data.height) && data.height !== cropBox.height) {
+ heightChanged = true;
+ cropBox.height = data.height;
+ }
+
+ if (aspectRatio) {
+ if (widthChanged) {
+ cropBox.height = cropBox.width / aspectRatio;
+ } else if (heightChanged) {
+ cropBox.width = cropBox.height * aspectRatio;
+ }
+ }
+
+ this.renderCropBox();
+ }
+ },
+
+ /**
+ * Get a canvas drawn the cropped image
+ *
+ * @param {Object} options (optional)
+ * @return {HTMLCanvasElement} canvas
+ */
+ getCroppedCanvas: function (options) {
+ var originalWidth;
+ var originalHeight;
+ var canvasWidth;
+ var canvasHeight;
+ var scaledWidth;
+ var scaledHeight;
+ var scaledRatio;
+ var aspectRatio;
+ var canvas;
+ var context;
+ var data;
+
+ if (!this.built || !this.cropped || !SUPPORT_CANVAS) {
+ return;
+ }
+
+ if (!$.isPlainObject(options)) {
+ options = {};
+ }
+
+ data = this.getData();
+ originalWidth = data.width;
+ originalHeight = data.height;
+ aspectRatio = originalWidth / originalHeight;
+
+ if ($.isPlainObject(options)) {
+ scaledWidth = options.width;
+ scaledHeight = options.height;
+
+ if (scaledWidth) {
+ scaledHeight = scaledWidth / aspectRatio;
+ scaledRatio = scaledWidth / originalWidth;
+ } else if (scaledHeight) {
+ scaledWidth = scaledHeight * aspectRatio;
+ scaledRatio = scaledHeight / originalHeight;
+ }
+ }
+
+ canvasWidth = scaledWidth || originalWidth;
+ canvasHeight = scaledHeight || originalHeight;
+
+ canvas = $('<canvas>')[0];
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
+ context = canvas.getContext('2d');
+
+ if (options.fillColor) {
+ context.fillStyle = options.fillColor;
+ context.fillRect(0, 0, canvasWidth, canvasHeight);
+ }
+
+ // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage
+ context.drawImage.apply(context, (function () {
+ var source = getSourceCanvas(this.$clone[0], this.image);
+ var sourceWidth = source.width;
+ var sourceHeight = source.height;
+ var args = [source];
+
+ // Source canvas
+ var srcX = data.x;
+ var srcY = data.y;
+ var srcWidth;
+ var srcHeight;
+
+ // Destination canvas
+ var dstX;
+ var dstY;
+ var dstWidth;
+ var dstHeight;
+
+ if (srcX <= -originalWidth || srcX > sourceWidth) {
+ srcX = srcWidth = dstX = dstWidth = 0;
+ } else if (srcX <= 0) {
+ dstX = -srcX;
+ srcX = 0;
+ srcWidth = dstWidth = min(sourceWidth, originalWidth + srcX);
+ } else if (srcX <= sourceWidth) {
+ dstX = 0;
+ srcWidth = dstWidth = min(originalWidth, sourceWidth - srcX);
+ }
+
+ if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) {
+ srcY = srcHeight = dstY = dstHeight = 0;
+ } else if (srcY <= 0) {
+ dstY = -srcY;
+ srcY = 0;
+ srcHeight = dstHeight = min(sourceHeight, originalHeight + srcY);
+ } else if (srcY <= sourceHeight) {
+ dstY = 0;
+ srcHeight = dstHeight = min(originalHeight, sourceHeight - srcY);
+ }
+
+ args.push(srcX, srcY, srcWidth, srcHeight);
+
+ // Scale destination sizes
+ if (scaledRatio) {
+ dstX *= scaledRatio;
+ dstY *= scaledRatio;
+ dstWidth *= scaledRatio;
+ dstHeight *= scaledRatio;
+ }
+
+ // Avoid "IndexSizeError" in IE and Firefox
+ if (dstWidth > 0 && dstHeight > 0) {
+ args.push(dstX, dstY, dstWidth, dstHeight);
+ }
+
+ return args;
+ }).call(this));
+
+ return canvas;
+ },
+
+ /**
+ * Change the aspect ratio of the crop box
+ *
+ * @param {Number} aspectRatio
+ */
+ setAspectRatio: function (aspectRatio) {
+ var options = this.options;
+
+ if (!this.disabled && !isUndefined(aspectRatio)) {
+
+ // 0 -> NaN
+ options.aspectRatio = num(aspectRatio) || NaN;
+
+ if (this.built) {
+ this.initCropBox();
+
+ if (this.cropped) {
+ this.renderCropBox();
+ }
+ }
+ }
+ },
+
+ /**
+ * Change the drag mode
+ *
+ * @param {String} mode (optional)
+ */
+ setDragMode: function (mode) {
+ var options = this.options;
+ var croppable;
+ var movable;
+
+ if (this.ready && !this.disabled) {
+ croppable = options.dragCrop && mode === ACTION_CROP;
+ movable = options.movable && mode === ACTION_MOVE;
+ mode = (croppable || movable) ? mode : ACTION_NONE;
+
+ this.$dragBox.
+ data(DATA_ACTION, mode).
+ toggleClass(CLASS_CROP, croppable).
+ toggleClass(CLASS_MOVE, movable);
+
+ if (!options.cropBoxMovable) {
+
+ // Sync drag mode to crop box when it is not movable(#300)
+ this.$face.
+ data(DATA_ACTION, mode).
+ toggleClass(CLASS_CROP, croppable).
+ toggleClass(CLASS_MOVE, movable);
+ }
+ }
+ }
+ });
+
+ $.extend(Cropper.prototype, prototype);
+
+ Cropper.DEFAULTS = {
+
+ // Define the aspect ratio of the crop box
+ aspectRatio: NaN,
+
+ // An object with the previous cropping result data
+ data: null,
+
+ // A jQuery selector for adding extra containers to preview
+ preview: '',
+
+ // Strict mode, the image cannot zoom out less than the container
+ strict: true,
+
+ // Rebuild when resize the window
+ responsive: true,
+
+ // Check if the target image is cross origin
+ checkImageOrigin: true,
+
+ // Show the black modal
+ modal: true,
+
+ // Show the dashed lines for guiding
+ guides: true,
+
+ // Show the center indicator for guiding
+ center: true,
+
+ // Show the white modal to highlight the crop box
+ highlight: true,
+
+ // Show the grid background
+ background: true,
+
+ // Enable to crop the image automatically when initialize
+ autoCrop: true,
+
+ // Define the percentage of automatic cropping area when initializes
+ autoCropArea: 0.8,
+
+ // Enable to create new crop box by dragging over the image
+ dragCrop: true,
+
+ // Enable to move the image
+ movable: true,
+
+ // Enable to rotate the image
+ rotatable: true,
+
+ // Enable to scale the image
+ scalable: true,
+
+ // Enable to zoom the image
+ zoomable: true,
+
+ // Enable to zoom the image by wheeling mouse
+ mouseWheelZoom: true,
+
+ // Define zoom ratio when zoom the image by wheeling mouse
+ wheelZoomRatio: 0.1,
+
+ // Enable to zoom the image by dragging touch
+ touchDragZoom: true,
+
+ // Enable to move the crop box
+ cropBoxMovable: true,
+
+ // Enable to resize the crop box
+ cropBoxResizable: true,
+
+ // Toggle drag mode between "crop" and "move" when double click on the cropper
+ doubleClickToggle: true,
+
+ // Size limitation
+ minCanvasWidth: 0,
+ minCanvasHeight: 0,
+ minCropBoxWidth: 0,
+ minCropBoxHeight: 0,
+ minContainerWidth: 200,
+ minContainerHeight: 100,
+
+ // Shortcuts of events
+ build: null,
+ built: null,
+ cropstart: null,
+ cropmove: null,
+ cropend: null,
+ crop: null,
+ zoom: null
};
Cropper.setDefaults = function (options) {
$.extend(Cropper.DEFAULTS, options);
};
+ Cropper.TEMPLATE = (
+ '<div class="cropper-container">' +
+ '<div class="cropper-canvas"></div>' +
+ '<div class="cropper-drag-box"></div>' +
+ '<div class="cropper-crop-box">' +
+ '<span class="cropper-view-box"></span>' +
+ '<span class="cropper-dashed dashed-h"></span>' +
+ '<span class="cropper-dashed dashed-v"></span>' +
+ '<span class="cropper-center"></span>' +
+ '<span class="cropper-face"></span>' +
+ '<span class="cropper-line line-e" data-action="e"></span>' +
+ '<span class="cropper-line line-n" data-action="n"></span>' +
+ '<span class="cropper-line line-w" data-action="w"></span>' +
+ '<span class="cropper-line line-s" data-action="s"></span>' +
+ '<span class="cropper-point point-e" data-action="e"></span>' +
+ '<span class="cropper-point point-n" data-action="n"></span>' +
+ '<span class="cropper-point point-w" data-action="w"></span>' +
+ '<span class="cropper-point point-s" data-action="s"></span>' +
+ '<span class="cropper-point point-ne" data-action="ne"></span>' +
+ '<span class="cropper-point point-nw" data-action="nw"></span>' +
+ '<span class="cropper-point point-sw" data-action="sw"></span>' +
+ '<span class="cropper-point point-se" data-action="se"></span>' +
+ '</div>' +
+ '</div>'
+ );
+
// Save the other cropper
Cropper.other = $.fn.cropper;
// Register as jQuery plugin
$.fn.cropper = function (options) {
- var args = toArray(arguments, 1),
- result;
+ var args = toArray(arguments, 1);
+ var result;
this.each(function () {
- var $this = $(this),
- data = $this.data("cropper"),
- fn;
+ var $this = $(this);
+ var data = $this.data(NAMESPACE);
+ var fn;
if (!data) {
- $this.data("cropper", (data = new Cropper(this, options)));
+ if (/destroy/.test(options)) {
+ return;
+ }
+
+ $this.data(NAMESPACE, (data = new Cropper(this, options)));
}
- if (typeof options === "string" && $.isFunction((fn = data[options]))) {
+ if (typeof options === 'string' && $.isFunction(fn = data[options])) {
result = fn.apply(data, args);
}
});
- return (typeof result !== STRING_UNDEFINED ? result : this);
+ return isUndefined(result) ? this : result;
};
$.fn.cropper.Constructor = Cropper;
@@ -1638,4 +2515,5 @@
$.fn.cropper = Cropper.other;
return this;
};
+
});
diff --git a/javascript/jquery/plugins/cropper/cropper.min.css b/javascript/jquery/plugins/cropper/cropper.min.css
index 4cf0820..cf3d050 100644
--- a/javascript/jquery/plugins/cropper/cropper.min.css
+++ b/javascript/jquery/plugins/cropper/cropper.min.css
@@ -1,9 +1,9 @@
/*!
- * Cropper v0.7.9
+ * Cropper v1.0.0
* https://github.com/fengyuanchen/cropper
*
- * Copyright 2014-2015 Fengyuan Chen
+ * Copyright (c) 2014-2015 Fengyuan Chen and contributors
* Released under the MIT license
- */
-
-.cropper-container{position:relative;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.cropper-container img{width:100%;height:100%;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important}.cropper-canvas,.cropper-modal{position:absolute;top:0;right:0;bottom:0;left:0}.cropper-canvas{background-color:#fff;opacity:0;filter:alpha(opacity=0)}.cropper-modal{background-color:#000;opacity:.5;filter:alpha(opacity=50)}.cropper-dragger{position:absolute;top:10%;left:10%;width:80%;height:80%}.cropper-viewer{display:block;width:100%;height:100%;overflow:hidden;outline:#69f solid 1px;outline-color:rgba(51,102,255,.75)}.cropper-dashed{position:absolute;display:block;border:0 dashed #fff;opacity:.5;filter:alpha(opacity=50)}.cropper-dashed.dashed-h{top:33.3%;left:0;width:100%;height:33.3%;border-top-width:1px;border-bottom-width:1px}.cropper-dashed.dashed-v{top:0;left:33.3%;width:33.3%;height:100%;border-right-width:1px;border-left-width:1px}.cropper-face,.cropper-line,.cropper-point{position:absolute;display:block;width:100%;height:100%;opacity:.1;filter:alpha(opacity=10)}.cropper-face{top:0;left:0;cursor:move;background-color:#fff}.cropper-line{background-color:#69f}.cropper-line.line-e{top:0;right:-3px;width:5px;cursor:e-resize}.cropper-line.line-n{top:-3px;left:0;height:5px;cursor:n-resize}.cropper-line.line-w{top:0;left:-3px;width:5px;cursor:w-resize}.cropper-line.line-s{bottom:-3px;left:0;height:5px;cursor:s-resize}.cropper-point{width:5px;height:5px;background-color:#69f;opacity:.75;filter:alpha(opacity=75)}.cropper-point.point-e{top:50%;right:-3px;margin-top:-3px;cursor:e-resize}.cropper-point.point-n{top:-3px;left:50%;margin-left:-3px;cursor:n-resize}.cropper-point.point-w{top:50%;left:-3px;margin-top:-3px;cursor:w-resize}.cropper-point.point-s{bottom:-3px;left:50%;margin-left:-3px;cursor:s-resize}.cropper-point.point-ne{top:-3px;right:-3px;cursor:ne-resize}.cropper-point.point-nw{top:-3px;left:-3px;cursor:nw-resize}.cropper-point.point-sw{bottom:-3px;left:-3px;cursor:sw-resize}.cropper-point.point-se{right:-3px;bottom:-3px;width:20px;height:20px;cursor:se-resize;opacity:1;filter:alpha(opacity=100)}.cropper-point.point-se:before{position:absolute;right:-50%;bottom:-50%;display:block;width:200%;height:200%;content:" ";background-color:#69f;opacity:0;filter:alpha(opacity=0)}@media (min-width:768px){.cropper-point.point-se{width:15px;height:15px}}@media (min-width:992px){.cropper-point.point-se{width:10px;height:10px}}@media (min-width:1200px){.cropper-point.point-se{width:5px;height:5px;opacity:.75;filter:alpha(opacity=75)}}.cropper-hidden{display:none!important}.cropper-invisible{position:fixed;top:0;left:0;z-index:-1;width:auto!important;max-width:none!important;height:auto!important;max-height:none!important;opacity:0;filter:alpha(opacity=0)}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-canvas,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed} \ No newline at end of file
+ *
+ * Date: 2015-10-10T02:10:06.999Z
+ */.cropper-container{position:relative;overflow:hidden;font-size:0;line-height:0;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;direction:ltr!important;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none}.cropper-container img{display:block;width:100%;min-width:0!important;max-width:none!important;height:100%;min-height:0!important;max-height:none!important;image-orientation:0deg!important}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal{position:absolute;top:0;right:0;bottom:0;left:0}.cropper-drag-box{background-color:#fff;filter:alpha(opacity=0);opacity:0}.cropper-dashed,.cropper-modal{filter:alpha(opacity=50);opacity:.5}.cropper-modal{background-color:#000}.cropper-view-box{display:block;width:100%;height:100%;overflow:hidden;outline:#39f solid 1px;outline-color:rgba(51,153,255,.75)}.cropper-dashed{position:absolute;display:block;border:0 dashed #eee}.cropper-dashed.dashed-h{top:33.33333%;left:0;width:100%;height:33.33333%;border-top-width:1px;border-bottom-width:1px}.cropper-dashed.dashed-v{top:0;left:33.33333%;width:33.33333%;height:100%;border-right-width:1px;border-left-width:1px}.cropper-center{position:absolute;top:50%;left:50%;display:block;width:0;height:0;filter:alpha(opacity=75);opacity:.75}.cropper-center:after,.cropper-center:before{position:absolute;display:block;content:" ";background-color:#eee}.cropper-center:before{top:0;left:-3px;width:7px;height:1px}.cropper-center:after{top:-3px;left:0;width:1px;height:7px}.cropper-face,.cropper-line,.cropper-point{position:absolute;display:block;width:100%;height:100%;filter:alpha(opacity=10);opacity:.1}.cropper-face{top:0;left:0;background-color:#fff}.cropper-line,.cropper-point{background-color:#39f}.cropper-line.line-e{top:0;right:-3px;width:5px;cursor:e-resize}.cropper-line.line-n{top:-3px;left:0;height:5px;cursor:n-resize}.cropper-line.line-w{top:0;left:-3px;width:5px;cursor:w-resize}.cropper-line.line-s{bottom:-3px;left:0;height:5px;cursor:s-resize}.cropper-point{width:5px;height:5px;filter:alpha(opacity=75);opacity:.75}.cropper-point.point-e{top:50%;right:-3px;margin-top:-3px;cursor:e-resize}.cropper-point.point-n{top:-3px;left:50%;margin-left:-3px;cursor:n-resize}.cropper-point.point-w{top:50%;left:-3px;margin-top:-3px;cursor:w-resize}.cropper-point.point-s{bottom:-3px;left:50%;margin-left:-3px;cursor:s-resize}.cropper-point.point-ne{top:-3px;right:-3px;cursor:ne-resize}.cropper-point.point-nw{top:-3px;left:-3px;cursor:nw-resize}.cropper-point.point-sw{bottom:-3px;left:-3px;cursor:sw-resize}.cropper-point.point-se{right:-3px;bottom:-3px;width:20px;height:20px;cursor:se-resize;filter:alpha(opacity=100);opacity:1}.cropper-point.point-se:before{position:absolute;right:-50%;bottom:-50%;display:block;width:200%;height:200%;content:" ";background-color:#39f;filter:alpha(opacity=0);opacity:0}@media (min-width:768px){.cropper-point.point-se{width:15px;height:15px}}@media (min-width:992px){.cropper-point.point-se{width:10px;height:10px}}@media (min-width:1200px){.cropper-point.point-se{width:5px;height:5px;filter:alpha(opacity=75);opacity:.75}}.cropper-bg{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC)}.cropper-invisible{filter:alpha(opacity=0);opacity:0}.cropper-hide{position:absolute;display:block;width:0;height:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed} \ No newline at end of file
diff --git a/javascript/jquery/plugins/cropper/cropper.min.js b/javascript/jquery/plugins/cropper/cropper.min.js
index 51e1362..1a619a1 100644
--- a/javascript/jquery/plugins/cropper/cropper.min.js
+++ b/javascript/jquery/plugins/cropper/cropper.min.js
@@ -1,9 +1,10 @@
/*!
- * Cropper v0.7.9
+ * Cropper v1.0.0
* https://github.com/fengyuanchen/cropper
*
- * Copyright 2014-2015 Fengyuan Chen
+ * Copyright (c) 2014-2015 Fengyuan Chen and contributors
* Released under the MIT license
+ *
+ * Date: 2015-10-10T02:10:08.624Z
*/
-
-!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){"use strict";var b=a(window),c=a(document),d=window.location,e=!0,f=!1,g=null,h=0/0,i=1/0,j="undefined",k="directive",l=".cropper",m=/^(e|n|w|s|ne|nw|sw|se|all|crop|move|zoom)$/,n=/^(x|y|width|height)$/,o=/^(naturalWidth|naturalHeight|width|height|aspectRatio|ratio|rotate)$/,p="cropper-modal",q="cropper-hidden",r="cropper-invisible",s="cropper-move",t="cropper-crop",u="cropper-disabled",v="mousedown touchstart",w="mousemove touchmove",x="mouseup mouseleave touchend touchleave touchcancel",y="wheel mousewheel DOMMouseScroll",z="resize"+l,A="dblclick",B="build"+l,C="built"+l,D="dragstart"+l,E="dragmove"+l,F="dragend"+l,G=function(a){return"number"==typeof a},H=function(a,b){var c=[];return G(b)&&c.push(b),c.slice.apply(a,c)},I=function(a,b){var c=H(arguments,2);return function(){return a.apply(b,c.concat(H(arguments)))}},J=function(a){var b="timestamp="+(new Date).getTime();return a+(-1===a.indexOf("?")?"?":"&")+b},K=function(b,c){this.element=b,this.$element=a(b),this.defaults=a.extend({},K.DEFAULTS,a.isPlainObject(c)?c:{}),this.$original=g,this.ready=f,this.built=f,this.cropped=f,this.rotated=f,this.disabled=f,this.replaced=f,this.init()},L=Math.sqrt,M=Math.min,N=Math.max,O=Math.abs,P=Math.sin,Q=Math.cos,R=parseFloat;K.prototype={constructor:K,support:{canvas:a.isFunction(a("<canvas>")[0].getContext)},init:function(){var b=this.defaults;a.each(b,function(a,c){switch(a){case"aspectRatio":b[a]=O(R(c))||h;break;case"autoCropArea":b[a]=O(R(c))||.8;break;case"minWidth":case"minHeight":b[a]=O(R(c))||0;break;case"maxWidth":case"maxHeight":b[a]=O(R(c))||i}}),this.image={rotate:0},this.load()},load:function(){var b,c,d=this,f=this.$element,g=this.element,h=this.image,i="";f.is("img")?c=f.prop("src"):f.is("canvas")&&this.support.canvas&&(c=g.toDataURL()),c&&(this.replaced&&(h.rotate=0),this.defaults.checkImageOrigin&&this.isCrossOriginURL(c)&&(i=" crossOrigin",c=J(c)),this.$clone=b=a("<img"+i+' src="'+c+'">'),b.one("load",function(){h.naturalWidth=this.naturalWidth||b.width(),h.naturalHeight=this.naturalHeight||b.height(),h.aspectRatio=h.naturalWidth/h.naturalHeight,d.url=c,d.ready=e,d.build()}),b.addClass(r).prependTo("body"))},isCrossOriginURL:function(a){var b=a.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);return!b||b[1]===d.protocol&&b[2]===d.hostname&&b[3]===d.port?f:e},build:function(){var b,c,d=this.$element,g=this.defaults;this.ready&&(this.built&&this.unbuild(),d.one(B,g.build),b=a.Event(B),d.trigger(b),b.isDefaultPrevented()||(this.$cropper=c=a(K.TEMPLATE),d.addClass(q),this.$clone.removeClass(r).prependTo(c),this.rotated||(this.$original=this.$clone.clone(),this.$original.addClass(q).prependTo(this.$cropper),this.originalImage=a.extend({},this.image)),this.$container=d.parent(),this.$container.append(c),this.$canvas=c.find(".cropper-canvas"),this.$dragger=c.find(".cropper-dragger"),this.$viewer=c.find(".cropper-viewer"),g.autoCrop?this.cropped=e:this.$dragger.addClass(q),g.modal&&this.$canvas.addClass(p),!g.dashed&&this.$dragger.find(".cropper-dashed").addClass(q),!g.movable&&this.$dragger.find(".cropper-face").data(k,"move"),!g.resizable&&this.$dragger.find(".cropper-line, .cropper-point").addClass(q),this.addListeners(),this.initPreview(),this.built=e,g.dragCrop&&this.setDragMode("crop"),this.update(),this.replaced=f,d.one(C,g.built),d.trigger(C)))},unbuild:function(){this.built&&(this.built=f,this.removeListeners(),this.$preview.empty(),this.$preview=g,this.$dragger=g,this.$canvas=g,this.$container=g,this.$cropper.remove(),this.$cropper=g)},update:function(a){this.initContainer(),this.initCropper(),this.initImage(),this.initDragger(),a?(this.setData(a,e),this.setDragMode("crop")):this.setData(this.defaults.data)},resize:function(){clearTimeout(this.resizing),this.resizing=setTimeout(a.proxy(this.update,this,this.getData()),200)},preview:function(){var b=this.image,c=this.dragger,d=b.width,e=b.height,f=c.left-b.left,g=c.top-b.top;this.$viewer.find("img").css({width:d,height:e,marginLeft:-f,marginTop:-g}),this.$preview.each(function(){var b=a(this),h=b.data(),i=h.width/c.width,j=h.width,k=c.height*i;k>h.height&&(i=h.height/c.height,j=c.width*i,k=h.height),b.width(j).height(k).find("img").css({width:d*i,height:e*i,marginLeft:-f*i,marginTop:-g*i})})},addListeners:function(){var d=this.defaults;this.$element.on(D,d.dragstart).on(E,d.dragmove).on(F,d.dragend),this.$cropper.on(v,a.proxy(this.dragstart,this)).on(A,a.proxy(this.dblclick,this)),d.zoomable&&this.$cropper.on(y,a.proxy(this.wheel,this)),d.multiple?this.$cropper.on(w,a.proxy(this.dragmove,this)).on(x,a.proxy(this.dragend,this)):c.on(w,this._dragmove=I(this.dragmove,this)).on(x,this._dragend=I(this.dragend,this)),b.on(z,this._resize=I(this.resize,this))},removeListeners:function(){var a=this.defaults;this.$element.off(D,a.dragstart).off(E,a.dragmove).off(F,a.dragend),this.$cropper.off(v,this.dragstart).off(A,this.dblclick),a.zoomable&&this.$cropper.off(y,this.wheel),a.multiple?this.$cropper.off(w,this.dragmove).off(x,this.dragend):c.off(w,this._dragmove).off(x,this._dragend),b.off(z,this._resize)},initPreview:function(){var b=this.url;this.$preview=a(this.defaults.preview),this.$viewer.html('<img src="'+b+'">'),this.$preview.each(function(){var c=a(this);c.data({width:c.width(),height:c.height()}).html('<img src="'+b+'" style="display:block;width:100%;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;">')})},initContainer:function(){var a=this.$element,b=this.$container,c=this.$cropper,d=this.defaults;c.addClass(q),a.removeClass(q),this.container={width:N(b.width(),d.minContainerWidth),height:N(b.height(),d.minContainerHeight)},a.addClass(q),c.removeClass(q)},initCropper:function(){var a,b=this.container,c=this.image;c.naturalWidth*b.height/c.naturalHeight-b.width>=0?(a={width:b.width,height:b.width/c.aspectRatio,left:0},a.top=(b.height-a.height)/2):(a={width:b.height*c.aspectRatio,height:b.height,top:0},a.left=(b.width-a.width)/2),this.$cropper.css({width:a.width,height:a.height,left:a.left,top:a.top}),this.cropper=a},initImage:function(){var b=this.image,c=this.cropper,d={_width:c.width,_height:c.height,width:c.width,height:c.height,left:0,top:0,ratio:c.width/b.naturalWidth};this.defaultImage=a.extend({},b,d),b._width!==c.width||b._height!==c.height?a.extend(b,d):(b=a.extend({},d,b),this.replaced&&(b.ratio=d.ratio)),this.image=b,this.renderImage()},renderImage:function(a){var b=this.image;"zoom"===a&&(b.left-=(b.width-b.oldWidth)/2,b.top-=(b.height-b.oldHeight)/2),b.left=M(N(b.left,b._width-b.width),0),b.top=M(N(b.top,b._height-b.height),0),this.$clone.css({width:b.width,height:b.height,marginLeft:b.left,marginTop:b.top}),a&&(this.defaults.done(this.getData()),this.preview())},initDragger:function(){var b,c,d=this.defaults,e=this.cropper,f=d.aspectRatio||this.image.aspectRatio,g=this.image.ratio;c=e.height*f-e.width>=0?{height:e.width/f,width:e.width,left:0,top:(e.height-e.width/f)/2,maxWidth:e.width,maxHeight:e.width/f}:{height:e.height,width:e.height*f,left:(e.width-e.height*f)/2,top:0,maxWidth:e.height*f,maxHeight:e.height},c.minWidth=0,c.minHeight=0,d.aspectRatio?(isFinite(d.maxWidth)?(c.maxWidth=M(c.maxWidth,d.maxWidth*g),c.maxHeight=c.maxWidth/f):isFinite(d.maxHeight)&&(c.maxHeight=M(c.maxHeight,d.maxHeight*g),c.maxWidth=c.maxHeight*f),d.minWidth>0?(c.minWidth=N(0,d.minWidth*g),c.minHeight=c.minWidth/f):d.minHeight>0&&(c.minHeight=N(0,d.minHeight*g),c.minWidth=c.minHeight*f)):(c.maxWidth=M(c.maxWidth,d.maxWidth*g),c.maxHeight=M(c.maxHeight,d.maxHeight*g),c.minWidth=N(0,d.minWidth*g),c.minHeight=N(0,d.minHeight*g)),c.minWidth=M(c.maxWidth,c.minWidth),c.minHeight=M(c.maxHeight,c.minHeight),b=a.extend({},c),b.width=N(c.minWidth,c.width*d.autoCropArea),b.height=N(c.minHeight,c.height*d.autoCropArea),b.left=(e.width-b.width)/2,b.top=(e.height-b.height)/2,b.oldLeft=c.oldLeft=c.left,b.oldTop=c.oldTop=c.top,this.autoCropDragger=b,this.defaultDragger=a.extend({},c),this.dragger=c},renderDragger:function(){var a=this.dragger,b=this.cropper;a.width>a.maxWidth?(a.width=a.maxWidth,a.left=a.oldLeft):a.width<a.minWidth&&(a.width=a.minWidth,a.left=a.oldLeft),a.height>a.maxHeight?(a.height=a.maxHeight,a.top=a.oldTop):a.height<a.minHeight&&(a.height=a.minHeight,a.top=a.oldTop),a.left=M(N(a.left,0),b.width-a.width),a.top=M(N(a.top,0),b.height-a.height),a.oldLeft=a.left,a.oldTop=a.top,this.dragger=a,this.defaults.movable&&this.$dragger.find(".cropper-face").data(k,a.width===b.width&&a.height===b.height?"move":"all"),this.disabled||this.defaults.done(this.getData()),this.$dragger.css({width:a.width,height:a.height,left:a.left,top:a.top}),this.preview()},reset:function(b){this.cropped&&!this.disabled&&(b&&(this.defaults.data={}),this.image=a.extend({},this.defaultImage),this.renderImage(),this.dragger=a.extend({},this.defaultDragger),this.setData(this.defaults.data))},clear:function(){this.cropped&&!this.disabled&&(this.cropped=f,this.setData({x:0,y:0,width:0,height:0}),this.$canvas.removeClass(p),this.$dragger.addClass(q))},destroy:function(){var a=this.$element;this.ready||this.$clone.off("load").remove(),this.unbuild(),a.removeClass(q).removeData("cropper"),this.rotated&&a.attr("src",this.$original.attr("src"))},replace:function(b,c){var d,g=this,h=this.$element,i=this.element;!this.disabled&&b&&b!==this.url&&b!==h.attr("src")&&(c||(this.rotated=f,this.replaced=e),h.is("img")?(h.attr("src",b),this.load()):h.is("canvas")&&this.support.canvas&&(d=i.getContext("2d"),a('<img src="'+b+'">').one("load",function(){i.width=this.width,i.height=this.height,d.clearRect(0,0,i.width,i.height),d.drawImage(this,0,0),g.load()})))},setData:function(b,c){var d=this.cropper,e=this.dragger,f=this.image,h=this.defaults.aspectRatio;this.built&&!this.disabled&&typeof b!==j&&((b===g||a.isEmptyObject(b))&&(e=a.extend({},this.autoCropDragger)),a.isPlainObject(b)&&!a.isEmptyObject(b)&&(c||(this.defaults.data=b),b=this.transformData(b),G(b.x)&&b.x<=d.width-f.left&&(e.left=b.x+f.left),G(b.y)&&b.y<=d.height-f.top&&(e.top=b.y+f.top),h?G(b.width)&&b.width<=e.maxWidth&&b.width>=e.minWidth?(e.width=b.width,e.height=e.width/h):G(b.height)&&b.height<=e.maxHeight&&b.height>=e.minHeight&&(e.height=b.height,e.width=e.height*h):(G(b.width)&&b.width<=e.maxWidth&&b.width>=e.minWidth&&(e.width=b.width),G(b.height)&&b.height<=e.maxHeight&&b.height>=e.minHeight&&(e.height=b.height))),this.dragger=e,this.renderDragger())},getData:function(a){var b=this.dragger,c=this.image,d={};return this.built&&(d={x:b.left-c.left,y:b.top-c.top,width:b.width,height:b.height},d=this.transformData(d,e,a)),d},transformData:function(b,c,d){var e=this.image.ratio,f={};return a.each(b,function(a,b){b=R(b),n.test(a)&&!isNaN(b)&&(f[a]=c?d?Math.round(b/e):b/e:b*e)}),f},setAspectRatio:function(a){var b="auto"===a;this.disabled||(a=R(a),(b||!isNaN(a)&&a>0)&&(this.defaults.aspectRatio=b?h:a,this.built&&(this.initDragger(),this.renderDragger(),this.setData(this.defaults.data))))},getImageData:function(){var b={};return this.ready&&a.each(this.image,function(a,c){o.test(a)&&(b[a]=c)}),b},getDataURL:function(b,c,d){var e,f=a("<canvas>")[0],g=this.getData(),h="";return a.isPlainObject(b)||(d=c,c=b,b={}),b=a.extend({width:g.width,height:g.height},b),this.cropped&&this.support.canvas&&(f.width=b.width,f.height=b.height,e=f.getContext("2d"),"image/jpeg"===c&&(e.fillStyle="#fff",e.fillRect(0,0,b.width,b.height)),e.drawImage(this.$clone[0],g.x,g.y,g.width,g.height,0,0,b.width,b.height),h=f.toDataURL(c,d)),h},setDragMode:function(a){var b=this.$canvas,c=this.defaults,d=f,g=f;if(this.built&&!this.disabled){switch(a){case"crop":c.dragCrop&&(d=e,b.data(k,a));break;case"move":g=e,b.data(k,a);break;default:b.removeData(k)}b.toggleClass(t,d).toggleClass(s,g)}},enable:function(){this.built&&(this.disabled=f,this.$cropper.removeClass(u))},disable:function(){this.built&&(this.disabled=e,this.$cropper.addClass(u))},rotate:function(a){var b=this.image;a=R(a)||0,this.built&&0!==a&&!this.disabled&&this.defaults.rotatable&&this.support.canvas&&(this.rotated=e,a=b.rotate=(b.rotate+a)%360,this.replace(this.getRotatedDataURL(a),!0))},getRotatedDataURL:function(b){var c=a("<canvas>")[0],d=c.getContext("2d"),e=this.originalImage,f=e.naturalWidth,g=e.naturalHeight,h=O(b)%180,i=(h>90?180-h:h)*Math.PI/180,j=f*Q(i)+g*P(i),k=f*P(i)+g*Q(i);return c.width=j,c.height=k,d.save(),d.translate(j/2,k/2),d.rotate(b*Math.PI/180),d.drawImage(this.$original[0],-f/2,-g/2,f,g),d.restore(),c.toDataURL()},zoom:function(a){var b,c,d,e=this.image;a=R(a),this.built&&a&&!this.disabled&&this.defaults.zoomable&&(b=e.width*(1+a),c=e.height*(1+a),d=b/e._width,d>10||(1>d&&(b=e._width,c=e._height),this.setDragMode(1>=d?"crop":"move"),e.oldWidth=e.width,e.oldHeight=e.height,e.width=b,e.height=c,e.ratio=e.width/e.naturalWidth,this.renderImage("zoom")))},dblclick:function(){this.disabled||this.setDragMode(this.$canvas.hasClass(t)?"move":"crop")},wheel:function(a){var b=a.originalEvent,c=1;this.disabled||(a.preventDefault(),b.deltaY?c=b.deltaY>0?1:-1:b.wheelDelta?c=-b.wheelDelta/120:b.detail&&(c=b.detail>0?1:-1),this.zoom(.1*c))},dragstart:function(b){var c,d,g,h=b.originalEvent.touches,i=b;if(!this.disabled){if(h){if(g=h.length,g>1){if(!this.defaults.zoomable||2!==g)return;i=h[1],this.startX2=i.pageX,this.startY2=i.pageY,c="zoom"}i=h[0]}if(c=c||a(i.target).data(k),m.test(c)){if(b.preventDefault(),d=a.Event(D),this.$element.trigger(d),d.isDefaultPrevented())return;this.directive=c,this.cropping=f,this.startX=i.pageX,this.startY=i.pageY,"crop"===c&&(this.cropping=e,this.$canvas.addClass(p))}}},dragmove:function(b){var c,d,e=b.originalEvent.touches,f=b;if(!this.disabled){if(e){if(d=e.length,d>1){if(!this.defaults.zoomable||2!==d)return;f=e[1],this.endX2=f.pageX,this.endY2=f.pageY}f=e[0]}if(this.directive){if(b.preventDefault(),c=a.Event(E),this.$element.trigger(c),c.isDefaultPrevented())return;this.endX=f.pageX,this.endY=f.pageY,this.dragging()}}},dragend:function(b){var c;if(!this.disabled&&this.directive){if(b.preventDefault(),c=a.Event(F),this.$element.trigger(c),c.isDefaultPrevented())return;this.cropping&&(this.cropping=f,this.$canvas.toggleClass(p,this.cropped&&this.defaults.modal)),this.directive=""}},dragging:function(){var a,b=this.directive,c=this.image,d=this.cropper,g=d.width,h=d.height,i=this.dragger,j=i.width,k=i.height,l=i.left,m=i.top,n=l+j,o=m+k,p=e,r=this.defaults.aspectRatio,s={x:this.endX-this.startX,y:this.endY-this.startY};switch(r&&(s.X=s.y*r,s.Y=s.x/r),b){case"all":l+=s.x,m+=s.y;break;case"e":if(s.x>=0&&(n>=g||r&&(0>=m||o>=h))){p=f;break}j+=s.x,r&&(k=j/r,m-=s.Y/2),0>j&&(b="w",j=0);break;case"n":if(s.y<=0&&(0>=m||r&&(0>=l||n>=g))){p=f;break}k-=s.y,m+=s.y,r&&(j=k*r,l+=s.X/2),0>k&&(b="s",k=0);break;case"w":if(s.x<=0&&(0>=l||r&&(0>=m||o>=h))){p=f;break}j-=s.x,l+=s.x,r&&(k=j/r,m+=s.Y/2),0>j&&(b="e",j=0);break;case"s":if(s.y>=0&&(o>=h||r&&(0>=l||n>=g))){p=f;break}k+=s.y,r&&(j=k*r,l-=s.X/2),0>k&&(b="n",k=0);break;case"ne":if(r){if(s.y<=0&&(0>=m||n>=g)){p=f;break}k-=s.y,m+=s.y,j=k*r}else s.x>=0?g>n?j+=s.x:s.y<=0&&0>=m&&(p=f):j+=s.x,s.y<=0?m>0&&(k-=s.y,m+=s.y):(k-=s.y,m+=s.y);0>j&&0>k?(b="sw",k=0,j=0):0>j?(b="nw",j=0):0>k&&(b="se",k=0);break;case"nw":if(r){if(s.y<=0&&(0>=m||0>=l)){p=f;break}k-=s.y,m+=s.y,j=k*r,l+=s.X}else s.x<=0?l>0?(j-=s.x,l+=s.x):s.y<=0&&0>=m&&(p=f):(j-=s.x,l+=s.x),s.y<=0?m>0&&(k-=s.y,m+=s.y):(k-=s.y,m+=s.y);0>j&&0>k?(b="se",k=0,j=0):0>j?(b="ne",j=0):0>k&&(b="sw",k=0);break;case"sw":if(r){if(s.x<=0&&(0>=l||o>=h)){p=f;break}j-=s.x,l+=s.x,k=j/r}else s.x<=0?l>0?(j-=s.x,l+=s.x):s.y>=0&&o>=h&&(p=f):(j-=s.x,l+=s.x),s.y>=0?h>o&&(k+=s.y):k+=s.y;0>j&&0>k?(b="ne",k=0,j=0):0>j?(b="se",j=0):0>k&&(b="nw",k=0);break;case"se":if(r){if(s.x>=0&&(n>=g||o>=h)){p=f;break}j+=s.x,k=j/r}else s.x>=0?g>n?j+=s.x:s.y>=0&&o>=h&&(p=f):j+=s.x,s.y>=0?h>o&&(k+=s.y):k+=s.y;0>j&&0>k?(b="nw",k=0,j=0):0>j?(b="sw",j=0):0>k&&(b="ne",k=0);break;case"move":c.left+=s.x,c.top+=s.y,this.renderImage("move"),p=f;break;case"zoom":this.zoom(function(a,b,c,d,e,f){return(L(e*e+f*f)-L(c*c+d*d))/L(a*a+b*b)}(c.width,c.height,O(this.startX-this.startX2),O(this.startY-this.startY2),O(this.endX-this.endX2),O(this.endY-this.endY2))),this.endX2=this.startX2,this.endY2=this.startY2,p=f;break;case"crop":s.x&&s.y&&(a=this.$cropper.offset(),l=this.startX-a.left,m=this.startY-a.top,j=i.minWidth,k=i.minHeight,s.x>0?s.y>0?b="se":(b="ne",m-=k):s.y>0?(b="sw",l-=j):(b="nw",l-=j,m-=k),this.cropped||(this.cropped=e,this.$dragger.removeClass(q)))}p&&(i.width=j,i.height=k,i.left=l,i.top=m,this.directive=b,this.renderDragger()),this.startX=this.endX,this.startY=this.endY}},K.TEMPLATE=function(a,b){return b=b.split(","),a.replace(/\d+/g,function(a){return b[a]})}('<0 6="5-container"><0 6="5-canvas"></0><0 6="5-dragger"><1 6="5-viewer"></1><1 6="5-8 8-h"></1><1 6="5-8 8-v"></1><1 6="5-face" 3-2="all"></1><1 6="5-7 7-e" 3-2="e"></1><1 6="5-7 7-n" 3-2="n"></1><1 6="5-7 7-w" 3-2="w"></1><1 6="5-7 7-s" 3-2="s"></1><1 6="5-4 4-e" 3-2="e"></1><1 6="5-4 4-n" 3-2="n"></1><1 6="5-4 4-w" 3-2="w"></1><1 6="5-4 4-s" 3-2="s"></1><1 6="5-4 4-ne" 3-2="ne"></1><1 6="5-4 4-nw" 3-2="nw"></1><1 6="5-4 4-sw" 3-2="sw"></1><1 6="5-4 4-se" 3-2="se"></1></0></0>',"div,span,directive,data,point,cropper,class,line,dashed"),K.DEFAULTS={aspectRatio:"auto",autoCropArea:.8,data:{},done:a.noop,preview:"",multiple:f,autoCrop:e,dragCrop:e,dashed:e,modal:e,movable:e,resizable:e,zoomable:e,rotatable:e,checkImageOrigin:e,minWidth:0,minHeight:0,maxWidth:i,maxHeight:i,minContainerWidth:300,minContainerHeight:150,build:g,built:g,dragstart:g,dragmove:g,dragend:g},K.setDefaults=function(b){a.extend(K.DEFAULTS,b)},K.other=a.fn.cropper,a.fn.cropper=function(b){var c,d=H(arguments,1);return this.each(function(){var e,f=a(this),g=f.data("cropper");g||f.data("cropper",g=new K(this,b)),"string"==typeof b&&a.isFunction(e=g[b])&&(c=e.apply(g,d))}),typeof c!==j?c:this},a.fn.cropper.Constructor=K,a.fn.cropper.setDefaults=K.setDefaults,a.fn.cropper.noConflict=function(){return a.fn.cropper=K.other,this}}); \ No newline at end of file
+!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):jQuery)}(function(t){"use strict";function i(t){return"number"==typeof t&&!isNaN(t)}function e(t){return"undefined"==typeof t}function s(t,e){var s=[];return i(e)&&s.push(e),s.slice.apply(t,s)}function o(t,i){var e=s(arguments,2);return function(){return t.apply(i,e.concat(s(arguments)))}}function h(t){var i=t.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);return i&&(i[1]!==f.protocol||i[2]!==f.hostname||i[3]!==f.port)}function a(t){var i="timestamp="+(new Date).getTime();return t+(-1===t.indexOf("?")?"?":"&")+i}function n(t){return t?' crossOrigin="'+t+'"':""}function r(t,i){var e;return t.naturalWidth?i(t.naturalWidth,t.naturalHeight):(e=document.createElement("img"),e.onload=function(){i(this.width,this.height)},void(e.src=t.src))}function p(t){var e=[],s=t.rotate,o=t.scaleX,h=t.scaleY;return i(s)&&e.push("rotate("+s+"deg)"),i(o)&&i(h)&&e.push("scale("+o+","+h+")"),e.length?e.join(" "):"none"}function c(t,i){var e,s,o=at(t.degree)%180,h=(o>90?180-o:o)*Math.PI/180,a=nt(h),n=rt(h),r=t.width,p=t.height,c=t.aspectRatio;return i?(e=r/(n+a/c),s=e/c):(e=r*n+p*a,s=r*a+p*n),{width:e,height:s}}function d(e,s){var o,h,a,n=t("<canvas>")[0],r=n.getContext("2d"),p=0,d=0,l=s.naturalWidth,g=s.naturalHeight,u=s.rotate,f=s.scaleX,m=s.scaleY,v=i(f)&&i(m)&&(1!==f||1!==m),w=i(u)&&0!==u,x=w||v,b=l,C=g;return v&&(o=l/2,h=g/2),w&&(a=c({width:l,height:g,degree:u}),b=a.width,C=a.height,o=a.width/2,h=a.height/2),n.width=b,n.height=C,x&&(p=-l/2,d=-g/2,r.save(),r.translate(o,h)),w&&r.rotate(u*Math.PI/180),v&&r.scale(f,m),r.drawImage(e,p,d,l,g),x&&r.restore(),n}function l(i,e){this.$element=t(i),this.options=t.extend({},l.DEFAULTS,t.isPlainObject(e)&&e),this.ready=!1,this.built=!1,this.complete=!1,this.rotated=!1,this.cropped=!1,this.disabled=!1,this.replaced=!1,this.isImg=!1,this.originalUrl="",this.crossOrigin="",this.canvas=null,this.cropBox=null,this.init()}var g=t(window),u=t(document),f=window.location,m="cropper",v="cropper-modal",w="cropper-hide",x="cropper-hidden",b="cropper-invisible",C="cropper-move",y="cropper-crop",B="cropper-disabled",$="cropper-bg",D="mousedown touchstart pointerdown MSPointerDown",Y="mousemove touchmove pointermove MSPointerMove",X="mouseup touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel",T="wheel mousewheel DOMMouseScroll",k="dblclick",M="load."+m,W="error."+m,L="resize."+m,H="build."+m,R="built."+m,z="cropstart."+m,I="cropmove."+m,P="cropend."+m,E="crop."+m,F="zoom."+m,O=/^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/,S="preview",j="action",A="e",N="w",U="s",Z="n",_="se",q="sw",K="ne",Q="nw",G="all",J="crop",V="move",tt="zoom",it="none",et=t.isFunction(t("<canvas>")[0].getContext),st=Math.sqrt,ot=Math.min,ht=Math.max,at=Math.abs,nt=Math.sin,rt=Math.cos,pt=parseFloat,ct={version:"1.0.0"};t.extend(ct,{init:function(){var t,i=this.$element;if(i.is("img")){if(this.isImg=!0,this.originalUrl=t=i.attr("src"),!t)return;t=i.prop("src")}else i.is("canvas")&&et&&(t=i[0].toDataURL());this.load(t)},trigger:function(i,e){var s=t.Event(i,e);return this.$element.trigger(s),s},load:function(i){var e,s,o=this.options,r=this.$element,p="";i&&(this.url=i,r.one(H,o.build),this.trigger(H).isDefaultPrevented()||(o.checkImageOrigin&&h(i)&&(p=r.prop("crossOrigin"),p||(p="anonymous",e=a(i)),this.crossOrigin=p),this.$clone=s=t("<img"+n(p)+' src="'+(e||i)+'">'),this.isImg?r[0].complete?this.start():r.one(M,t.proxy(this.start,this)):s.one(M,t.proxy(this.start,this)).one(W,t.proxy(this.stop,this)).addClass(w).insertAfter(r)))},start:function(){var i=this.$element,e=this.$clone;this.isImg||(e.off(W,this.stop),i=e),r(i[0],t.proxy(function(t,i){this.image={naturalWidth:t,naturalHeight:i,aspectRatio:t/i},this.ready=!0,this.build()},this))},stop:function(){this.$clone.remove(),this.$clone=null}}),t.extend(ct,{build:function(){var i,e,s,o=this.options,h=this.$element,a=this.$clone;this.ready&&(this.built&&this.unbuild(),this.$container=h.parent(),this.$cropper=i=t(l.TEMPLATE),this.$canvas=i.find(".cropper-canvas").append(a),this.$dragBox=i.find(".cropper-drag-box"),this.$cropBox=e=i.find(".cropper-crop-box"),this.$viewBox=i.find(".cropper-view-box"),this.$face=s=e.find(".cropper-face"),h.addClass(x).after(i),this.isImg||a.removeClass(w),this.initPreview(),this.bind(),o.aspectRatio=pt(o.aspectRatio)||NaN,o.autoCrop?(this.cropped=!0,o.modal&&this.$dragBox.addClass(v)):e.addClass(x),o.guides||e.find(".cropper-dashed").addClass(x),o.center||e.find(".cropper-center").addClass(x),o.cropBoxMovable&&s.addClass(C).data(j,G),o.highlight||s.addClass(b),o.background&&i.addClass($),o.cropBoxResizable||e.find(".cropper-line, .cropper-point").addClass(x),this.setDragMode(o.dragCrop?J:o.movable?V:it),this.render(),this.built=!0,this.setData(o.data),h.one(R,o.built),setTimeout(t.proxy(function(){this.trigger(R),this.complete=!0},this),0))},unbuild:function(){this.built&&(this.built=!1,this.initialImage=null,this.initialCanvas=null,this.initialCropBox=null,this.container=null,this.canvas=null,this.cropBox=null,this.unbind(),this.resetPreview(),this.$preview=null,this.$viewBox=null,this.$cropBox=null,this.$dragBox=null,this.$canvas=null,this.$container=null,this.$cropper.remove(),this.$cropper=null)}}),t.extend(ct,{render:function(){this.initContainer(),this.initCanvas(),this.initCropBox(),this.renderCanvas(),this.cropped&&this.renderCropBox()},initContainer:function(){var t=this.options,i=this.$element,e=this.$container,s=this.$cropper;s.addClass(x),i.removeClass(x),s.css(this.container={width:ht(e.width(),pt(t.minContainerWidth)||200),height:ht(e.height(),pt(t.minContainerHeight)||100)}),i.addClass(x),s.removeClass(x)},initCanvas:function(){var i=this.container,e=i.width,s=i.height,o=this.image,h=o.aspectRatio,a={aspectRatio:h,width:e,height:s};s*h>e?a.height=e/h:a.width=s*h,a.oldLeft=a.left=(e-a.width)/2,a.oldTop=a.top=(s-a.height)/2,this.canvas=a,this.limitCanvas(!0,!0),this.initialImage=t.extend({},o),this.initialCanvas=t.extend({},a)},limitCanvas:function(t,i){var e,s,o=this.options,h=o.strict,a=this.container,n=a.width,r=a.height,p=this.canvas,c=p.aspectRatio,d=this.cropBox,l=this.cropped&&d,g=this.initialCanvas||p;t&&(e=pt(o.minCanvasWidth)||0,s=pt(o.minCanvasHeight)||0,h&&(e?e=ht(e,l?d.width:g.width):s?s=ht(s,l?d.height:g.height):l&&(e=d.width,s=d.height,s*c>e?e=s*c:s=e/c)),e&&s?s*c>e?s=e/c:e=s*c:e?s=e/c:s&&(e=s*c),p.minWidth=e,p.minHeight=s,p.maxWidth=1/0,p.maxHeight=1/0),i&&(h?(p.minLeft=l?ot(d.left,d.left+d.width-p.width):ot(0,n-p.width),p.minTop=l?ot(d.top,d.top+d.height-p.height):ot(0,r-p.height),p.maxLeft=l?d.left:ht(0,n-p.width),p.maxTop=l?d.top:ht(0,r-p.height)):(p.minLeft=-p.width,p.minTop=-p.height,p.maxLeft=n,p.maxTop=r))},renderCanvas:function(t){var i,e,s=this.options,o=this.canvas,h=this.image;this.rotated&&(this.rotated=!1,e=c({width:h.width,height:h.height,degree:h.rotate}),i=e.width/e.height,i!==o.aspectRatio&&(o.left-=(e.width-o.width)/2,o.top-=(e.height-o.height)/2,o.width=e.width,o.height=e.height,o.aspectRatio=i,this.limitCanvas(!0,!1))),(o.width>o.maxWidth||o.width<o.minWidth)&&(o.left=o.oldLeft),(o.height>o.maxHeight||o.height<o.minHeight)&&(o.top=o.oldTop),o.width=ot(ht(o.width,o.minWidth),o.maxWidth),o.height=ot(ht(o.height,o.minHeight),o.maxHeight),this.limitCanvas(!1,!0),o.oldLeft=o.left=ot(ht(o.left,o.minLeft),o.maxLeft),o.oldTop=o.top=ot(ht(o.top,o.minTop),o.maxTop),this.$canvas.css({width:o.width,height:o.height,left:o.left,top:o.top}),this.renderImage(),this.cropped&&s.strict&&this.limitCropBox(!0,!0),t&&this.output()},renderImage:function(i){var e,s=this.canvas,o=this.image;o.rotate&&(e=c({width:s.width,height:s.height,degree:o.rotate,aspectRatio:o.aspectRatio},!0)),t.extend(o,e?{width:e.width,height:e.height,left:(s.width-e.width)/2,top:(s.height-e.height)/2}:{width:s.width,height:s.height,left:0,top:0}),this.$clone.css({width:o.width,height:o.height,marginLeft:o.left,marginTop:o.top,transform:p(o)}),i&&this.output()},initCropBox:function(){var i=this.options,e=this.canvas,s=i.aspectRatio,o=pt(i.autoCropArea)||.8,h={width:e.width,height:e.height};s&&(e.height*s>e.width?h.height=h.width/s:h.width=h.height*s),this.cropBox=h,this.limitCropBox(!0,!0),h.width=ot(ht(h.width,h.minWidth),h.maxWidth),h.height=ot(ht(h.height,h.minHeight),h.maxHeight),h.width=ht(h.minWidth,h.width*o),h.height=ht(h.minHeight,h.height*o),h.oldLeft=h.left=e.left+(e.width-h.width)/2,h.oldTop=h.top=e.top+(e.height-h.height)/2,this.initialCropBox=t.extend({},h)},limitCropBox:function(t,i){var e,s,o,h,a=this.options,n=a.strict,r=this.container,p=r.width,c=r.height,d=this.canvas,l=this.cropBox,g=a.aspectRatio;t&&(e=pt(a.minCropBoxWidth)||0,s=pt(a.minCropBoxHeight)||0,e=ot(e,p),s=ot(s,c),o=ot(p,n?d.width:p),h=ot(c,n?d.height:c),g&&(e&&s?s*g>e?s=e/g:e=s*g:e?s=e/g:s&&(e=s*g),h*g>o?h=o/g:o=h*g),l.minWidth=ot(e,o),l.minHeight=ot(s,h),l.maxWidth=o,l.maxHeight=h),i&&(n?(l.minLeft=ht(0,d.left),l.minTop=ht(0,d.top),l.maxLeft=ot(p,d.left+d.width)-l.width,l.maxTop=ot(c,d.top+d.height)-l.height):(l.minLeft=0,l.minTop=0,l.maxLeft=p-l.width,l.maxTop=c-l.height))},renderCropBox:function(){var t=this.options,i=this.container,e=i.width,s=i.height,o=this.cropBox;(o.width>o.maxWidth||o.width<o.minWidth)&&(o.left=o.oldLeft),(o.height>o.maxHeight||o.height<o.minHeight)&&(o.top=o.oldTop),o.width=ot(ht(o.width,o.minWidth),o.maxWidth),o.height=ot(ht(o.height,o.minHeight),o.maxHeight),this.limitCropBox(!1,!0),o.oldLeft=o.left=ot(ht(o.left,o.minLeft),o.maxLeft),o.oldTop=o.top=ot(ht(o.top,o.minTop),o.maxTop),t.movable&&t.cropBoxMovable&&this.$face.data(j,o.width===e&&o.height===s?V:G),this.$cropBox.css({width:o.width,height:o.height,left:o.left,top:o.top}),this.cropped&&t.strict&&this.limitCanvas(!0,!0),this.disabled||this.output()},output:function(){this.preview(),this.complete?this.trigger(E,this.getData()):this.built||this.$element.one(R,t.proxy(function(){this.trigger(E,this.getData())},this))}}),t.extend(ct,{initPreview:function(){var i=n(this.crossOrigin),e=this.url;this.$preview=t(this.options.preview),this.$viewBox.html("<img"+i+' src="'+e+'">'),this.$preview.each(function(){var s=t(this);s.data(S,{width:s.width(),height:s.height(),original:s.html()}),s.html("<img"+i+' src="'+e+'" style="display:block;width:100%;height:auto;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;image-orientation:0deg!important">')})},resetPreview:function(){this.$preview.each(function(){var i=t(this);i.html(i.data(S).original).removeData(S)})},preview:function(){var i=this.image,e=this.canvas,s=this.cropBox,o=s.width,h=s.height,a=i.width,n=i.height,r=s.left-e.left-i.left,c=s.top-e.top-i.top;this.cropped&&!this.disabled&&(this.$viewBox.find("img").css({width:a,height:n,marginLeft:-r,marginTop:-c,transform:p(i)}),this.$preview.each(function(){var e=t(this),s=e.data(S),d=s.width,l=s.height,g=d,u=l,f=1;o&&(f=d/o,u=h*f),h&&u>l&&(f=l/h,g=o*f,u=l),e.width(g).height(u).find("img").css({width:a*f,height:n*f,marginLeft:-r*f,marginTop:-c*f,transform:p(i)})}))}}),t.extend(ct,{bind:function(){var i=this.options,e=this.$element,s=this.$cropper;t.isFunction(i.cropstart)&&e.on(z,i.cropstart),t.isFunction(i.cropmove)&&e.on(I,i.cropmove),t.isFunction(i.cropend)&&e.on(P,i.cropend),t.isFunction(i.crop)&&e.on(E,i.crop),t.isFunction(i.zoom)&&e.on(F,i.zoom),s.on(D,t.proxy(this.cropStart,this)),i.zoomable&&i.mouseWheelZoom&&s.on(T,t.proxy(this.wheel,this)),i.doubleClickToggle&&s.on(k,t.proxy(this.dblclick,this)),u.on(Y,this._cropMove=o(this.cropMove,this)).on(X,this._cropEnd=o(this.cropEnd,this)),i.responsive&&g.on(L,this._resize=o(this.resize,this))},unbind:function(){var i=this.options,e=this.$element,s=this.$cropper;t.isFunction(i.cropstart)&&e.off(z,i.cropstart),t.isFunction(i.cropmove)&&e.off(I,i.cropmove),t.isFunction(i.cropend)&&e.off(P,i.cropend),t.isFunction(i.crop)&&e.off(E,i.crop),t.isFunction(i.zoom)&&e.off(F,i.zoom),s.off(D,this.cropStart),i.zoomable&&i.mouseWheelZoom&&s.off(T,this.wheel),i.doubleClickToggle&&s.off(k,this.dblclick),u.off(Y,this._cropMove).off(X,this._cropEnd),i.responsive&&g.off(L,this._resize)}}),t.extend(ct,{resize:function(){var i,e,s,o=this.$container,h=this.container;!this.disabled&&h&&(s=o.width()/h.width,(1!==s||o.height()!==h.height)&&(i=this.getCanvasData(),e=this.getCropBoxData(),this.render(),this.setCanvasData(t.each(i,function(t,e){i[t]=e*s})),this.setCropBoxData(t.each(e,function(t,i){e[t]=i*s}))))},dblclick:function(){this.disabled||(this.$dragBox.hasClass(y)?this.setDragMode(V):this.setDragMode(J))},wheel:function(t){var i=t.originalEvent,e=i,s=pt(this.options.wheelZoomRatio)||.1,o=1;this.disabled||(t.preventDefault(),e.deltaY?o=e.deltaY>0?1:-1:e.wheelDelta?o=-e.wheelDelta/120:e.detail&&(o=e.detail>0?1:-1),this.zoom(-o*s,i))},cropStart:function(i){var e,s,o=this.options,h=i.originalEvent,a=h&&h.touches,n=i;if(!this.disabled){if(a){if(e=a.length,e>1){if(!o.zoomable||!o.touchDragZoom||2!==e)return;n=a[1],this.startX2=n.pageX,this.startY2=n.pageY,s=tt}n=a[0]}if(s=s||t(n.target).data(j),O.test(s)){if(this.trigger(z,{originalEvent:h,action:s}).isDefaultPrevented())return;i.preventDefault(),this.action=s,this.cropping=!1,this.startX=n.pageX||h&&h.pageX,this.startY=n.pageY||h&&h.pageY,s===J&&(this.cropping=!0,this.$dragBox.addClass(v))}}},cropMove:function(t){var i,e=this.options,s=t.originalEvent,o=s&&s.touches,h=t,a=this.action;if(!this.disabled){if(o){if(i=o.length,i>1){if(!e.zoomable||!e.touchDragZoom||2!==i)return;h=o[1],this.endX2=h.pageX,this.endY2=h.pageY}h=o[0]}if(a){if(this.trigger(I,{originalEvent:s,action:a}).isDefaultPrevented())return;t.preventDefault(),this.endX=h.pageX||s&&s.pageX,this.endY=h.pageY||s&&s.pageY,this.change(h.shiftKey,a===tt?s:null)}}},cropEnd:function(t){var i=t.originalEvent,e=this.action;this.disabled||e&&(t.preventDefault(),this.cropping&&(this.cropping=!1,this.$dragBox.toggleClass(v,this.cropped&&this.options.modal)),this.action="",this.trigger(P,{originalEvent:i,action:e}))}}),t.extend(ct,{change:function(t,i){var e,s,o=this.options,h=o.aspectRatio,a=this.action,n=this.container,r=this.canvas,p=this.cropBox,c=p.width,d=p.height,l=p.left,g=p.top,u=l+c,f=g+d,m=0,v=0,w=n.width,b=n.height,C=!0;switch(!h&&t&&(h=c&&d?c/d:1),o.strict&&(m=p.minLeft,v=p.minTop,w=m+ot(n.width,r.width),b=v+ot(n.height,r.height)),s={x:this.endX-this.startX,y:this.endY-this.startY},h&&(s.X=s.y*h,s.Y=s.x/h),a){case G:l+=s.x,g+=s.y;break;case A:if(s.x>=0&&(u>=w||h&&(v>=g||f>=b))){C=!1;break}c+=s.x,h&&(d=c/h,g-=s.Y/2),0>c&&(a=N,c=0);break;case Z:if(s.y<=0&&(v>=g||h&&(m>=l||u>=w))){C=!1;break}d-=s.y,g+=s.y,h&&(c=d*h,l+=s.X/2),0>d&&(a=U,d=0);break;case N:if(s.x<=0&&(m>=l||h&&(v>=g||f>=b))){C=!1;break}c-=s.x,l+=s.x,h&&(d=c/h,g+=s.Y/2),0>c&&(a=A,c=0);break;case U:if(s.y>=0&&(f>=b||h&&(m>=l||u>=w))){C=!1;break}d+=s.y,h&&(c=d*h,l-=s.X/2),0>d&&(a=Z,d=0);break;case K:if(h){if(s.y<=0&&(v>=g||u>=w)){C=!1;break}d-=s.y,g+=s.y,c=d*h}else s.x>=0?w>u?c+=s.x:s.y<=0&&v>=g&&(C=!1):c+=s.x,s.y<=0?g>v&&(d-=s.y,g+=s.y):(d-=s.y,g+=s.y);0>c&&0>d?(a=q,d=0,c=0):0>c?(a=Q,c=0):0>d&&(a=_,d=0);break;case Q:if(h){if(s.y<=0&&(v>=g||m>=l)){C=!1;break}d-=s.y,g+=s.y,c=d*h,l+=s.X}else s.x<=0?l>m?(c-=s.x,l+=s.x):s.y<=0&&v>=g&&(C=!1):(c-=s.x,l+=s.x),s.y<=0?g>v&&(d-=s.y,g+=s.y):(d-=s.y,g+=s.y);0>c&&0>d?(a=_,d=0,c=0):0>c?(a=K,c=0):0>d&&(a=q,d=0);break;case q:if(h){if(s.x<=0&&(m>=l||f>=b)){C=!1;break}c-=s.x,l+=s.x,d=c/h}else s.x<=0?l>m?(c-=s.x,l+=s.x):s.y>=0&&f>=b&&(C=!1):(c-=s.x,l+=s.x),s.y>=0?b>f&&(d+=s.y):d+=s.y;0>c&&0>d?(a=K,d=0,c=0):0>c?(a=_,c=0):0>d&&(a=Q,d=0);break;case _:if(h){if(s.x>=0&&(u>=w||f>=b)){C=!1;break}c+=s.x,d=c/h}else s.x>=0?w>u?c+=s.x:s.y>=0&&f>=b&&(C=!1):c+=s.x,s.y>=0?b>f&&(d+=s.y):d+=s.y;0>c&&0>d?(a=Q,d=0,c=0):0>c?(a=q,c=0):0>d&&(a=K,d=0);break;case V:this.move(s.x,s.y),C=!1;break;case tt:this.zoom(function(t,i,e,s){var o=st(t*t+i*i),h=st(e*e+s*s);return(h-o)/o}(at(this.startX-this.startX2),at(this.startY-this.startY2),at(this.endX-this.endX2),at(this.endY-this.endY2)),i),this.startX2=this.endX2,this.startY2=this.endY2,C=!1;break;case J:s.x&&s.y&&(e=this.$cropper.offset(),l=this.startX-e.left,g=this.startY-e.top,c=p.minWidth,d=p.minHeight,s.x>0?s.y>0?a=_:(a=K,g-=d):s.y>0?(a=q,l-=c):(a=Q,l-=c,g-=d),this.cropped||(this.cropped=!0,this.$cropBox.removeClass(x)))}C&&(p.width=c,p.height=d,p.left=l,p.top=g,this.action=a,this.renderCropBox()),this.startX=this.endX,this.startY=this.endY}}),t.extend(ct,{crop:function(){this.built&&!this.disabled&&(this.cropped||(this.cropped=!0,this.limitCropBox(!0,!0),this.options.modal&&this.$dragBox.addClass(v),this.$cropBox.removeClass(x)),this.setCropBoxData(this.initialCropBox))},reset:function(){this.built&&!this.disabled&&(this.image=t.extend({},this.initialImage),this.canvas=t.extend({},this.initialCanvas),this.cropBox=t.extend({},this.initialCropBox),this.renderCanvas(),this.cropped&&this.renderCropBox())},clear:function(){this.cropped&&!this.disabled&&(t.extend(this.cropBox,{left:0,top:0,width:0,height:0}),this.cropped=!1,this.renderCropBox(),this.limitCanvas(!0,!0),this.renderCanvas(),this.$dragBox.removeClass(v),this.$cropBox.addClass(x))},replace:function(t){!this.disabled&&t&&(this.isImg&&(this.replaced=!0,this.$element.attr("src",t)),this.options.data=null,this.load(t))},enable:function(){this.built&&(this.disabled=!1,this.$cropper.removeClass(B))},disable:function(){this.built&&(this.disabled=!0,this.$cropper.addClass(B))},destroy:function(){var t=this.$element;this.ready?(this.isImg&&this.replaced&&t.attr("src",this.originalUrl),this.unbuild(),t.removeClass(x)):this.isImg?t.off(M,this.start):this.$clone&&this.$clone.remove(),t.removeData(m)},move:function(t,s){var o=this.canvas;e(s)&&(s=t),t=pt(t),s=pt(s),this.built&&!this.disabled&&this.options.movable&&(o.left+=i(t)?t:0,o.top+=i(s)?s:0,this.renderCanvas(!0))},zoom:function(t,i){var e,s,o=this.canvas;if(t=pt(t),t&&this.built&&!this.disabled&&this.options.zoomable){if(this.trigger(F,{originalEvent:i,ratio:t}).isDefaultPrevented())return;t=0>t?1/(1-t):1+t,e=o.width*t,s=o.height*t,o.left-=(e-o.width)/2,o.top-=(s-o.height)/2,o.width=e,o.height=s,this.renderCanvas(!0),this.setDragMode(V)}},rotate:function(t){var i=this.image,e=i.rotate||0;t=pt(t)||0,this.built&&!this.disabled&&this.options.rotatable&&(i.rotate=(e+t)%360,this.rotated=!0,this.renderCanvas(!0))},scale:function(t,s){var o=this.image;e(s)&&(s=t),t=pt(t),s=pt(s),this.built&&!this.disabled&&this.options.scalable&&(o.scaleX=i(t)?t:1,o.scaleY=i(s)?s:1,this.renderImage(!0))},getData:function(i){var e,s,o=this.options,h=this.image,a=this.canvas,n=this.cropBox;return this.built&&this.cropped?(s={x:n.left-a.left,y:n.top-a.top,width:n.width,height:n.height},e=h.width/h.naturalWidth,t.each(s,function(t,o){o/=e,s[t]=i?Math.round(o):o})):s={x:0,y:0,width:0,height:0},o.rotatable&&(s.rotate=h.rotate||0),o.scalable&&(s.scaleX=h.scaleX||1,s.scaleY=h.scaleY||1),s},setData:function(e){var s,o,h,a=this.options,n=this.image,r=this.canvas,p={};t.isFunction(e)&&(e=e.call(this.element)),this.built&&!this.disabled&&t.isPlainObject(e)&&(a.rotatable&&i(e.rotate)&&e.rotate!==n.rotate&&(n.rotate=e.rotate,this.rotated=s=!0),a.scalable&&(i(e.scaleX)&&e.scaleX!==n.scaleX&&(n.scaleX=e.scaleX,o=!0),i(e.scaleY)&&e.scaleY!==n.scaleY&&(n.scaleY=e.scaleY,o=!0)),s?this.renderCanvas():o&&this.renderImage(),h=n.width/n.naturalWidth,i(e.x)&&(p.left=e.x*h+r.left),i(e.y)&&(p.top=e.y*h+r.top),i(e.width)&&(p.width=e.width*h),i(e.height)&&(p.height=e.height*h),this.setCropBoxData(p))},getContainerData:function(){return this.built?this.container:{}},getImageData:function(){return this.ready?this.image:{}},getCanvasData:function(){var t,i=this.canvas;return this.built&&(t={left:i.left,top:i.top,width:i.width,height:i.height}),t||{}},setCanvasData:function(e){var s=this.canvas,o=s.aspectRatio;t.isFunction(e)&&(e=e.call(this.$element)),this.built&&!this.disabled&&t.isPlainObject(e)&&(i(e.left)&&(s.left=e.left),i(e.top)&&(s.top=e.top),i(e.width)?(s.width=e.width,s.height=e.width/o):i(e.height)&&(s.height=e.height,s.width=e.height*o),this.renderCanvas(!0))},getCropBoxData:function(){var t,i=this.cropBox;return this.built&&this.cropped&&(t={left:i.left,top:i.top,width:i.width,height:i.height}),t||{}},setCropBoxData:function(e){var s,o,h=this.cropBox,a=this.options.aspectRatio;t.isFunction(e)&&(e=e.call(this.$element)),this.built&&this.cropped&&!this.disabled&&t.isPlainObject(e)&&(i(e.left)&&(h.left=e.left),i(e.top)&&(h.top=e.top),i(e.width)&&e.width!==h.width&&(s=!0,h.width=e.width),i(e.height)&&e.height!==h.height&&(o=!0,h.height=e.height),a&&(s?h.height=h.width/a:o&&(h.width=h.height*a)),this.renderCropBox())},getCroppedCanvas:function(i){var e,s,o,h,a,n,r,p,c,l,g;return this.built&&this.cropped&&et?(t.isPlainObject(i)||(i={}),g=this.getData(),e=g.width,s=g.height,p=e/s,t.isPlainObject(i)&&(a=i.width,n=i.height,a?(n=a/p,r=a/e):n&&(a=n*p,r=n/s)),o=a||e,h=n||s,c=t("<canvas>")[0],c.width=o,c.height=h,l=c.getContext("2d"),i.fillColor&&(l.fillStyle=i.fillColor,l.fillRect(0,0,o,h)),l.drawImage.apply(l,function(){var t,i,o,h,a,n,p=d(this.$clone[0],this.image),c=p.width,l=p.height,u=[p],f=g.x,m=g.y;return-e>=f||f>c?f=t=o=a=0:0>=f?(o=-f,f=0,t=a=ot(c,e+f)):c>=f&&(o=0,t=a=ot(e,c-f)),0>=t||-s>=m||m>l?m=i=h=n=0:0>=m?(h=-m,m=0,i=n=ot(l,s+m)):l>=m&&(h=0,i=n=ot(s,l-m)),u.push(f,m,t,i),r&&(o*=r,h*=r,a*=r,n*=r),a>0&&n>0&&u.push(o,h,a,n),u}.call(this)),c):void 0},setAspectRatio:function(t){var i=this.options;this.disabled||e(t)||(i.aspectRatio=pt(t)||NaN,this.built&&(this.initCropBox(),this.cropped&&this.renderCropBox()))},setDragMode:function(t){var i,e,s=this.options;this.ready&&!this.disabled&&(i=s.dragCrop&&t===J,e=s.movable&&t===V,t=i||e?t:it,this.$dragBox.data(j,t).toggleClass(y,i).toggleClass(C,e),s.cropBoxMovable||this.$face.data(j,t).toggleClass(y,i).toggleClass(C,e))}}),t.extend(l.prototype,ct),l.DEFAULTS={aspectRatio:NaN,data:null,preview:"",strict:!0,responsive:!0,checkImageOrigin:!0,modal:!0,guides:!0,center:!0,highlight:!0,background:!0,autoCrop:!0,autoCropArea:.8,dragCrop:!0,movable:!0,rotatable:!0,scalable:!0,zoomable:!0,mouseWheelZoom:!0,wheelZoomRatio:.1,touchDragZoom:!0,cropBoxMovable:!0,cropBoxResizable:!0,doubleClickToggle:!0,minCanvasWidth:0,minCanvasHeight:0,minCropBoxWidth:0,minCropBoxHeight:0,minContainerWidth:200,minContainerHeight:100,build:null,built:null,cropstart:null,cropmove:null,cropend:null,crop:null,zoom:null},l.setDefaults=function(i){t.extend(l.DEFAULTS,i)},l.TEMPLATE='<div class="cropper-container"><div class="cropper-canvas"></div><div class="cropper-drag-box"></div><div class="cropper-crop-box"><span class="cropper-view-box"></span><span class="cropper-dashed dashed-h"></span><span class="cropper-dashed dashed-v"></span><span class="cropper-center"></span><span class="cropper-face"></span><span class="cropper-line line-e" data-action="e"></span><span class="cropper-line line-n" data-action="n"></span><span class="cropper-line line-w" data-action="w"></span><span class="cropper-line line-s" data-action="s"></span><span class="cropper-point point-e" data-action="e"></span><span class="cropper-point point-n" data-action="n"></span><span class="cropper-point point-w" data-action="w"></span><span class="cropper-point point-s" data-action="s"></span><span class="cropper-point point-ne" data-action="ne"></span><span class="cropper-point point-nw" data-action="nw"></span><span class="cropper-point point-sw" data-action="sw"></span><span class="cropper-point point-se" data-action="se"></span></div></div>',l.other=t.fn.cropper,t.fn.cropper=function(i){var o,h=s(arguments,1);return this.each(function(){var e,s=t(this),a=s.data(m);if(!a){if(/destroy/.test(i))return;s.data(m,a=new l(this,i))}"string"==typeof i&&t.isFunction(e=a[i])&&(o=e.apply(a,h))}),e(o)?this:o},t.fn.cropper.Constructor=l,t.fn.cropper.setDefaults=l.setDefaults,t.fn.cropper.noConflict=function(){return t.fn.cropper=l.other,this}}); \ No newline at end of file