|
@@ -0,0 +1,778 @@
|
|
|
+/*!
|
|
|
+ * Cropper v0.3.2
|
|
|
+ * https://github.com/fengyuanchen/cropper
|
|
|
+ *
|
|
|
+ * Copyright 2014 Fengyuan Chen
|
|
|
+ * Released under the MIT license
|
|
|
+ */
|
|
|
+
|
|
|
+(function(factory) {
|
|
|
+ if (typeof define === "function" && define.amd) {
|
|
|
+ // AMD. Register as anonymous module.
|
|
|
+ define(["jquery"], factory);
|
|
|
+ } else {
|
|
|
+ // Browser globals.
|
|
|
+ factory(jQuery);
|
|
|
+ }
|
|
|
+}(function($) {
|
|
|
+
|
|
|
+ "use strict";
|
|
|
+
|
|
|
+ var $window = $(window),
|
|
|
+ Cropper = function(element, options) {
|
|
|
+ options = $.isPlainObject(options) ? options : {};
|
|
|
+ this.$image = $(element);
|
|
|
+ this.defaults = $.extend({}, Cropper.defaults, this.$image.data(), options);
|
|
|
+ this.init();
|
|
|
+ };
|
|
|
+
|
|
|
+ Cropper.prototype = {
|
|
|
+ construstor: Cropper,
|
|
|
+
|
|
|
+ init: function() {
|
|
|
+ this.setAspectRatio(this.defaults.aspectRatio);
|
|
|
+ this.render();
|
|
|
+ },
|
|
|
+
|
|
|
+ render: function(callback) {
|
|
|
+ var that = this,
|
|
|
+ $image = this.$image,
|
|
|
+ $clone,
|
|
|
+ src;
|
|
|
+
|
|
|
+ if (this.active) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.$clone) {
|
|
|
+ this.$clone.remove(); // Remove the old clone
|
|
|
+ }
|
|
|
+
|
|
|
+ src = $image.attr("src"); // Don't use "prop"
|
|
|
+ $clone = $('<img src="' + src + '">');
|
|
|
+
|
|
|
+ $clone.on("load", function() {
|
|
|
+ var image;
|
|
|
+
|
|
|
+ $clone.off("load");
|
|
|
+
|
|
|
+ if (this.naturalWidth && this.naturalHeight) {
|
|
|
+ image = {
|
|
|
+ naturalHeight: this.naturalHeight,
|
|
|
+ naturalWidth: this.naturalWidth
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ Cropper.fn.size($clone, {
|
|
|
+ height: "auto",
|
|
|
+ width: "auto"
|
|
|
+ });
|
|
|
+
|
|
|
+ image = Cropper.fn.size($clone);
|
|
|
+ image = {
|
|
|
+ naturalHeight: image.height,
|
|
|
+ naturalWidth: image.width
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ Cropper.fn.size($clone, {
|
|
|
+ height: "100%",
|
|
|
+ width: "100%"
|
|
|
+ });
|
|
|
+
|
|
|
+ image.aspectRatio = image.naturalWidth / image.naturalHeight;
|
|
|
+ that.src = src;
|
|
|
+ that.image = image;
|
|
|
+ that.active = true;
|
|
|
+ that.createCropper();
|
|
|
+ });
|
|
|
+
|
|
|
+ if ($.isFunction(callback)) {
|
|
|
+ $image.on("ready.cropper", callback);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$clone = $clone;
|
|
|
+ $image.after($clone);
|
|
|
+ },
|
|
|
+
|
|
|
+ unrender: function() {
|
|
|
+ if (this.active) {
|
|
|
+ this.active = false;
|
|
|
+ this.removeCropper();
|
|
|
+ this.src = "";
|
|
|
+ this.image = null;
|
|
|
+ this.cropper = null;
|
|
|
+ this.dragger = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ rerender: function() {
|
|
|
+ this.unrender();
|
|
|
+ this.render();
|
|
|
+ },
|
|
|
+
|
|
|
+ resize: function() {
|
|
|
+ clearTimeout(this.resizing);
|
|
|
+ this.resizing = setTimeout($.proxy(this.rerender, this), 200);
|
|
|
+ },
|
|
|
+
|
|
|
+ createCropper: function() {
|
|
|
+ this.$cropper = $(Cropper.template);
|
|
|
+ this.$dragger = this.$cropper.find(".cropper-dragger");
|
|
|
+ Cropper.fn.toggle(this.$image);
|
|
|
+ this.$image.after(this.$cropper);
|
|
|
+ this.$cropper.prepend(this.$clone);
|
|
|
+
|
|
|
+ if (!this.defaults.modal) {
|
|
|
+ Cropper.fn.toggle(this.$cropper.find(".cropper-modal"));
|
|
|
+ }
|
|
|
+
|
|
|
+ this.setPreview();
|
|
|
+ this.addListener();
|
|
|
+ },
|
|
|
+
|
|
|
+ removeCropper: function() {
|
|
|
+ this.removeListener();
|
|
|
+ this.$preview = null;
|
|
|
+ this.$clone.remove();
|
|
|
+ this.$clone = null;
|
|
|
+ this.$dragger = null;
|
|
|
+ this.$cropper.remove();
|
|
|
+ this.$cropper = null;
|
|
|
+ Cropper.fn.toggle(this.$image);
|
|
|
+ },
|
|
|
+
|
|
|
+ addListener: function() {
|
|
|
+ this.$cropper.bind("mousedown touchstart", $.proxy(this.dragstart, this));
|
|
|
+ this.$cropper.bind("mousemove touchmove", $.proxy(this.dragmove, this));
|
|
|
+ this.$cropper.bind("mouseup mouseleave touchend touchleave", $.proxy(this.dragend, this));
|
|
|
+ $window.on("resize", $.proxy(this.resize, this));
|
|
|
+ },
|
|
|
+
|
|
|
+ removeListener: function() {
|
|
|
+ this.$cropper.unbind("mousedown touchstart", this.dragstart);
|
|
|
+ this.$cropper.unbind("mousemove touchmove", this.dragmove);
|
|
|
+ this.$cropper.unbind("mouseup mouseleave touchend touchleave", this.dragend);
|
|
|
+ $window.off("resize", this.resize);
|
|
|
+ },
|
|
|
+
|
|
|
+ setPreview: function() {
|
|
|
+ var preview = this.defaults.preview;
|
|
|
+
|
|
|
+ this.$preview = this.$cropper.find(".cropper-preview");
|
|
|
+
|
|
|
+ if (typeof preview === "string" && preview.length > 0) {
|
|
|
+ this.$preview = this.$preview.add(preview);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$preview.html('<img src="' + this.src + '">');
|
|
|
+ this.setCropper();
|
|
|
+ },
|
|
|
+
|
|
|
+ setCropper: function() {
|
|
|
+ var $container = this.$image.parent(),
|
|
|
+ container = Cropper.fn.size($container),
|
|
|
+ image = this.image,
|
|
|
+ cropper;
|
|
|
+
|
|
|
+ if (((image.naturalWidth * container.height / image.naturalHeight) - container.width) >= 0) {
|
|
|
+ cropper = {
|
|
|
+ height: container.width / image.aspectRatio,
|
|
|
+ width: container.width,
|
|
|
+ left: 0
|
|
|
+ };
|
|
|
+
|
|
|
+ cropper.top = (container.height - cropper.height) / 2;
|
|
|
+ } else {
|
|
|
+ cropper = {
|
|
|
+ height: container.height,
|
|
|
+ width: container.height * image.aspectRatio,
|
|
|
+ top: 0
|
|
|
+ };
|
|
|
+
|
|
|
+ cropper.left = (container.width - cropper.width) / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ $.each(cropper, function(i, n) {
|
|
|
+ cropper[i] = Math.round(n);
|
|
|
+ });
|
|
|
+
|
|
|
+ image.height = cropper.height;
|
|
|
+ image.width = cropper.width;
|
|
|
+ image.ratio = image.width / image.naturalWidth;
|
|
|
+
|
|
|
+ Cropper.fn.position($container);
|
|
|
+ this.$cropper.css({
|
|
|
+ height: cropper.height,
|
|
|
+ left: cropper.left,
|
|
|
+ top: cropper.top,
|
|
|
+ width: cropper.width
|
|
|
+ });
|
|
|
+
|
|
|
+ this.cropper = cropper;
|
|
|
+ this.setDragger();
|
|
|
+ },
|
|
|
+
|
|
|
+ setDragger: function() {
|
|
|
+ var cropper = this.cropper,
|
|
|
+ // If not set, use the original aspect ratio of the image.
|
|
|
+ aspectRatio = this.defaults.aspectRatio || this.image.aspectRatio,
|
|
|
+ dragger;
|
|
|
+
|
|
|
+ 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,
|
|
|
+ maxHeight: cropper.height,
|
|
|
+ maxWidth: cropper.height * aspectRatio
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ dragger.height *= 0.8;
|
|
|
+ dragger.width *= 0.8;
|
|
|
+
|
|
|
+ dragger.left = (cropper.width - dragger.width) / 2;
|
|
|
+ dragger.top = (cropper.height - dragger.height) / 2;
|
|
|
+
|
|
|
+ this.dragger = Cropper.fn.round(dragger);
|
|
|
+ this.setData(this.defaults.data);
|
|
|
+ this.$image.trigger("ready.cropper").off("ready.cropper");
|
|
|
+ },
|
|
|
+
|
|
|
+ resetDragger: function() {
|
|
|
+ var dragger = this.dragger,
|
|
|
+ cropper = this.cropper;
|
|
|
+
|
|
|
+ dragger.width = dragger.width > dragger.maxWidth ? dragger.maxWidth : Math.abs(dragger.width);
|
|
|
+ dragger.height = dragger.height > dragger.maxHeight ? dragger.maxHeight : Math.abs(dragger.height);
|
|
|
+
|
|
|
+ dragger.maxLeft = cropper.width - dragger.width;
|
|
|
+ dragger.maxTop = cropper.height - dragger.height;
|
|
|
+
|
|
|
+ dragger.left = dragger.left < 0 ? 0 : dragger.left > dragger.maxLeft ? dragger.maxLeft : dragger.left;
|
|
|
+ dragger.top = dragger.top < 0 ? 0 : dragger.top > dragger.maxTop ? dragger.maxTop : dragger.top;
|
|
|
+
|
|
|
+ dragger = Cropper.fn.round(dragger);
|
|
|
+
|
|
|
+ this.$dragger.css({
|
|
|
+ height: dragger.height,
|
|
|
+ left: dragger.left,
|
|
|
+ top: dragger.top,
|
|
|
+ width: dragger.width
|
|
|
+ });
|
|
|
+
|
|
|
+ this.dragger = dragger;
|
|
|
+ this.preview();
|
|
|
+ this.output();
|
|
|
+ },
|
|
|
+
|
|
|
+ dragging: function() {
|
|
|
+ var direction = this.direction,
|
|
|
+ dragger = this.dragger,
|
|
|
+ aspectRatio = this.defaults.aspectRatio,
|
|
|
+ range = {
|
|
|
+ x: this.endX - this.startX,
|
|
|
+ y: this.endY - this.startY
|
|
|
+ };
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ range.X = range.y * aspectRatio;
|
|
|
+ range.Y = range.x / aspectRatio;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (direction) {
|
|
|
+
|
|
|
+ // dragging
|
|
|
+ case "e":
|
|
|
+ dragger.width += range.x;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.height = dragger.width / aspectRatio;
|
|
|
+ dragger.top -= range.Y / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.width < 0) {
|
|
|
+ this.direction = "w";
|
|
|
+ dragger.width = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "n":
|
|
|
+ dragger.height -= range.y;
|
|
|
+ dragger.top += range.y;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.width = dragger.height * aspectRatio;
|
|
|
+ dragger.left += range.X / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.height < 0) {
|
|
|
+ this.direction = "s";
|
|
|
+ dragger.height = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "w":
|
|
|
+ dragger.width -= range.x;
|
|
|
+ dragger.left += range.x;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.height = dragger.width / aspectRatio;
|
|
|
+ dragger.top += range.Y / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.width < 0) {
|
|
|
+ this.direction = "e";
|
|
|
+ dragger.width = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "s":
|
|
|
+ dragger.height += range.y;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.width = dragger.height * aspectRatio;
|
|
|
+ dragger.left -= range.X / 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.height < 0) {
|
|
|
+ this.direction = "n";
|
|
|
+ dragger.height = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "ne":
|
|
|
+ dragger.height -= range.y;
|
|
|
+ dragger.top += range.y;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.width = dragger.height * aspectRatio;
|
|
|
+ } else {
|
|
|
+ dragger.width += range.x;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.height < 0) {
|
|
|
+ this.direction = "sw";
|
|
|
+ dragger.height = 0;
|
|
|
+ dragger.width = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "nw":
|
|
|
+ dragger.height -= range.y;
|
|
|
+ dragger.top += range.y;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.width = dragger.height * aspectRatio;
|
|
|
+ dragger.left += range.X;
|
|
|
+ } else {
|
|
|
+ dragger.width -= range.x;
|
|
|
+ dragger.left += range.x;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.height < 0) {
|
|
|
+ this.direction = "se";
|
|
|
+ dragger.height = 0;
|
|
|
+ dragger.width = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "sw":
|
|
|
+ dragger.width -= range.x;
|
|
|
+ dragger.left += range.x;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.height = dragger.width / aspectRatio;
|
|
|
+ } else {
|
|
|
+ dragger.height += range.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.width < 0) {
|
|
|
+ this.direction = "ne";
|
|
|
+ dragger.height = 0;
|
|
|
+ dragger.width = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "se":
|
|
|
+ dragger.width += range.x;
|
|
|
+
|
|
|
+ if (aspectRatio) {
|
|
|
+ dragger.height = dragger.width / aspectRatio;
|
|
|
+ } else {
|
|
|
+ dragger.height += range.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dragger.width < 0) {
|
|
|
+ this.direction = "nw";
|
|
|
+ dragger.height = 0;
|
|
|
+ dragger.width = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ // moving
|
|
|
+ default:
|
|
|
+ dragger.left += range.x;
|
|
|
+ dragger.top += range.y;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.resetDragger();
|
|
|
+ this.startX = this.endX;
|
|
|
+ this.startY = this.endY;
|
|
|
+ },
|
|
|
+
|
|
|
+ output: function() {
|
|
|
+ this.defaults.done(this.getData());
|
|
|
+ },
|
|
|
+
|
|
|
+ preview: function() {
|
|
|
+ var that = this,
|
|
|
+ cropper = that.cropper,
|
|
|
+ dragger = that.dragger;
|
|
|
+
|
|
|
+ this.$preview.each(function() {
|
|
|
+ var $this = $(this),
|
|
|
+ ratio = $this.outerWidth() / dragger.width,
|
|
|
+ styles = {
|
|
|
+ height: cropper.height,
|
|
|
+ marginLeft: - dragger.left,
|
|
|
+ marginTop: - dragger.top,
|
|
|
+ width: cropper.width
|
|
|
+ };
|
|
|
+
|
|
|
+ $this.css({overflow: "hidden"});
|
|
|
+ $this.find("img").css(Cropper.fn.round(styles, function(n) {
|
|
|
+ return n * ratio;
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // Public methods
|
|
|
+
|
|
|
+ enable: function(callback) {
|
|
|
+ this.render(callback);
|
|
|
+ },
|
|
|
+
|
|
|
+ disable: function() {
|
|
|
+ this.unrender();
|
|
|
+ },
|
|
|
+
|
|
|
+ setAspectRatio: function(aspectRatio) {
|
|
|
+ if (aspectRatio === "auto" || ($.isNumeric(aspectRatio) && aspectRatio > 0)) {
|
|
|
+ this.defaults.aspectRatio = aspectRatio === "auto" ? NaN : aspectRatio;
|
|
|
+
|
|
|
+ if (this.active) {
|
|
|
+ this.setDragger();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ setData: function(data) {
|
|
|
+ var cropper = this.cropper,
|
|
|
+ dragger = this.dragger,
|
|
|
+ aspectRatio = this.defaults.aspectRatio,
|
|
|
+ isNumber = function(n) {
|
|
|
+ return typeof n === "number";
|
|
|
+ };
|
|
|
+
|
|
|
+ if (!this.active) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($.isPlainObject(data) && !$.isEmptyObject(data)) {
|
|
|
+ data = Cropper.fn.transformData(data, this.image.ratio);
|
|
|
+
|
|
|
+ if (isNumber(data.x1) && data.x1 <= cropper.width) {
|
|
|
+ dragger.left = data.x1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isNumber(data.y1) && data.y1 <= cropper.height) {
|
|
|
+ dragger.top = data.y1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (aspectRatio){
|
|
|
+ if (isNumber(data.width) && data.width <= cropper.width) {
|
|
|
+ dragger.width = data.width;
|
|
|
+ dragger.height = dragger.width / aspectRatio;
|
|
|
+ } else if (isNumber(data.height) && data.height <= cropper.height) {
|
|
|
+ dragger.height = data.height;
|
|
|
+ dragger.width = dragger.height * aspectRatio;
|
|
|
+ } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
|
|
|
+ dragger.width = data.x2 - dragger.left;
|
|
|
+ dragger.height = dragger.width / aspectRatio;
|
|
|
+ } else if (isNumber(data.y2) && data.y2 <= cropper.height) {
|
|
|
+ dragger.height = data.y2 - dragger.top;
|
|
|
+ dragger.width = dragger.height * aspectRatio;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (isNumber(data.width) && data.width <= cropper.width) {
|
|
|
+ dragger.width = data.width;
|
|
|
+ } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
|
|
|
+ dragger.width = data.x2 - dragger.left;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isNumber(data.height) && data.height <= cropper.height) {
|
|
|
+ dragger.height = data.height;
|
|
|
+ } else if (isNumber(data.y2) && data.height <= cropper.height) {
|
|
|
+ dragger.height = data.y2 - dragger.top;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.dragger = dragger;
|
|
|
+ this.resetDragger();
|
|
|
+ },
|
|
|
+
|
|
|
+ getData: function() {
|
|
|
+ var dragger = this.dragger,
|
|
|
+ data = {};
|
|
|
+
|
|
|
+ if (this.active) {
|
|
|
+ data = {
|
|
|
+ x1: dragger.left,
|
|
|
+ y1: dragger.top,
|
|
|
+ width: dragger.width,
|
|
|
+ height: dragger.height,
|
|
|
+ x2: dragger.left + dragger.width,
|
|
|
+ y2: dragger.top + dragger.height
|
|
|
+ };
|
|
|
+
|
|
|
+ data = Cropper.fn.transformData(data, (1 / this.image.ratio));
|
|
|
+ }
|
|
|
+
|
|
|
+ return data;
|
|
|
+ },
|
|
|
+
|
|
|
+ setImgSrc: function(src) {
|
|
|
+ if (typeof src === "string" && src.length > 0 && src !== this.src) {
|
|
|
+ this.$image.attr("src", src);
|
|
|
+ this.rerender();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ getImgInfo: function() {
|
|
|
+ return this.image || {};
|
|
|
+ },
|
|
|
+
|
|
|
+ // Public events
|
|
|
+
|
|
|
+ dragstart: function(event) {
|
|
|
+ var touches = Cropper.fn.getOriginalEvent(event).touches,
|
|
|
+ e = event,
|
|
|
+ touching,
|
|
|
+ direction;
|
|
|
+
|
|
|
+ if (touches && touches.length === 1) {
|
|
|
+ e = touches[0];
|
|
|
+ this.touchId = e.identifier;
|
|
|
+ touching = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ direction = $(e.target).data().direction;
|
|
|
+
|
|
|
+ if (Cropper.fn.isDirection(direction)) {
|
|
|
+ this.startX = e.pageX;
|
|
|
+ this.startY = e.pageY;
|
|
|
+ this.direction = direction;
|
|
|
+ this.$image.trigger("dragstart");
|
|
|
+ touching && event.preventDefault();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ dragmove: function(event) {
|
|
|
+ var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
|
|
|
+ e = event,
|
|
|
+ touching;
|
|
|
+
|
|
|
+ if (touches && touches.length === 1) {
|
|
|
+ e = touches[0];
|
|
|
+ touching = true;
|
|
|
+
|
|
|
+ if (e.identifier !== this.touchId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.direction) {
|
|
|
+ this.$image.trigger("dragmove");
|
|
|
+ touching && event.preventDefault();
|
|
|
+ this.endX = e.pageX;
|
|
|
+ this.endY = e.pageY;
|
|
|
+ this.dragging();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ dragend: function(event) {
|
|
|
+ var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
|
|
|
+ e = event,
|
|
|
+ touching;
|
|
|
+
|
|
|
+ if (touches && touches.length === 1) {
|
|
|
+ e = touches[0];
|
|
|
+ touching = true;
|
|
|
+
|
|
|
+ if (e.identifier !== this.touchId) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.direction) {
|
|
|
+ this.direction = "";
|
|
|
+ this.$image.trigger("dragend");
|
|
|
+ touching && event.preventDefault();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // Common methods
|
|
|
+ Cropper.fn = {
|
|
|
+ toggle: function($e) {
|
|
|
+ $e.toggleClass("cropper-hidden");
|
|
|
+ },
|
|
|
+
|
|
|
+ position: function($e, option) {
|
|
|
+ var position = $e.css("position");
|
|
|
+
|
|
|
+ if (position === "static") {
|
|
|
+ $e.css("position", option || "relative");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ size: function($e, options) {
|
|
|
+ if ($.isPlainObject(options)) {
|
|
|
+ $e.css(options);
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ height: $e.height(),
|
|
|
+ width: $e.width()
|
|
|
+ };
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ round: function(data, fn) {
|
|
|
+ var value,
|
|
|
+ i;
|
|
|
+
|
|
|
+ for (i in data) {
|
|
|
+ value = data[i];
|
|
|
+
|
|
|
+ if (data.hasOwnProperty(i) && typeof value === "number") {
|
|
|
+ data[i] = Math.round($.isFunction(fn) ? fn(value) : value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return data;
|
|
|
+ },
|
|
|
+
|
|
|
+ transformData: function(data, ratio) {
|
|
|
+ var that = this,
|
|
|
+ result = {};
|
|
|
+
|
|
|
+ $.each(data, function(i, n) {
|
|
|
+ if (that.isDataOption(i) && $.isNumeric(n) && n >= 0) {
|
|
|
+ result[i] = Math.round(n * ratio);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return result;
|
|
|
+ },
|
|
|
+
|
|
|
+ getOriginalEvent: function(event) {
|
|
|
+ if (event && typeof event.originalEvent !== "undefined") {
|
|
|
+ event = event.originalEvent;
|
|
|
+ }
|
|
|
+
|
|
|
+ return event;
|
|
|
+ },
|
|
|
+
|
|
|
+ isDataOption: function(s) {
|
|
|
+ return /^(x1|y1|x2|y2|width|height)$/i.test(s);
|
|
|
+ },
|
|
|
+
|
|
|
+ isDirection: function(s) {
|
|
|
+ return /^(\*|e|n|w|s|ne|nw|sw|se)$/i.test(s);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ Cropper.template = [
|
|
|
+ '<div class="cropper-container">',
|
|
|
+ '<div class="cropper-modal"></div>',
|
|
|
+ '<div class="cropper-dragger">',
|
|
|
+ '<span class="cropper-preview"></span>',
|
|
|
+ '<span class="cropper-dashed dashed-h"></span>',
|
|
|
+ '<span class="cropper-dashed dashed-v"></span>',
|
|
|
+ '<span class="cropper-face" data-direction="*"></span>',
|
|
|
+ '<span class="cropper-line line-e" data-direction="e"></span>',
|
|
|
+ '<span class="cropper-line line-n" data-direction="n"></span>',
|
|
|
+ '<span class="cropper-line line-w" data-direction="w"></span>',
|
|
|
+ '<span class="cropper-line line-s" data-direction="s"></span>',
|
|
|
+ '<span class="cropper-point point-e" data-direction="e"></span>',
|
|
|
+ '<span class="cropper-point point-n" data-direction="n"></span>',
|
|
|
+ '<span class="cropper-point point-w" data-direction="w"></span>',
|
|
|
+ '<span class="cropper-point point-s" data-direction="s"></span>',
|
|
|
+ '<span class="cropper-point point-ne" data-direction="ne"></span>',
|
|
|
+ '<span class="cropper-point point-nw" data-direction="nw"></span>',
|
|
|
+ '<span class="cropper-point point-sw" data-direction="sw"></span>',
|
|
|
+ '<span class="cropper-point point-se" data-direction="se"></span>',
|
|
|
+ '</div>',
|
|
|
+ '</div>'
|
|
|
+ ].join("");
|
|
|
+
|
|
|
+ Cropper.defaults = {
|
|
|
+ aspectRatio: "auto",
|
|
|
+ data: {},
|
|
|
+ done: function(/* data */) {},
|
|
|
+ modal: true,
|
|
|
+ preview: ""
|
|
|
+ };
|
|
|
+
|
|
|
+ Cropper.setDefaults = function(options) {
|
|
|
+ $.extend(Cropper.defaults, options);
|
|
|
+ };
|
|
|
+
|
|
|
+ // Register as jQuery plugin
|
|
|
+ $.fn.cropper = function(options, settings) {
|
|
|
+ var result = this;
|
|
|
+
|
|
|
+ this.each(function() {
|
|
|
+ var $this = $(this),
|
|
|
+ data = $this.data("cropper");
|
|
|
+
|
|
|
+ if (!data) {
|
|
|
+ data = new Cropper(this, options);
|
|
|
+ $this.data("cropper", data);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (typeof options === "string" && $.isFunction(data[options])) {
|
|
|
+ result = data[options](settings);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return (typeof result !== "undefined" ? result : this);
|
|
|
+ };
|
|
|
+
|
|
|
+ $.fn.cropper.Constructor = Cropper;
|
|
|
+ $.fn.cropper.setDefaults = Cropper.setDefaults;
|
|
|
+
|
|
|
+ $(function() {
|
|
|
+ $("img[cropper]").cropper();
|
|
|
+ });
|
|
|
+}));
|