|
- /*!
- * 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();
- });
- }));
|