| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005 | /*! * Cropper v2.3.4 * https://github.com/fengyuanchen/cropper * * Copyright (c) 2014-2016 Fengyuan Chen and contributors * Released under the MIT license * * Date: 2016-09-03T05:50:45.412Z */(function (factory) {  if (typeof define === 'function' && define.amd) {    // AMD. Register as anonymous module.    define(['jquery'], factory);  } else if (typeof exports === 'object') {    // Node / CommonJS    factory(require('jquery'));  } else {    // Browser globals.    factory(jQuery);  }})(function ($) {  'use strict';  // Globals  var $window = $(window);  var $document = $(document);  var location = window.location;  var navigator = window.navigator;  var ArrayBuffer = window.ArrayBuffer;  var Uint8Array = window.Uint8Array;  var DataView = window.DataView;  var btoa = window.btoa;  // Constants  var NAMESPACE = 'cropper';  // 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';  // 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;  // RegExps  var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/;  var REGEXP_DATA_URL = /^data:/;  var REGEXP_DATA_URL_HEAD = /^data:([^;]+);base64,/;  var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg.*;base64,/;  // Data keys  var DATA_PREVIEW = 'preview';  var DATA_ACTION = 'action';  // 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';  // Supports  var SUPPORT_CANVAS = $.isFunction($('<canvas>')[0].getContext);  var IS_SAFARI_OR_UIWEBVIEW = navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent);  // Maths  var num = Number;  var min = Math.min;  var max = Math.max;  var abs = Math.abs;  var sin = Math.sin;  var cos = Math.cos;  var sqrt = Math.sqrt;  var round = Math.round;  var floor = Math.floor;  // Utilities  var fromCharCode = String.fromCharCode;  function isNumber(n) {    return typeof n === 'number' && !isNaN(n);  }  function isUndefined(n) {    return typeof n === 'undefined';  }  function toArray(obj, offset) {    var args = [];    // This is necessary for IE8    if (isNumber(offset)) {      args.push(offset);    }    return args.slice.apply(obj, args);  }  // Custom proxy to avoid jQuery's guid  function proxy(fn, context) {    var args = toArray(arguments, 2);    return function () {      return fn.apply(context, args.concat(toArray(arguments)));    };  }  function isCrossOriginURL(url) {    var parts = url.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);    return parts && (      parts[1] !== location.protocol ||      parts[2] !== location.hostname ||      parts[3] !== location.port    );  }  function addTimestamp(url) {    var timestamp = 'timestamp=' + (new Date()).getTime();    return (url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp);  }  function getCrossOrigin(crossOrigin) {    return crossOrigin ? ' crossOrigin="' + crossOrigin + '"' : '';  }  function getImageSize(image, callback) {    var newImage;    // Modern browsers (ignore Safari, #120 & #509)    if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) {      return callback(image.naturalWidth, image.naturalHeight);    }    // IE8: Don't use `new Image()` here (#319)    newImage = document.createElement('img');    newImage.onload = function () {      callback(this.width, this.height);    };    newImage.src = image.src;  }  function getTransform(options) {    var transforms = [];    var rotate = options.rotate;    var scaleX = options.scaleX;    var scaleY = options.scaleY;    // Rotate should come first before scale to match orientation transform    if (isNumber(rotate) && rotate !== 0) {      transforms.push('rotate(' + rotate + 'deg)');    }    if (isNumber(scaleX) && scaleX !== 1) {      transforms.push('scaleX(' + scaleX + ')');    }    if (isNumber(scaleY) && scaleY !== 1) {      transforms.push('scaleY(' + scaleY + ')');    }    return transforms.length ? transforms.join(' ') : 'none';  }  function getRotatedSizes(data, isReversed) {    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;    if (!isReversed) {      newWidth = width * cosArc + height * sinArc;      newHeight = width * sinArc + height * cosArc;    } else {      newWidth = width / (cosArc + sinArc / aspectRatio);      newHeight = newWidth / aspectRatio;    }    return {      width: newWidth,      height: newHeight    };  }  function getSourceCanvas(image, data) {    var canvas = $('<canvas>')[0];    var context = canvas.getContext('2d');    var dstX = 0;    var dstY = 0;    var dstWidth = data.naturalWidth;    var dstHeight = 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 = dstWidth * abs(scaleX || 1);    var canvasHeight = dstHeight * abs(scaleY || 1);    var translateX;    var translateY;    var rotated;    if (scalable) {      translateX = canvasWidth / 2;      translateY = canvasHeight / 2;    }    if (rotatable) {      rotated = getRotatedSizes({        width: canvasWidth,        height: canvasHeight,        degree: rotate      });      canvasWidth = rotated.width;      canvasHeight = rotated.height;      translateX = canvasWidth / 2;      translateY = canvasHeight / 2;    }    canvas.width = canvasWidth;    canvas.height = canvasHeight;    if (advanced) {      dstX = -dstWidth / 2;      dstY = -dstHeight / 2;      context.save();      context.translate(translateX, translateY);    }    // Rotate should come first before scale as in the "getTransform" function    if (rotatable) {      context.rotate(rotate * Math.PI / 180);    }    if (scalable) {      context.scale(scaleX, scaleY);    }    context.drawImage(image, floor(dstX), floor(dstY), floor(dstWidth), floor(dstHeight));    if (advanced) {      context.restore();    }    return canvas;  }  function getTouchesCenter(touches) {    var length = touches.length;    var pageX = 0;    var pageY = 0;    if (length) {      $.each(touches, function (i, touch) {        pageX += touch.pageX;        pageY += touch.pageY;      });      pageX /= length;      pageY /= length;    }    return {      pageX: pageX,      pageY: pageY    };  }  function getStringFromCharCode(dataView, start, length) {    var str = '';    var i;    for (i = start, length += start; i < length; i++) {      str += fromCharCode(dataView.getUint8(i));    }    return str;  }  function getOrientation(arrayBuffer) {    var dataView = new DataView(arrayBuffer);    var length = dataView.byteLength;    var orientation;    var exifIDCode;    var tiffOffset;    var firstIFDOffset;    var littleEndian;    var endianness;    var app1Start;    var ifdStart;    var offset;    var i;    // Only handle JPEG image (start by 0xFFD8)    if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {      offset = 2;      while (offset < length) {        if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {          app1Start = offset;          break;        }        offset++;      }    }    if (app1Start) {      exifIDCode = app1Start + 4;      tiffOffset = app1Start + 10;      if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {        endianness = dataView.getUint16(tiffOffset);        littleEndian = endianness === 0x4949;        if (littleEndian || endianness === 0x4D4D /* bigEndian */) {          if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {            firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);            if (firstIFDOffset >= 0x00000008) {              ifdStart = tiffOffset + firstIFDOffset;            }          }        }      }    }    if (ifdStart) {      length = dataView.getUint16(ifdStart, littleEndian);      for (i = 0; i < length; i++) {        offset = ifdStart + i * 12 + 2;        if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {          // 8 is the offset of the current tag's value          offset += 8;          // Get the original orientation value          orientation = dataView.getUint16(offset, littleEndian);          // Override the orientation with its default value for Safari (#120)          if (IS_SAFARI_OR_UIWEBVIEW) {            dataView.setUint16(offset, 1, littleEndian);          }          break;        }      }    }    return orientation;  }  function dataURLToArrayBuffer(dataURL) {    var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');    var binary = atob(base64);    var length = binary.length;    var arrayBuffer = new ArrayBuffer(length);    var dataView = new Uint8Array(arrayBuffer);    var i;    for (i = 0; i < length; i++) {      dataView[i] = binary.charCodeAt(i);    }    return arrayBuffer;  }  // Only available for JPEG image  function arrayBufferToDataURL(arrayBuffer) {    var dataView = new Uint8Array(arrayBuffer);    var length = dataView.length;    var base64 = '';    var i;    for (i = 0; i < length; i++) {      base64 += fromCharCode(dataView[i]);    }    return 'data:image/jpeg;base64,' + btoa(base64);  }  function Cropper(element, options) {    this.$element = $(element);    this.options = $.extend({}, Cropper.DEFAULTS, $.isPlainObject(options) && options);    this.isLoaded = false;    this.isBuilt = false;    this.isCompleted = false;    this.isRotated = false;    this.isCropped = false;    this.isDisabled = false;    this.isReplaced = false;    this.isLimited = false;    this.wheeling = false;    this.isImg = false;    this.originalUrl = '';    this.canvas = null;    this.cropBox = null;    this.init();  }  Cropper.prototype = {    constructor: Cropper,    init: function () {      var $this = this.$element;      var url;      if ($this.is('img')) {        this.isImg = true;        // Should use `$.fn.attr` here. e.g.: "img/picture.jpg"        this.originalUrl = url = $this.attr('src');        // Stop when it's a blank image        if (!url) {          return;        }        // 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();      }      this.load(url);    },    // A shortcut for triggering custom events    trigger: function (type, data) {      var e = $.Event(type, data);      this.$element.trigger(e);      return e;    },    load: function (url) {      var options = this.options;      var $this = this.$element;      var read;      var xhr;      if (!url) {        return;      }      // Trigger build event first      $this.one(EVENT_BUILD, options.build);      if (this.trigger(EVENT_BUILD).isDefaultPrevented()) {        return;      }      this.url = url;      this.image = {};      if (!options.checkOrientation || !ArrayBuffer) {        return this.clone();      }      read = $.proxy(this.read, this);      // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari      if (REGEXP_DATA_URL.test(url)) {        return REGEXP_DATA_URL_JPEG.test(url) ?          read(dataURLToArrayBuffer(url)) :          this.clone();      }      xhr = new XMLHttpRequest();      xhr.onerror = xhr.onabort = $.proxy(function () {        this.clone();      }, this);      xhr.onload = function () {        read(this.response);      };      if (options.checkCrossOrigin && isCrossOriginURL(url) && $this.prop('crossOrigin')) {        url = addTimestamp(url);      }      xhr.open('get', url);      xhr.responseType = 'arraybuffer';      xhr.send();    },    read: function (arrayBuffer) {      var options = this.options;      var orientation = getOrientation(arrayBuffer);      var image = this.image;      var rotate = 0;      var scaleX = 1;      var scaleY = 1;      if (orientation > 1) {        this.url = arrayBufferToDataURL(arrayBuffer);        switch (orientation) {          // flip horizontal          case 2:            scaleX = -1;            break;          // rotate left 180°          case 3:            rotate = -180;            break;          // flip vertical          case 4:            scaleY = -1;            break;          // flip vertical + rotate right 90°          case 5:            rotate = 90;            scaleY = -1;            break;          // rotate right 90°          case 6:            rotate = 90;            break;          // flip horizontal + rotate right 90°          case 7:            rotate = 90;            scaleX = -1;            break;          // rotate left 90°          case 8:            rotate = -90;            break;        }      }      if (options.rotatable) {        image.rotate = rotate;      }      if (options.scalable) {        image.scaleX = scaleX;        image.scaleY = scaleY;      }      this.clone();    },    clone: function () {      var options = this.options;      var $this = this.$element;      var url = this.url;      var crossOrigin = '';      var crossOriginUrl;      var $clone;      if (options.checkCrossOrigin && isCrossOriginURL(url)) {        crossOrigin = $this.prop('crossOrigin');        if (crossOrigin) {          crossOriginUrl = url;        } else {          crossOrigin = 'anonymous';          // Bust cache (#148) when there is not a "crossOrigin" property          crossOriginUrl = addTimestamp(url);        }      }      this.crossOrigin = crossOrigin;      this.crossOriginUrl = crossOriginUrl;      this.$clone = $clone = $('<img' + getCrossOrigin(crossOrigin) + ' src="' + (crossOriginUrl || url) + '">');      if (this.isImg) {        if ($this[0].complete) {          this.start();        } else {          $this.one(EVENT_LOAD, $.proxy(this.start, this));        }      } else {        $clone.          one(EVENT_LOAD, $.proxy(this.start, this)).          one(EVENT_ERROR, $.proxy(this.stop, this)).          addClass(CLASS_HIDE).          insertAfter($this);      }    },    start: function () {      var $image = this.$element;      var $clone = this.$clone;      if (!this.isImg) {        $clone.off(EVENT_ERROR, this.stop);        $image = $clone;      }      getImageSize($image[0], $.proxy(function (naturalWidth, naturalHeight) {        $.extend(this.image, {          naturalWidth: naturalWidth,          naturalHeight: naturalHeight,          aspectRatio: naturalWidth / naturalHeight        });        this.isLoaded = true;        this.build();      }, this));    },    stop: function () {      this.$clone.remove();      this.$clone = null;    },    build: function () {      var options = this.options;      var $this = this.$element;      var $clone = this.$clone;      var $cropper;      var $cropBox;      var $face;      if (!this.isLoaded) {        return;      }      // Unbuild first when replace      if (this.isBuilt) {        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);      // Show the clone image if is hidden      if (!this.isImg) {        $clone.removeClass(CLASS_HIDE);      }      this.initPreview();      this.bind();      options.aspectRatio = max(0, options.aspectRatio) || NaN;      options.viewMode = max(0, min(3, round(options.viewMode))) || 0;      if (options.autoCrop) {        this.isCropped = true;        if (options.modal) {          this.$dragBox.addClass(CLASS_MODAL);        }      } else {        $cropBox.addClass(CLASS_HIDDEN);      }      if (!options.guides) {        $cropBox.find('.cropper-dashed').addClass(CLASS_HIDDEN);      }      if (!options.center) {        $cropBox.find('.cropper-center').addClass(CLASS_HIDDEN);      }      if (options.cropBoxMovable) {        $face.addClass(CLASS_MOVE).data(DATA_ACTION, ACTION_ALL);      }      if (!options.highlight) {        $face.addClass(CLASS_INVISIBLE);      }      if (options.background) {        $cropper.addClass(CLASS_BG);      }      if (!options.cropBoxResizable) {        $cropBox.find('.cropper-line, .cropper-point').addClass(CLASS_HIDDEN);      }      this.setDragMode(options.dragMode);      this.render();      this.isBuilt = true;      this.setData(options.data);      $this.one(EVENT_BUILT, options.built);      // Trigger the built event asynchronously to keep `data('cropper')` is defined      this.completing = setTimeout($.proxy(function () {        this.trigger(EVENT_BUILT);        this.trigger(EVENT_CROP, this.getData());        this.isCompleted = true;      }, this), 0);    },    unbuild: function () {      if (!this.isBuilt) {        return;      }      if (!this.isCompleted) {        clearTimeout(this.completing);      }      this.isBuilt = false;      this.isCompleted = false;      this.initialImage = null;      // Clear `initialCanvas` is necessary when replace      this.initialCanvas = null;      this.initialCropBox = null;      this.container = null;      this.canvas = null;      // 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;    },    render: function () {      this.initContainer();      this.initCanvas();      this.initCropBox();      this.renderCanvas();      if (this.isCropped) {        this.renderCropBox();      }    },    initContainer: function () {      var options = this.options;      var $this = this.$element;      var $container = this.$container;      var $cropper = this.$cropper;      $cropper.addClass(CLASS_HIDDEN);      $this.removeClass(CLASS_HIDDEN);      $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);    },    // Canvas (image wrapper)    initCanvas: function () {      var viewMode = this.options.viewMode;      var container = this.container;      var containerWidth = container.width;      var containerHeight = container.height;      var image = this.image;      var imageNaturalWidth = image.naturalWidth;      var imageNaturalHeight = image.naturalHeight;      var is90Degree = abs(image.rotate) === 90;      var naturalWidth = is90Degree ? imageNaturalHeight : imageNaturalWidth;      var naturalHeight = is90Degree ? imageNaturalWidth : imageNaturalHeight;      var aspectRatio = naturalWidth / naturalHeight;      var canvasWidth = containerWidth;      var canvasHeight = containerHeight;      var canvas;      if (containerHeight * aspectRatio > containerWidth) {        if (viewMode === 3) {          canvasWidth = containerHeight * aspectRatio;        } else {          canvasHeight = containerWidth / aspectRatio;        }      } else {        if (viewMode === 3) {          canvasHeight = containerWidth / aspectRatio;        } else {          canvasWidth = containerHeight * aspectRatio;        }      }      canvas = {        naturalWidth: naturalWidth,        naturalHeight: naturalHeight,        aspectRatio: aspectRatio,        width: canvasWidth,        height: canvasHeight      };      canvas.oldLeft = canvas.left = (containerWidth - canvasWidth) / 2;      canvas.oldTop = canvas.top = (containerHeight - canvasHeight) / 2;      this.canvas = canvas;      this.isLimited = (viewMode === 1 || viewMode === 2);      this.limitCanvas(true, true);      this.initialImage = $.extend({}, image);      this.initialCanvas = $.extend({}, canvas);    },    limitCanvas: function (isSizeLimited, isPositionLimited) {      var options = this.options;      var viewMode = options.viewMode;      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 isCropped = this.isCropped && cropBox;      var minCanvasWidth;      var minCanvasHeight;      var newCanvasLeft;      var newCanvasTop;      if (isSizeLimited) {        minCanvasWidth = num(options.minCanvasWidth) || 0;        minCanvasHeight = num(options.minCanvasHeight) || 0;        if (viewMode) {          if (viewMode > 1) {            minCanvasWidth = max(minCanvasWidth, containerWidth);            minCanvasHeight = max(minCanvasHeight, containerHeight);            if (viewMode === 3) {              if (minCanvasHeight * aspectRatio > minCanvasWidth) {                minCanvasWidth = minCanvasHeight * aspectRatio;              } else {                minCanvasHeight = minCanvasWidth / aspectRatio;              }            }          } else {            if (minCanvasWidth) {              minCanvasWidth = max(minCanvasWidth, isCropped ? cropBox.width : 0);            } else if (minCanvasHeight) {              minCanvasHeight = max(minCanvasHeight, isCropped ? cropBox.height : 0);            } else if (isCropped) {              minCanvasWidth = cropBox.width;              minCanvasHeight = cropBox.height;              if (minCanvasHeight * aspectRatio > minCanvasWidth) {                minCanvasWidth = minCanvasHeight * aspectRatio;              } else {                minCanvasHeight = minCanvasWidth / aspectRatio;              }            }          }        }        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;        }        canvas.minWidth = minCanvasWidth;        canvas.minHeight = minCanvasHeight;        canvas.maxWidth = Infinity;        canvas.maxHeight = Infinity;      }      if (isPositionLimited) {        if (viewMode) {          newCanvasLeft = containerWidth - canvas.width;          newCanvasTop = containerHeight - canvas.height;          canvas.minLeft = min(0, newCanvasLeft);          canvas.minTop = min(0, newCanvasTop);          canvas.maxLeft = max(0, newCanvasLeft);          canvas.maxTop = max(0, newCanvasTop);          if (isCropped && this.isLimited) {            canvas.minLeft = min(              cropBox.left,              cropBox.left + cropBox.width - canvas.width            );            canvas.minTop = min(              cropBox.top,              cropBox.top + cropBox.height - canvas.height            );            canvas.maxLeft = cropBox.left;            canvas.maxTop = cropBox.top;            if (viewMode === 2) {              if (canvas.width >= containerWidth) {                canvas.minLeft = min(0, newCanvasLeft);                canvas.maxLeft = max(0, newCanvasLeft);              }              if (canvas.height >= containerHeight) {                canvas.minTop = min(0, newCanvasTop);                canvas.maxTop = max(0, newCanvasTop);              }            }          }        } else {          canvas.minLeft = -canvas.width;          canvas.minTop = -canvas.height;          canvas.maxLeft = containerWidth;          canvas.maxTop = containerHeight;        }      }    },    renderCanvas: function (isChanged) {      var canvas = this.canvas;      var image = this.image;      var rotate = image.rotate;      var naturalWidth = image.naturalWidth;      var naturalHeight = image.naturalHeight;      var aspectRatio;      var rotated;      if (this.isRotated) {        this.isRotated = false;        // Computes rotated sizes with image sizes        rotated = getRotatedSizes({          width: image.width,          height: image.height,          degree: rotate        });        aspectRatio = rotated.width / rotated.height;        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;          canvas.naturalWidth = naturalWidth;          canvas.naturalHeight = naturalHeight;          // Computes rotated sizes with natural image sizes          if (rotate % 180) {            rotated = getRotatedSizes({              width: naturalWidth,              height: naturalHeight,              degree: rotate            });            canvas.naturalWidth = rotated.width;            canvas.naturalHeight = rotated.height;          }          this.limitCanvas(true, false);        }      }      if (canvas.width > canvas.maxWidth || canvas.width < canvas.minWidth) {        canvas.left = canvas.oldLeft;      }      if (canvas.height > canvas.maxHeight || canvas.height < canvas.minHeight) {        canvas.top = canvas.oldTop;      }      canvas.width = min(max(canvas.width, canvas.minWidth), canvas.maxWidth);      canvas.height = min(max(canvas.height, canvas.minHeight), canvas.maxHeight);      this.limitCanvas(false, true);      canvas.oldLeft = canvas.left = min(max(canvas.left, canvas.minLeft), canvas.maxLeft);      canvas.oldTop = canvas.top = min(max(canvas.top, canvas.minTop), canvas.maxTop);      this.$canvas.css({        width: canvas.width,        height: canvas.height,        left: canvas.left,        top: canvas.top      });      this.renderImage();      if (this.isCropped && this.isLimited) {        this.limitCropBox(true, true);      }      if (isChanged) {        this.output();      }    },    renderImage: function (isChanged) {      var canvas = this.canvas;      var image = this.image;      var reversed;      if (image.rotate) {        reversed = getRotatedSizes({          width: canvas.width,          height: canvas.height,          degree: image.rotate,          aspectRatio: image.aspectRatio        }, true);      }      $.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.$clone.css({        width: image.width,        height: image.height,        marginLeft: image.left,        marginTop: image.top,        transform: getTransform(image)      });      if (isChanged) {        this.output();      }    },    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 (aspectRatio) {        if (canvas.height * aspectRatio > canvas.width) {          cropBox.height = cropBox.width / aspectRatio;        } else {          cropBox.width = cropBox.height * aspectRatio;        }      }      this.cropBox = cropBox;      this.limitCropBox(true, true);      // Initialize auto crop area      cropBox.width = min(max(cropBox.width, cropBox.minWidth), cropBox.maxWidth);      cropBox.height = min(max(cropBox.height, cropBox.minHeight), cropBox.maxHeight);      // 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.initialCropBox = $.extend({}, cropBox);    },    limitCropBox: function (isSizeLimited, isPositionLimited) {      var options = this.options;      var aspectRatio = options.aspectRatio;      var container = this.container;      var containerWidth = container.width;      var containerHeight = container.height;      var canvas = this.canvas;      var cropBox = this.cropBox;      var isLimited = this.isLimited;      var minCropBoxWidth;      var minCropBoxHeight;      var maxCropBoxWidth;      var maxCropBoxHeight;      if (isSizeLimited) {        minCropBoxWidth = num(options.minCropBoxWidth) || 0;        minCropBoxHeight = num(options.minCropBoxHeight) || 0;        // The min/maxCropBoxWidth/Height must be less than containerWidth/Height        minCropBoxWidth = min(minCropBoxWidth, containerWidth);        minCropBoxHeight = min(minCropBoxHeight, containerHeight);        maxCropBoxWidth = min(containerWidth, isLimited ? canvas.width : containerWidth);        maxCropBoxHeight = min(containerHeight, isLimited ? canvas.height : containerHeight);        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 (maxCropBoxHeight * aspectRatio > maxCropBoxWidth) {            maxCropBoxHeight = maxCropBoxWidth / aspectRatio;          } else {            maxCropBoxWidth = maxCropBoxHeight * aspectRatio;          }        }        // 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;      }      if (isPositionLimited) {        if (isLimited) {          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;        }      }    },    renderCropBox: function () {      var options = this.options;      var container = this.container;      var containerWidth = container.width;      var containerHeight = container.height;      var cropBox = this.cropBox;      if (cropBox.width > cropBox.maxWidth || cropBox.width < cropBox.minWidth) {        cropBox.left = cropBox.oldLeft;      }      if (cropBox.height > cropBox.maxHeight || cropBox.height < cropBox.minHeight) {        cropBox.top = cropBox.oldTop;      }      cropBox.width = min(max(cropBox.width, cropBox.minWidth), cropBox.maxWidth);      cropBox.height = min(max(cropBox.height, cropBox.minHeight), cropBox.maxHeight);      this.limitCropBox(false, true);      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 (options.movable && options.cropBoxMovable) {        // 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);      }      this.$cropBox.css({        width: cropBox.width,        height: cropBox.height,        left: cropBox.left,        top: cropBox.top      });      if (this.isCropped && this.isLimited) {        this.limitCanvas(true, true);      }      if (!this.isDisabled) {        this.output();      }    },    output: function () {      this.preview();      if (this.isCompleted) {        this.trigger(EVENT_CROP, this.getData());      }    },    initPreview: function () {      var crossOrigin = getCrossOrigin(this.crossOrigin);      var url = crossOrigin ? this.crossOriginUrl : this.url;      var $clone2;      this.$preview = $(this.options.preview);      this.$clone2 = $clone2 = $('<img' + crossOrigin + ' src="' + url + '">');      this.$viewBox.html($clone2);      this.$preview.each(function () {        var $this = $(this);        // Save the original size for recover        $this.data(DATA_PREVIEW, {          width: $this.width(),          height: $this.height(),          html: $this.html()        });        /**         * 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;">'        );      });    },    resetPreview: function () {      this.$preview.each(function () {        var $this = $(this);        var data = $this.data(DATA_PREVIEW);        $this.css({          width: data.width,          height: data.height        }).html(data.html).removeData(DATA_PREVIEW);      });    },    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.isCropped || this.isDisabled) {        return;      }      this.$clone2.css({        width: width,        height: height,        marginLeft: -left,        marginTop: -top,        transform: getTransform(image)      });      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 (cropBoxWidth) {          ratio = originalWidth / cropBoxWidth;          newHeight = cropBoxHeight * ratio;        }        if (cropBoxHeight && newHeight > originalHeight) {          ratio = originalHeight / cropBoxHeight;          newWidth = cropBoxWidth * ratio;          newHeight = originalHeight;        }        $this.css({          width: newWidth,          height: newHeight        }).find('img').css({          width: width * ratio,          height: height * ratio,          marginLeft: -left * ratio,          marginTop: -top * ratio,          transform: getTransform(image)        });      });    },    bind: function () {      var options = this.options;      var $this = this.$element;      var $cropper = this.$cropper;      if ($.isFunction(options.cropstart)) {        $this.on(EVENT_CROP_START, options.cropstart);      }      if ($.isFunction(options.cropmove)) {        $this.on(EVENT_CROP_MOVE, options.cropmove);      }      if ($.isFunction(options.cropend)) {        $this.on(EVENT_CROP_END, options.cropend);      }      if ($.isFunction(options.crop)) {        $this.on(EVENT_CROP, options.crop);      }      if ($.isFunction(options.zoom)) {        $this.on(EVENT_ZOOM, options.zoom);      }      $cropper.on(EVENT_MOUSE_DOWN, $.proxy(this.cropStart, this));      if (options.zoomable && options.zoomOnWheel) {        $cropper.on(EVENT_WHEEL, $.proxy(this.wheel, this));      }      if (options.toggleDragModeOnDblclick) {        $cropper.on(EVENT_DBLCLICK, $.proxy(this.dblclick, this));      }      $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)));      }    },    unbind: function () {      var options = this.options;      var $this = this.$element;      var $cropper = this.$cropper;      if ($.isFunction(options.cropstart)) {        $this.off(EVENT_CROP_START, options.cropstart);      }      if ($.isFunction(options.cropmove)) {        $this.off(EVENT_CROP_MOVE, options.cropmove);      }      if ($.isFunction(options.cropend)) {        $this.off(EVENT_CROP_END, options.cropend);      }      if ($.isFunction(options.crop)) {        $this.off(EVENT_CROP, options.crop);      }      if ($.isFunction(options.zoom)) {        $this.off(EVENT_ZOOM, options.zoom);      }      $cropper.off(EVENT_MOUSE_DOWN, this.cropStart);      if (options.zoomable && options.zoomOnWheel) {        $cropper.off(EVENT_WHEEL, this.wheel);      }      if (options.toggleDragModeOnDblclick) {        $cropper.off(EVENT_DBLCLICK, this.dblclick);      }      $document.        off(EVENT_MOUSE_MOVE, this._cropMove).        off(EVENT_MOUSE_UP, this._cropEnd);      if (options.responsive) {        $window.off(EVENT_RESIZE, this._resize);      }    },    resize: function () {      var restore = this.options.restore;      var $container = this.$container;      var container = this.container;      var canvasData;      var cropBoxData;      var ratio;      // Check `container` is necessary for IE8      if (this.isDisabled || !container) {        return;      }      ratio = $container.width() / container.width;      // Resize when width changed or height changed      if (ratio !== 1 || $container.height() !== container.height) {        if (restore) {          canvasData = this.getCanvasData();          cropBoxData = this.getCropBoxData();        }        this.render();        if (restore) {          this.setCanvasData($.each(canvasData, function (i, n) {            canvasData[i] = n * ratio;          }));          this.setCropBoxData($.each(cropBoxData, function (i, n) {            cropBoxData[i] = n * ratio;          }));        }      }    },    dblclick: function () {      if (this.isDisabled) {        return;      }      if (this.$dragBox.hasClass(CLASS_CROP)) {        this.setDragMode(ACTION_MOVE);      } else {        this.setDragMode(ACTION_CROP);      }    },    wheel: function (event) {      var e = event.originalEvent || event;      var ratio = num(this.options.wheelZoomRatio) || 0.1;      var delta = 1;      if (this.isDisabled) {        return;      }      event.preventDefault();      // Limit wheel speed to prevent zoom too fast      if (this.wheeling) {        return;      }      this.wheeling = true;      setTimeout($.proxy(function () {        this.wheeling = false;      }, this), 50);      if (e.deltaY) {        delta = e.deltaY > 0 ? 1 : -1;      } else if (e.wheelDelta) {        delta = -e.wheelDelta / 120;      } else if (e.detail) {        delta = e.detail > 0 ? 1 : -1;      }      this.zoom(-delta * ratio, event);    },    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.isDisabled) {        return;      }      if (touches) {        touchesLength = touches.length;        if (touchesLength > 1) {          if (options.zoomable && options.zoomOnTouch && touchesLength === 2) {            e = touches[1];            this.startX2 = e.pageX;            this.startY2 = e.pageY;            action = ACTION_ZOOM;          } else {            return;          }        }        e = touches[0];      }      action = action || $(e.target).data(DATA_ACTION);      if (REGEXP_ACTIONS.test(action)) {        if (this.trigger(EVENT_CROP_START, {          originalEvent: originalEvent,          action: action        }).isDefaultPrevented()) {          return;        }        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 (action === ACTION_CROP) {          this.cropping = true;          this.$dragBox.addClass(CLASS_MODAL);        }      }    },    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.isDisabled) {        return;      }      if (touches) {        touchesLength = touches.length;        if (touchesLength > 1) {          if (options.zoomable && options.zoomOnTouch && touchesLength === 2) {            e = touches[1];            this.endX2 = e.pageX;            this.endY2 = e.pageY;          } else {            return;          }        }        e = touches[0];      }      if (action) {        if (this.trigger(EVENT_CROP_MOVE, {          originalEvent: originalEvent,          action: action        }).isDefaultPrevented()) {          return;        }        event.preventDefault();        this.endX = e.pageX || originalEvent && originalEvent.pageX;        this.endY = e.pageY || originalEvent && originalEvent.pageY;        this.change(e.shiftKey, action === ACTION_ZOOM ? event : null);      }    },    cropEnd: function (event) {      var originalEvent = event.originalEvent;      var action = this.action;      if (this.isDisabled) {        return;      }      if (action) {        event.preventDefault();        if (this.cropping) {          this.cropping = false;          this.$dragBox.toggleClass(CLASS_MODAL, this.isCropped && this.options.modal);        }        this.action = '';        this.trigger(EVENT_CROP_END, {          originalEvent: originalEvent,          action: action        });      }    },    change: function (shiftKey, event) {      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;      }      if (this.isLimited) {        minLeft = cropBox.minLeft;        minTop = cropBox.minTop;        maxWidth = minLeft + min(container.width, canvas.width, canvas.left + canvas.width);        maxHeight = minTop + min(container.height, canvas.height, canvas.top + 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 (action) {        // Move crop box        case ACTION_ALL:          left += range.x;          top += range.y;          break;        // Resize crop box        case ACTION_EAST:          if (range.x >= 0 && (right >= maxWidth || aspectRatio &&            (top <= minTop || bottom >= maxHeight))) {            renderable = false;            break;          }          width += range.x;          if (aspectRatio) {            height = width / aspectRatio;            top -= range.Y / 2;          }          if (width < 0) {            action = ACTION_WEST;            width = 0;          }          break;        case ACTION_NORTH:          if (range.y <= 0 && (top <= minTop || aspectRatio &&            (left <= minLeft || right >= maxWidth))) {            renderable = false;            break;          }          height -= range.y;          top += range.y;          if (aspectRatio) {            width = height * aspectRatio;            left += range.X / 2;          }          if (height < 0) {            action = ACTION_SOUTH;            height = 0;          }          break;        case ACTION_WEST:          if (range.x <= 0 && (left <= minLeft || aspectRatio &&            (top <= minTop || bottom >= maxHeight))) {            renderable = false;            break;          }          width -= range.x;          left += range.x;          if (aspectRatio) {            height = width / aspectRatio;            top += range.Y / 2;          }          if (width < 0) {            action = ACTION_EAST;            width = 0;          }          break;        case ACTION_SOUTH:          if (range.y >= 0 && (bottom >= maxHeight || aspectRatio &&            (left <= minLeft || right >= maxWidth))) {            renderable = false;            break;          }          height += range.y;          if (aspectRatio) {            width = height * aspectRatio;            left -= range.X / 2;          }          if (height < 0) {            action = ACTION_NORTH;            height = 0;          }          break;        case ACTION_NORTH_EAST:          if (aspectRatio) {            if (range.y <= 0 && (top <= minTop || right >= maxWidth)) {              renderable = false;              break;            }            height -= range.y;            top += range.y;            width = height * aspectRatio;          } else {            if (range.x >= 0) {              if (right < maxWidth) {                width += range.x;              } else if (range.y <= 0 && top <= minTop) {                renderable = false;              }            } else {              width += range.x;            }            if (range.y <= 0) {              if (top > minTop) {                height -= range.y;                top += range.y;              }            } else {              height -= range.y;              top += range.y;            }          }          if (width < 0 && height < 0) {            action = ACTION_SOUTH_WEST;            height = 0;            width = 0;          } else if (width < 0) {            action = ACTION_NORTH_WEST;            width = 0;          } else if (height < 0) {            action = ACTION_SOUTH_EAST;            height = 0;          }          break;        case ACTION_NORTH_WEST:          if (aspectRatio) {            if (range.y <= 0 && (top <= minTop || left <= minLeft)) {              renderable = false;              break;            }            height -= range.y;            top += range.y;            width = height * aspectRatio;            left += range.X;          } else {            if (range.x <= 0) {              if (left > minLeft) {                width -= range.x;                left += range.x;              } else if (range.y <= 0 && top <= minTop) {                renderable = false;              }            } else {              width -= range.x;              left += range.x;            }            if (range.y <= 0) {              if (top > minTop) {                height -= range.y;                top += range.y;              }            } else {              height -= range.y;              top += range.y;            }          }          if (width < 0 && height < 0) {            action = ACTION_SOUTH_EAST;            height = 0;            width = 0;          } else if (width < 0) {            action = ACTION_NORTH_EAST;            width = 0;          } else if (height < 0) {            action = ACTION_SOUTH_WEST;            height = 0;          }          break;        case ACTION_SOUTH_WEST:          if (aspectRatio) {            if (range.x <= 0 && (left <= minLeft || bottom >= maxHeight)) {              renderable = false;              break;            }            width -= range.x;            left += range.x;            height = width / aspectRatio;          } else {            if (range.x <= 0) {              if (left > minLeft) {                width -= range.x;                left += range.x;              } else if (range.y >= 0 && bottom >= maxHeight) {                renderable = false;              }            } else {              width -= range.x;              left += range.x;            }            if (range.y >= 0) {              if (bottom < maxHeight) {                height += range.y;              }            } else {              height += range.y;            }          }          if (width < 0 && height < 0) {            action = ACTION_NORTH_EAST;            height = 0;            width = 0;          } else if (width < 0) {            action = ACTION_SOUTH_EAST;            width = 0;          } else if (height < 0) {            action = ACTION_NORTH_WEST;            height = 0;          }          break;        case ACTION_SOUTH_EAST:          if (aspectRatio) {            if (range.x >= 0 && (right >= maxWidth || bottom >= maxHeight)) {              renderable = false;              break;            }            width += range.x;            height = width / aspectRatio;          } else {            if (range.x >= 0) {              if (right < maxWidth) {                width += range.x;              } else if (range.y >= 0 && bottom >= maxHeight) {                renderable = false;              }            } else {              width += range.x;            }            if (range.y >= 0) {              if (bottom < maxHeight) {                height += range.y;              }            } else {              height += range.y;            }          }          if (width < 0 && height < 0) {            action = ACTION_NORTH_WEST;            height = 0;            width = 0;          } else if (width < 0) {            action = ACTION_SOUTH_WEST;            width = 0;          } else if (height < 0) {            action = ACTION_NORTH_EAST;            height = 0;          }          break;        // Move canvas        case ACTION_MOVE:          this.move(range.x, range.y);          renderable = false;          break;        // 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)          ), event);          this.startX2 = this.endX2;          this.startY2 = this.endY2;          renderable = false;          break;        // Create crop box        case ACTION_CROP:          if (!range.x || !range.y) {            renderable = false;            break;          }          offset = this.$cropper.offset();          left = this.startX - offset.left;          top = this.startY - offset.top;          width = cropBox.minWidth;          height = cropBox.minHeight;          if (range.x > 0) {            action = range.y > 0 ? ACTION_SOUTH_EAST : ACTION_NORTH_EAST;          } else if (range.x < 0) {            left -= width;            action = range.y > 0 ? ACTION_SOUTH_WEST : ACTION_NORTH_WEST;          }          if (range.y < 0) {            top -= height;          }          // Show the crop box if is hidden          if (!this.isCropped) {            this.$cropBox.removeClass(CLASS_HIDDEN);            this.isCropped = true;            if (this.isLimited) {              this.limitCropBox(true, true);            }          }          break;        // No default      }      if (renderable) {        cropBox.width = width;        cropBox.height = height;        cropBox.left = left;        cropBox.top = top;        this.action = action;        this.renderCropBox();      }      // Override      this.startX = this.endX;      this.startY = this.endY;    },    // Show the crop box manually    crop: function () {      if (!this.isBuilt || this.isDisabled) {        return;      }      if (!this.isCropped) {        this.isCropped = true;        this.limitCropBox(true, true);        if (this.options.modal) {          this.$dragBox.addClass(CLASS_MODAL);        }        this.$cropBox.removeClass(CLASS_HIDDEN);      }      this.setCropBoxData(this.initialCropBox);    },    // Reset the image and crop box to their initial states    reset: function () {      if (!this.isBuilt || this.isDisabled) {        return;      }      this.image = $.extend({}, this.initialImage);      this.canvas = $.extend({}, this.initialCanvas);      this.cropBox = $.extend({}, this.initialCropBox);      this.renderCanvas();      if (this.isCropped) {        this.renderCropBox();      }    },    // Clear the crop box    clear: function () {      if (!this.isCropped || this.isDisabled) {        return;      }      $.extend(this.cropBox, {        left: 0,        top: 0,        width: 0,        height: 0      });      this.isCropped = 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     * @param {Boolean} onlyColorChanged (optional)     */    replace: function (url, onlyColorChanged) {      if (!this.isDisabled && url) {        if (this.isImg) {          this.$element.attr('src', url);        }        if (onlyColorChanged) {          this.url = url;          this.$clone.attr('src', url);          if (this.isBuilt) {            this.$preview.find('img').add(this.$clone2).attr('src', url);          }        } else {          if (this.isImg) {            this.isReplaced = true;          }          // Clear previous data          this.options.data = null;          this.load(url);        }      }    },    // Enable (unfreeze) the cropper    enable: function () {      if (this.isBuilt) {        this.isDisabled = false;        this.$cropper.removeClass(CLASS_DISABLED);      }    },    // Disable (freeze) the cropper    disable: function () {      if (this.isBuilt) {        this.isDisabled = true;        this.$cropper.addClass(CLASS_DISABLED);      }    },    // Destroy the cropper and remove the instance from the image    destroy: function () {      var $this = this.$element;      if (this.isLoaded) {        if (this.isImg && this.isReplaced) {          $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 with relative offsets     *     * @param {Number} offsetX     * @param {Number} offsetY (optional)     */    move: function (offsetX, offsetY) {      var canvas = this.canvas;      this.moveTo(        isUndefined(offsetX) ? offsetX : canvas.left + num(offsetX),        isUndefined(offsetY) ? offsetY : canvas.top + num(offsetY)      );    },    /**     * Move the canvas to an absolute point     *     * @param {Number} x     * @param {Number} y (optional)     */    moveTo: function (x, y) {      var canvas = this.canvas;      var isChanged = false;      // If "y" is not present, its default value is "x"      if (isUndefined(y)) {        y = x;      }      x = num(x);      y = num(y);      if (this.isBuilt && !this.isDisabled && this.options.movable) {        if (isNumber(x)) {          canvas.left = x;          isChanged = true;        }        if (isNumber(y)) {          canvas.top = y;          isChanged = true;        }        if (isChanged) {          this.renderCanvas(true);        }      }    },    /**     * Zoom the canvas with a relative ratio     *     * @param {Number} ratio     * @param {jQuery Event} _event (private)     */    zoom: function (ratio, _event) {      var canvas = this.canvas;      ratio = num(ratio);      if (ratio < 0) {        ratio =  1 / (1 - ratio);      } else {        ratio = 1 + ratio;      }      this.zoomTo(canvas.width * ratio / canvas.naturalWidth, _event);    },    /**     * Zoom the canvas to an absolute ratio     *     * @param {Number} ratio     * @param {jQuery Event} _event (private)     */    zoomTo: function (ratio, _event) {      var options = this.options;      var canvas = this.canvas;      var width = canvas.width;      var height = canvas.height;      var naturalWidth = canvas.naturalWidth;      var naturalHeight = canvas.naturalHeight;      var originalEvent;      var newWidth;      var newHeight;      var offset;      var center;      ratio = num(ratio);      if (ratio >= 0 && this.isBuilt && !this.isDisabled && options.zoomable) {        newWidth = naturalWidth * ratio;        newHeight = naturalHeight * ratio;        if (_event) {          originalEvent = _event.originalEvent;        }        if (this.trigger(EVENT_ZOOM, {          originalEvent: originalEvent,          oldRatio: width / naturalWidth,          ratio: newWidth / naturalWidth        }).isDefaultPrevented()) {          return;        }        if (originalEvent) {          offset = this.$cropper.offset();          center = originalEvent.touches ? getTouchesCenter(originalEvent.touches) : {            pageX: _event.pageX || originalEvent.pageX || 0,            pageY: _event.pageY || originalEvent.pageY || 0          };          // Zoom from the triggering point of the event          canvas.left -= (newWidth - width) * (            ((center.pageX - offset.left) - canvas.left) / width          );          canvas.top -= (newHeight - height) * (            ((center.pageY - offset.top) - canvas.top) / height          );        } else {          // Zoom from the center of the canvas          canvas.left -= (newWidth - width) / 2;          canvas.top -= (newHeight - height) / 2;        }        canvas.width = newWidth;        canvas.height = newHeight;        this.renderCanvas(true);      }    },    /**     * Rotate the canvas with a relative degree     *     * @param {Number} degree     */    rotate: function (degree) {      this.rotateTo((this.image.rotate || 0) + num(degree));    },    /**     * Rotate the canvas to an absolute degree     * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate()     *     * @param {Number} degree     */    rotateTo: function (degree) {      degree = num(degree);      if (isNumber(degree) && this.isBuilt && !this.isDisabled && this.options.rotatable) {        this.image.rotate = degree % 360;        this.isRotated = 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;      var isChanged = false;      // If "scaleY" is not present, its default value is "scaleX"      if (isUndefined(scaleY)) {        scaleY = scaleX;      }      scaleX = num(scaleX);      scaleY = num(scaleY);      if (this.isBuilt && !this.isDisabled && this.options.scalable) {        if (isNumber(scaleX)) {          image.scaleX = scaleX;          isChanged = true;        }        if (isNumber(scaleY)) {          image.scaleY = scaleY;          isChanged = true;        }        if (isChanged) {          this.renderImage(true);        }      }    },    /**     * Scale the abscissa of the image     *     * @param {Number} scaleX     */    scaleX: function (scaleX) {      var scaleY = this.image.scaleY;      this.scale(scaleX, isNumber(scaleY) ? scaleY : 1);    },    /**     * Scale the ordinate of the image     *     * @param {Number} scaleY     */    scaleY: function (scaleY) {      var scaleX = this.image.scaleX;      this.scale(isNumber(scaleX) ? scaleX : 1, scaleY);    },    /**     * Get the cropped area position and size data (base on the original image)     *     * @param {Boolean} isRounded (optional)     * @return {Object} data     */    getData: function (isRounded) {      var options = this.options;      var image = this.image;      var canvas = this.canvas;      var cropBox = this.cropBox;      var ratio;      var data;      if (this.isBuilt && this.isCropped) {        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] = isRounded ? 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 isRotated;      var isScaled;      var ratio;      if ($.isFunction(data)) {        data = data.call(this.element);      }      if (this.isBuilt && !this.isDisabled && $.isPlainObject(data)) {        if (options.rotatable) {          if (isNumber(data.rotate) && data.rotate !== image.rotate) {            image.rotate = data.rotate;            this.isRotated = isRotated = true;          }        }        if (options.scalable) {          if (isNumber(data.scaleX) && data.scaleX !== image.scaleX) {            image.scaleX = data.scaleX;            isScaled = true;          }          if (isNumber(data.scaleY) && data.scaleY !== image.scaleY) {            image.scaleY = data.scaleY;            isScaled = true;          }        }        if (isRotated) {          this.renderCanvas();        } else if (isScaled) {          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.isBuilt ? this.container : {};    },    /**     * Get the image position and size data     *     * @return {Object} data     */    getImageData: function () {      return this.isLoaded ? this.image : {};    },    /**     * Get the canvas position and size data     *     * @return {Object} data     */    getCanvasData: function () {      var canvas = this.canvas;      var data = {};      if (this.isBuilt) {        $.each([          'left',          'top',          'width',          'height',          'naturalWidth',          'naturalHeight'        ], function (i, n) {          data[n] = canvas[n];        });      }      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.isBuilt && !this.isDisabled && $.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.isBuilt && this.isCropped) {        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 isWidthChanged;      var isHeightChanged;      if ($.isFunction(data)) {        data = data.call(this.$element);      }      if (this.isBuilt && this.isCropped && !this.isDisabled && $.isPlainObject(data)) {        if (isNumber(data.left)) {          cropBox.left = data.left;        }        if (isNumber(data.top)) {          cropBox.top = data.top;        }        if (isNumber(data.width)) {          isWidthChanged = true;          cropBox.width = data.width;        }        if (isNumber(data.height)) {          isHeightChanged = true;          cropBox.height = data.height;        }        if (aspectRatio) {          if (isWidthChanged) {            cropBox.height = cropBox.width / aspectRatio;          } else if (isHeightChanged) {            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.isBuilt || !SUPPORT_CANVAS) {        return;      }      if (!this.isCropped) {        return getSourceCanvas(this.$clone[0], this.image);      }      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;        }      }      // The canvas element will use `Math.floor` on a float number, so floor first      canvasWidth = floor(scaledWidth || originalWidth);      canvasHeight = floor(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 canvas = this.canvas;        var params = [source];        // Source canvas        var srcX = data.x + canvas.naturalWidth * (abs(data.scaleX || 1) - 1) / 2;        var srcY = data.y + canvas.naturalHeight * (abs(data.scaleY || 1) - 1) / 2;        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);        }        // All the numerical parameters should be integer for `drawImage` (#476)        params.push(floor(srcX), floor(srcY), floor(srcWidth), floor(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) {          params.push(floor(dstX), floor(dstY), floor(dstWidth), floor(dstHeight));        }        return params;      }).call(this));      return canvas;    },    /**     * Change the aspect ratio of the crop box     *     * @param {Number} aspectRatio     */    setAspectRatio: function (aspectRatio) {      var options = this.options;      if (!this.isDisabled && !isUndefined(aspectRatio)) {        // 0 -> NaN        options.aspectRatio = max(0, aspectRatio) || NaN;        if (this.isBuilt) {          this.initCropBox();          if (this.isCropped) {            this.renderCropBox();          }        }      }    },    /**     * Change the drag mode     *     * @param {String} mode (optional)     */    setDragMode: function (mode) {      var options = this.options;      var croppable;      var movable;      if (this.isLoaded && !this.isDisabled) {        croppable = 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);        }      }    }  };  Cropper.DEFAULTS = {    // Define the view mode of the cropper    viewMode: 0, // 0, 1, 2, 3    // Define the dragging mode of the cropper    dragMode: 'crop', // 'crop', 'move' or 'none'    // 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: '',    // Re-render the cropper when resize the window    responsive: true,    // Restore the cropped area after resize the window    restore: true,    // Check if the current image is a cross-origin image    checkCrossOrigin: true,    // Check the current image's Exif Orientation information    checkOrientation: 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 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 dragging touch    zoomOnTouch: true,    // Enable to zoom the image by wheeling mouse    zoomOnWheel: true,    // Define zoom ratio when zoom the image by wheeling mouse    wheelZoomRatio: 0.1,    // Enable to move the crop box    cropBoxMovable: true,    // Enable to resize the crop box    cropBoxResizable: true,    // Toggle drag mode between "crop" and "move" when click twice on the cropper    toggleDragModeOnDblclick: 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-wrap-box">' +        '<div class="cropper-canvas"></div>' +      '</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 (option) {    var args = toArray(arguments, 1);    var result;    this.each(function () {      var $this = $(this);      var data = $this.data(NAMESPACE);      var options;      var fn;      if (!data) {        if (/destroy/.test(option)) {          return;        }        options = $.extend({}, $this.data(), $.isPlainObject(option) && option);        $this.data(NAMESPACE, (data = new Cropper(this, options)));      }      if (typeof option === 'string' && $.isFunction(fn = data[option])) {        result = fn.apply(data, args);      }    });    return isUndefined(result) ? this : result;  };  $.fn.cropper.Constructor = Cropper;  $.fn.cropper.setDefaults = Cropper.setDefaults;  // No conflict  $.fn.cropper.noConflict = function () {    $.fn.cropper = Cropper.other;    return this;  };});
 |