Path: blob/master/web-gui/buildyourownbotnet/assets/js/jcrop/jquery.Jcrop.js
1293 views
/**1* jquery.Jcrop.js v0.9.122* jQuery Image Cropping Plugin - released under MIT License3* Author: Kelly Hallman <[email protected]>4* http://github.com/tapmodo/Jcrop5* Copyright (c) 2008-2013 Tapmodo Interactive LLC {{{6*7* Permission is hereby granted, free of charge, to any person8* obtaining a copy of this software and associated documentation9* files (the "Software"), to deal in the Software without10* restriction, including without limitation the rights to use,11* copy, modify, merge, publish, distribute, sublicense, and/or sell12* copies of the Software, and to permit persons to whom the13* Software is furnished to do so, subject to the following14* conditions:15*16* The above copyright notice and this permission notice shall be17* included in all copies or substantial portions of the Software.18*19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,20* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES21* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND22* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT23* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,24* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING25* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR26* OTHER DEALINGS IN THE SOFTWARE.27*28* }}}29*/3031(function ($) {3233$.Jcrop = function (obj, opt) {34var options = $.extend({}, $.Jcrop.defaults),35docOffset,36_ua = navigator.userAgent.toLowerCase(),37is_msie = /msie/.test(_ua),38ie6mode = /msie [1-6]\./.test(_ua);3940// Internal Methods {{{41function px(n) {42return Math.round(n) + 'px';43}44function cssClass(cl) {45return options.baseClass + '-' + cl;46}47function supportsColorFade() {48return $.fx.step.hasOwnProperty('backgroundColor');49}50function getPos(obj) //{{{51{52var pos = $(obj).offset();53return [pos.left, pos.top];54}55//}}}56function mouseAbs(e) //{{{57{58return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])];59}60//}}}61function setOptions(opt) //{{{62{63if (typeof(opt) !== 'object') opt = {};64options = $.extend(options, opt);6566$.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) {67if (typeof(options[e]) !== 'function') options[e] = function () {};68});69}70//}}}71function startDragMode(mode, pos, touch) //{{{72{73docOffset = getPos($img);74Tracker.setCursor(mode === 'move' ? mode : mode + '-resize');7576if (mode === 'move') {77return Tracker.activateHandlers(createMover(pos), doneSelect, touch);78}7980var fc = Coords.getFixed();81var opp = oppLockCorner(mode);82var opc = Coords.getCorner(oppLockCorner(opp));8384Coords.setPressed(Coords.getCorner(opp));85Coords.setCurrent(opc);8687Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch);88}89//}}}90function dragmodeHandler(mode, f) //{{{91{92return function (pos) {93if (!options.aspectRatio) {94switch (mode) {95case 'e':96pos[1] = f.y2;97break;98case 'w':99pos[1] = f.y2;100break;101case 'n':102pos[0] = f.x2;103break;104case 's':105pos[0] = f.x2;106break;107}108} else {109switch (mode) {110case 'e':111pos[1] = f.y + 1;112break;113case 'w':114pos[1] = f.y + 1;115break;116case 'n':117pos[0] = f.x + 1;118break;119case 's':120pos[0] = f.x + 1;121break;122}123}124Coords.setCurrent(pos);125Selection.update();126};127}128//}}}129function createMover(pos) //{{{130{131var lloc = pos;132KeyManager.watchKeys();133134return function (pos) {135Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]);136lloc = pos;137138Selection.update();139};140}141//}}}142function oppLockCorner(ord) //{{{143{144switch (ord) {145case 'n':146return 'sw';147case 's':148return 'nw';149case 'e':150return 'nw';151case 'w':152return 'ne';153case 'ne':154return 'sw';155case 'nw':156return 'se';157case 'se':158return 'nw';159case 'sw':160return 'ne';161}162}163//}}}164function createDragger(ord) //{{{165{166return function (e) {167if (options.disabled) {168return false;169}170if ((ord === 'move') && !options.allowMove) {171return false;172}173174// Fix position of crop area when dragged the very first time.175// Necessary when crop image is in a hidden element when page is loaded.176docOffset = getPos($img);177178btndown = true;179startDragMode(ord, mouseAbs(e));180e.stopPropagation();181e.preventDefault();182return false;183};184}185//}}}186function presize($obj, w, h) //{{{187{188var nw = $obj.width(),189nh = $obj.height();190if ((nw > w) && w > 0) {191nw = w;192nh = (w / $obj.width()) * $obj.height();193}194if ((nh > h) && h > 0) {195nh = h;196nw = (h / $obj.height()) * $obj.width();197}198xscale = $obj.width() / nw;199yscale = $obj.height() / nh;200$obj.width(nw).height(nh);201}202//}}}203function unscale(c) //{{{204{205return {206x: c.x * xscale,207y: c.y * yscale,208x2: c.x2 * xscale,209y2: c.y2 * yscale,210w: c.w * xscale,211h: c.h * yscale212};213}214//}}}215function doneSelect(pos) //{{{216{217var c = Coords.getFixed();218if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) {219Selection.enableHandles();220Selection.done();221} else {222Selection.release();223}224Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');225}226//}}}227function newSelection(e) //{{{228{229if (options.disabled) {230return false;231}232if (!options.allowSelect) {233return false;234}235btndown = true;236docOffset = getPos($img);237Selection.disableHandles();238Tracker.setCursor('crosshair');239var pos = mouseAbs(e);240Coords.setPressed(pos);241Selection.update();242Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0,5)==='touch');243KeyManager.watchKeys();244245e.stopPropagation();246e.preventDefault();247return false;248}249//}}}250function selectDrag(pos) //{{{251{252Coords.setCurrent(pos);253Selection.update();254}255//}}}256function newTracker() //{{{257{258var trk = $('<div></div>').addClass(cssClass('tracker'));259if (is_msie) {260trk.css({261opacity: 0,262backgroundColor: 'white'263});264}265return trk;266}267//}}}268269// }}}270// Initialization {{{271// Sanitize some options {{{272if (typeof(obj) !== 'object') {273obj = $(obj)[0];274}275if (typeof(opt) !== 'object') {276opt = {};277}278// }}}279setOptions(opt);280// Initialize some jQuery objects {{{281// The values are SET on the image(s) for the interface282// If the original image has any of these set, they will be reset283// However, if you destroy() the Jcrop instance the original image's284// character in the DOM will be as you left it.285var img_css = {286border: 'none',287visibility: 'visible',288margin: 0,289padding: 0,290position: 'absolute',291top: 0,292left: 0293};294295var $origimg = $(obj),296img_mode = true;297298if (obj.tagName == 'IMG') {299// Fix size of crop image.300// Necessary when crop image is within a hidden element when page is loaded.301if ($origimg[0].width != 0 && $origimg[0].height != 0) {302// Obtain dimensions from contained img element.303$origimg.width($origimg[0].width);304$origimg.height($origimg[0].height);305} else {306// Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).307var tempImage = new Image();308tempImage.src = $origimg[0].src;309$origimg.width(tempImage.width);310$origimg.height(tempImage.height);311}312313var $img = $origimg.clone().removeAttr('id').css(img_css).show();314315$img.width($origimg.width());316$img.height($origimg.height());317$origimg.after($img).hide();318319} else {320$img = $origimg.css(img_css).show();321img_mode = false;322if (options.shade === null) { options.shade = true; }323}324325presize($img, options.boxWidth, options.boxHeight);326327var boundx = $img.width(),328boundy = $img.height(),329330331$div = $('<div />').width(boundx).height(boundy).addClass(cssClass('holder')).css({332position: 'relative',333backgroundColor: options.bgColor334}).insertAfter($origimg).append($img);335336if (options.addClass) {337$div.addClass(options.addClass);338}339340var $img2 = $('<div />'),341342$img_holder = $('<div />')343.width('100%').height('100%').css({344zIndex: 310,345position: 'absolute',346overflow: 'hidden'347}),348349$hdl_holder = $('<div />')350.width('100%').height('100%').css('zIndex', 320),351352$sel = $('<div />')353.css({354position: 'absolute',355zIndex: 600356}).dblclick(function(){357var c = Coords.getFixed();358options.onDblClick.call(api,c);359}).insertBefore($img).append($img_holder, $hdl_holder);360361if (img_mode) {362363$img2 = $('<img />')364.attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy),365366$img_holder.append($img2);367368}369370if (ie6mode) {371$sel.css({372overflowY: 'hidden'373});374}375376var bound = options.boundary;377var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({378position: 'absolute',379top: px(-bound),380left: px(-bound),381zIndex: 290382}).mousedown(newSelection);383384/* }}} */385// Set more variables {{{386var bgcolor = options.bgColor,387bgopacity = options.bgOpacity,388xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true,389btndown, animating, shift_down;390391docOffset = getPos($img);392// }}}393// }}}394// Internal Modules {{{395// Touch Module {{{396var Touch = (function () {397// Touch support detection function adapted (under MIT License)398// from code by Jeffrey Sambells - http://github.com/iamamused/399function hasTouchSupport() {400var support = {}, events = ['touchstart', 'touchmove', 'touchend'],401el = document.createElement('div'), i;402403try {404for(i=0; i<events.length; i++) {405var eventName = events[i];406eventName = 'on' + eventName;407var isSupported = (eventName in el);408if (!isSupported) {409el.setAttribute(eventName, 'return;');410isSupported = typeof el[eventName] == 'function';411}412support[events[i]] = isSupported;413}414return support.touchstart && support.touchend && support.touchmove;415}416catch(err) {417return false;418}419}420421function detectSupport() {422if ((options.touchSupport === true) || (options.touchSupport === false)) return options.touchSupport;423else return hasTouchSupport();424}425return {426createDragger: function (ord) {427return function (e) {428if (options.disabled) {429return false;430}431if ((ord === 'move') && !options.allowMove) {432return false;433}434docOffset = getPos($img);435btndown = true;436startDragMode(ord, mouseAbs(Touch.cfilter(e)), true);437e.stopPropagation();438e.preventDefault();439return false;440};441},442newSelection: function (e) {443return newSelection(Touch.cfilter(e));444},445cfilter: function (e){446e.pageX = e.originalEvent.changedTouches[0].pageX;447e.pageY = e.originalEvent.changedTouches[0].pageY;448return e;449},450isSupported: hasTouchSupport,451support: detectSupport()452};453}());454// }}}455// Coords Module {{{456var Coords = (function () {457var x1 = 0,458y1 = 0,459x2 = 0,460y2 = 0,461ox, oy;462463function setPressed(pos) //{{{464{465pos = rebound(pos);466x2 = x1 = pos[0];467y2 = y1 = pos[1];468}469//}}}470function setCurrent(pos) //{{{471{472pos = rebound(pos);473ox = pos[0] - x2;474oy = pos[1] - y2;475x2 = pos[0];476y2 = pos[1];477}478//}}}479function getOffset() //{{{480{481return [ox, oy];482}483//}}}484function moveOffset(offset) //{{{485{486var ox = offset[0],487oy = offset[1];488489if (0 > x1 + ox) {490ox -= ox + x1;491}492if (0 > y1 + oy) {493oy -= oy + y1;494}495496if (boundy < y2 + oy) {497oy += boundy - (y2 + oy);498}499if (boundx < x2 + ox) {500ox += boundx - (x2 + ox);501}502503x1 += ox;504x2 += ox;505y1 += oy;506y2 += oy;507}508//}}}509function getCorner(ord) //{{{510{511var c = getFixed();512switch (ord) {513case 'ne':514return [c.x2, c.y];515case 'nw':516return [c.x, c.y];517case 'se':518return [c.x2, c.y2];519case 'sw':520return [c.x, c.y2];521}522}523//}}}524function getFixed() //{{{525{526if (!options.aspectRatio) {527return getRect();528}529// This function could use some optimization I think...530var aspect = options.aspectRatio,531min_x = options.minSize[0] / xscale,532533534//min_y = options.minSize[1]/yscale,535max_x = options.maxSize[0] / xscale,536max_y = options.maxSize[1] / yscale,537rw = x2 - x1,538rh = y2 - y1,539rwa = Math.abs(rw),540rha = Math.abs(rh),541real_ratio = rwa / rha,542xx, yy, w, h;543544if (max_x === 0) {545max_x = boundx * 10;546}547if (max_y === 0) {548max_y = boundy * 10;549}550if (real_ratio < aspect) {551yy = y2;552w = rha * aspect;553xx = rw < 0 ? x1 - w : w + x1;554555if (xx < 0) {556xx = 0;557h = Math.abs((xx - x1) / aspect);558yy = rh < 0 ? y1 - h : h + y1;559} else if (xx > boundx) {560xx = boundx;561h = Math.abs((xx - x1) / aspect);562yy = rh < 0 ? y1 - h : h + y1;563}564} else {565xx = x2;566h = rwa / aspect;567yy = rh < 0 ? y1 - h : y1 + h;568if (yy < 0) {569yy = 0;570w = Math.abs((yy - y1) * aspect);571xx = rw < 0 ? x1 - w : w + x1;572} else if (yy > boundy) {573yy = boundy;574w = Math.abs(yy - y1) * aspect;575xx = rw < 0 ? x1 - w : w + x1;576}577}578579// Magic %-)580if (xx > x1) { // right side581if (xx - x1 < min_x) {582xx = x1 + min_x;583} else if (xx - x1 > max_x) {584xx = x1 + max_x;585}586if (yy > y1) {587yy = y1 + (xx - x1) / aspect;588} else {589yy = y1 - (xx - x1) / aspect;590}591} else if (xx < x1) { // left side592if (x1 - xx < min_x) {593xx = x1 - min_x;594} else if (x1 - xx > max_x) {595xx = x1 - max_x;596}597if (yy > y1) {598yy = y1 + (x1 - xx) / aspect;599} else {600yy = y1 - (x1 - xx) / aspect;601}602}603604if (xx < 0) {605x1 -= xx;606xx = 0;607} else if (xx > boundx) {608x1 -= xx - boundx;609xx = boundx;610}611612if (yy < 0) {613y1 -= yy;614yy = 0;615} else if (yy > boundy) {616y1 -= yy - boundy;617yy = boundy;618}619620return makeObj(flipCoords(x1, y1, xx, yy));621}622//}}}623function rebound(p) //{{{624{625if (p[0] < 0) p[0] = 0;626if (p[1] < 0) p[1] = 0;627628if (p[0] > boundx) p[0] = boundx;629if (p[1] > boundy) p[1] = boundy;630631return [Math.round(p[0]), Math.round(p[1])];632}633//}}}634function flipCoords(x1, y1, x2, y2) //{{{635{636var xa = x1,637xb = x2,638ya = y1,639yb = y2;640if (x2 < x1) {641xa = x2;642xb = x1;643}644if (y2 < y1) {645ya = y2;646yb = y1;647}648return [xa, ya, xb, yb];649}650//}}}651function getRect() //{{{652{653var xsize = x2 - x1,654ysize = y2 - y1,655delta;656657if (xlimit && (Math.abs(xsize) > xlimit)) {658x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit);659}660if (ylimit && (Math.abs(ysize) > ylimit)) {661y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit);662}663664if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) {665y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale);666}667if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) {668x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale);669}670671if (x1 < 0) {672x2 -= x1;673x1 -= x1;674}675if (y1 < 0) {676y2 -= y1;677y1 -= y1;678}679if (x2 < 0) {680x1 -= x2;681x2 -= x2;682}683if (y2 < 0) {684y1 -= y2;685y2 -= y2;686}687if (x2 > boundx) {688delta = x2 - boundx;689x1 -= delta;690x2 -= delta;691}692if (y2 > boundy) {693delta = y2 - boundy;694y1 -= delta;695y2 -= delta;696}697if (x1 > boundx) {698delta = x1 - boundy;699y2 -= delta;700y1 -= delta;701}702if (y1 > boundy) {703delta = y1 - boundy;704y2 -= delta;705y1 -= delta;706}707708return makeObj(flipCoords(x1, y1, x2, y2));709}710//}}}711function makeObj(a) //{{{712{713return {714x: a[0],715y: a[1],716x2: a[2],717y2: a[3],718w: a[2] - a[0],719h: a[3] - a[1]720};721}722//}}}723724return {725flipCoords: flipCoords,726setPressed: setPressed,727setCurrent: setCurrent,728getOffset: getOffset,729moveOffset: moveOffset,730getCorner: getCorner,731getFixed: getFixed732};733}());734735//}}}736// Shade Module {{{737var Shade = (function() {738var enabled = false,739holder = $('<div />').css({740position: 'absolute',741zIndex: 240,742opacity: 0743}),744shades = {745top: createShade(),746left: createShade().height(boundy),747right: createShade().height(boundy),748bottom: createShade()749};750751function resizeShades(w,h) {752shades.left.css({ height: px(h) });753shades.right.css({ height: px(h) });754}755function updateAuto()756{757return updateShade(Coords.getFixed());758}759function updateShade(c)760{761shades.top.css({762left: px(c.x),763width: px(c.w),764height: px(c.y)765});766shades.bottom.css({767top: px(c.y2),768left: px(c.x),769width: px(c.w),770height: px(boundy-c.y2)771});772shades.right.css({773left: px(c.x2),774width: px(boundx-c.x2)775});776shades.left.css({777width: px(c.x)778});779}780function createShade() {781return $('<div />').css({782position: 'absolute',783backgroundColor: options.shadeColor||options.bgColor784}).appendTo(holder);785}786function enableShade() {787if (!enabled) {788enabled = true;789holder.insertBefore($img);790updateAuto();791Selection.setBgOpacity(1,0,1);792$img2.hide();793794setBgColor(options.shadeColor||options.bgColor,1);795if (Selection.isAwake())796{797setOpacity(options.bgOpacity,1);798}799else setOpacity(1,1);800}801}802function setBgColor(color,now) {803colorChangeMacro(getShades(),color,now);804}805function disableShade() {806if (enabled) {807holder.remove();808$img2.show();809enabled = false;810if (Selection.isAwake()) {811Selection.setBgOpacity(options.bgOpacity,1,1);812} else {813Selection.setBgOpacity(1,1,1);814Selection.disableHandles();815}816colorChangeMacro($div,0,1);817}818}819function setOpacity(opacity,now) {820if (enabled) {821if (options.bgFade && !now) {822holder.animate({823opacity: 1-opacity824},{825queue: false,826duration: options.fadeTime827});828}829else holder.css({opacity:1-opacity});830}831}832function refreshAll() {833options.shade ? enableShade() : disableShade();834if (Selection.isAwake()) setOpacity(options.bgOpacity);835}836function getShades() {837return holder.children();838}839840return {841update: updateAuto,842updateRaw: updateShade,843getShades: getShades,844setBgColor: setBgColor,845enable: enableShade,846disable: disableShade,847resize: resizeShades,848refresh: refreshAll,849opacity: setOpacity850};851}());852// }}}853// Selection Module {{{854var Selection = (function () {855var awake,856hdep = 370,857borders = {},858handle = {},859dragbar = {},860seehandles = false;861862// Private Methods863function insertBorder(type) //{{{864{865var jq = $('<div />').css({866position: 'absolute',867opacity: options.borderOpacity868}).addClass(cssClass(type));869$img_holder.append(jq);870return jq;871}872//}}}873function dragDiv(ord, zi) //{{{874{875var jq = $('<div />').mousedown(createDragger(ord)).css({876cursor: ord + '-resize',877position: 'absolute',878zIndex: zi879}).addClass('ord-'+ord);880881if (Touch.support) {882jq.bind('touchstart.jcrop', Touch.createDragger(ord));883}884885$hdl_holder.append(jq);886return jq;887}888//}}}889function insertHandle(ord) //{{{890{891var hs = options.handleSize,892893div = dragDiv(ord, hdep++).css({894opacity: options.handleOpacity895}).addClass(cssClass('handle'));896897if (hs) { div.width(hs).height(hs); }898899return div;900}901//}}}902function insertDragbar(ord) //{{{903{904return dragDiv(ord, hdep++).addClass('jcrop-dragbar');905}906//}}}907function createDragbars(li) //{{{908{909var i;910for (i = 0; i < li.length; i++) {911dragbar[li[i]] = insertDragbar(li[i]);912}913}914//}}}915function createBorders(li) //{{{916{917var cl,i;918for (i = 0; i < li.length; i++) {919switch(li[i]){920case'n': cl='hline'; break;921case's': cl='hline bottom'; break;922case'e': cl='vline right'; break;923case'w': cl='vline'; break;924}925borders[li[i]] = insertBorder(cl);926}927}928//}}}929function createHandles(li) //{{{930{931var i;932for (i = 0; i < li.length; i++) {933handle[li[i]] = insertHandle(li[i]);934}935}936//}}}937function moveto(x, y) //{{{938{939if (!options.shade) {940$img2.css({941top: px(-y),942left: px(-x)943});944}945$sel.css({946top: px(y),947left: px(x)948});949}950//}}}951function resize(w, h) //{{{952{953$sel.width(Math.round(w)).height(Math.round(h));954}955//}}}956function refresh() //{{{957{958var c = Coords.getFixed();959960Coords.setPressed([c.x, c.y]);961Coords.setCurrent([c.x2, c.y2]);962963updateVisible();964}965//}}}966967// Internal Methods968function updateVisible(select) //{{{969{970if (awake) {971return update(select);972}973}974//}}}975function update(select) //{{{976{977var c = Coords.getFixed();978979resize(c.w, c.h);980moveto(c.x, c.y);981if (options.shade) Shade.updateRaw(c);982983awake || show();984985if (select) {986options.onSelect.call(api, unscale(c));987} else {988options.onChange.call(api, unscale(c));989}990}991//}}}992function setBgOpacity(opacity,force,now) //{{{993{994if (!awake && !force) return;995if (options.bgFade && !now) {996$img.animate({997opacity: opacity998},{999queue: false,1000duration: options.fadeTime1001});1002} else {1003$img.css('opacity', opacity);1004}1005}1006//}}}1007function show() //{{{1008{1009$sel.show();10101011if (options.shade) Shade.opacity(bgopacity);1012else setBgOpacity(bgopacity,true);10131014awake = true;1015}1016//}}}1017function release() //{{{1018{1019disableHandles();1020$sel.hide();10211022if (options.shade) Shade.opacity(1);1023else setBgOpacity(1);10241025awake = false;1026options.onRelease.call(api);1027}1028//}}}1029function showHandles() //{{{1030{1031if (seehandles) {1032$hdl_holder.show();1033}1034}1035//}}}1036function enableHandles() //{{{1037{1038seehandles = true;1039if (options.allowResize) {1040$hdl_holder.show();1041return true;1042}1043}1044//}}}1045function disableHandles() //{{{1046{1047seehandles = false;1048$hdl_holder.hide();1049}1050//}}}1051function animMode(v) //{{{1052{1053if (v) {1054animating = true;1055disableHandles();1056} else {1057animating = false;1058enableHandles();1059}1060}1061//}}}1062function done() //{{{1063{1064animMode(false);1065refresh();1066}1067//}}}1068// Insert draggable elements {{{1069// Insert border divs for outline10701071if (options.dragEdges && $.isArray(options.createDragbars))1072createDragbars(options.createDragbars);10731074if ($.isArray(options.createHandles))1075createHandles(options.createHandles);10761077if (options.drawBorders && $.isArray(options.createBorders))1078createBorders(options.createBorders);10791080//}}}10811082// This is a hack for iOS5 to support drag/move touch functionality1083$(document).bind('touchstart.jcrop-ios',function(e) {1084if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation();1085});10861087var $track = newTracker().mousedown(createDragger('move')).css({1088cursor: 'move',1089position: 'absolute',1090zIndex: 3601091});10921093if (Touch.support) {1094$track.bind('touchstart.jcrop', Touch.createDragger('move'));1095}10961097$img_holder.append($track);1098disableHandles();10991100return {1101updateVisible: updateVisible,1102update: update,1103release: release,1104refresh: refresh,1105isAwake: function () {1106return awake;1107},1108setCursor: function (cursor) {1109$track.css('cursor', cursor);1110},1111enableHandles: enableHandles,1112enableOnly: function () {1113seehandles = true;1114},1115showHandles: showHandles,1116disableHandles: disableHandles,1117animMode: animMode,1118setBgOpacity: setBgOpacity,1119done: done1120};1121}());11221123//}}}1124// Tracker Module {{{1125var Tracker = (function () {1126var onMove = function () {},1127onDone = function () {},1128trackDoc = options.trackDocument;11291130function toFront(touch) //{{{1131{1132$trk.css({1133zIndex: 4501134});11351136if (touch)1137$(document)1138.bind('touchmove.jcrop', trackTouchMove)1139.bind('touchend.jcrop', trackTouchEnd);11401141else if (trackDoc)1142$(document)1143.bind('mousemove.jcrop',trackMove)1144.bind('mouseup.jcrop',trackUp);1145}1146//}}}1147function toBack() //{{{1148{1149$trk.css({1150zIndex: 2901151});1152$(document).unbind('.jcrop');1153}1154//}}}1155function trackMove(e) //{{{1156{1157onMove(mouseAbs(e));1158return false;1159}1160//}}}1161function trackUp(e) //{{{1162{1163e.preventDefault();1164e.stopPropagation();11651166if (btndown) {1167btndown = false;11681169onDone(mouseAbs(e));11701171if (Selection.isAwake()) {1172options.onSelect.call(api, unscale(Coords.getFixed()));1173}11741175toBack();1176onMove = function () {};1177onDone = function () {};1178}11791180return false;1181}1182//}}}1183function activateHandlers(move, done, touch) //{{{1184{1185btndown = true;1186onMove = move;1187onDone = done;1188toFront(touch);1189return false;1190}1191//}}}1192function trackTouchMove(e) //{{{1193{1194onMove(mouseAbs(Touch.cfilter(e)));1195return false;1196}1197//}}}1198function trackTouchEnd(e) //{{{1199{1200return trackUp(Touch.cfilter(e));1201}1202//}}}1203function setCursor(t) //{{{1204{1205$trk.css('cursor', t);1206}1207//}}}12081209if (!trackDoc) {1210$trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);1211}12121213$img.before($trk);1214return {1215activateHandlers: activateHandlers,1216setCursor: setCursor1217};1218}());1219//}}}1220// KeyManager Module {{{1221var KeyManager = (function () {1222var $keymgr = $('<input type="radio" />').css({1223position: 'fixed',1224left: '-120px',1225width: '12px'1226}).addClass('jcrop-keymgr'),12271228$keywrap = $('<div />').css({1229position: 'absolute',1230overflow: 'hidden'1231}).append($keymgr);12321233function watchKeys() //{{{1234{1235if (options.keySupport) {1236$keymgr.show();1237$keymgr.focus();1238}1239}1240//}}}1241function onBlur(e) //{{{1242{1243$keymgr.hide();1244}1245//}}}1246function doNudge(e, x, y) //{{{1247{1248if (options.allowMove) {1249Coords.moveOffset([x, y]);1250Selection.updateVisible(true);1251}1252e.preventDefault();1253e.stopPropagation();1254}1255//}}}1256function parseKey(e) //{{{1257{1258if (e.ctrlKey || e.metaKey) {1259return true;1260}1261shift_down = e.shiftKey ? true : false;1262var nudge = shift_down ? 10 : 1;12631264switch (e.keyCode) {1265case 37:1266doNudge(e, -nudge, 0);1267break;1268case 39:1269doNudge(e, nudge, 0);1270break;1271case 38:1272doNudge(e, 0, -nudge);1273break;1274case 40:1275doNudge(e, 0, nudge);1276break;1277case 27:1278if (options.allowSelect) Selection.release();1279break;1280case 9:1281return true;1282}12831284return false;1285}1286//}}}12871288if (options.keySupport) {1289$keymgr.keydown(parseKey).blur(onBlur);1290if (ie6mode || !options.fixedSupport) {1291$keymgr.css({1292position: 'absolute',1293left: '-20px'1294});1295$keywrap.append($keymgr).insertBefore($img);1296} else {1297$keymgr.insertBefore($img);1298}1299}130013011302return {1303watchKeys: watchKeys1304};1305}());1306//}}}1307// }}}1308// API methods {{{1309function setClass(cname) //{{{1310{1311$div.removeClass().addClass(cssClass('holder')).addClass(cname);1312}1313//}}}1314function animateTo(a, callback) //{{{1315{1316var x1 = a[0] / xscale,1317y1 = a[1] / yscale,1318x2 = a[2] / xscale,1319y2 = a[3] / yscale;13201321if (animating) {1322return;1323}13241325var animto = Coords.flipCoords(x1, y1, x2, y2),1326c = Coords.getFixed(),1327initcr = [c.x, c.y, c.x2, c.y2],1328animat = initcr,1329interv = options.animationDelay,1330ix1 = animto[0] - initcr[0],1331iy1 = animto[1] - initcr[1],1332ix2 = animto[2] - initcr[2],1333iy2 = animto[3] - initcr[3],1334pcent = 0,1335velocity = options.swingSpeed;13361337x1 = animat[0];1338y1 = animat[1];1339x2 = animat[2];1340y2 = animat[3];13411342Selection.animMode(true);1343var anim_timer;13441345function queueAnimator() {1346window.setTimeout(animator, interv);1347}1348var animator = (function () {1349return function () {1350pcent += (100 - pcent) / velocity;13511352animat[0] = Math.round(x1 + ((pcent / 100) * ix1));1353animat[1] = Math.round(y1 + ((pcent / 100) * iy1));1354animat[2] = Math.round(x2 + ((pcent / 100) * ix2));1355animat[3] = Math.round(y2 + ((pcent / 100) * iy2));13561357if (pcent >= 99.8) {1358pcent = 100;1359}1360if (pcent < 100) {1361setSelectRaw(animat);1362queueAnimator();1363} else {1364Selection.done();1365Selection.animMode(false);1366if (typeof(callback) === 'function') {1367callback.call(api);1368}1369}1370};1371}());1372queueAnimator();1373}1374//}}}1375function setSelect(rect) //{{{1376{1377setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]);1378options.onSelect.call(api, unscale(Coords.getFixed()));1379Selection.enableHandles();1380}1381//}}}1382function setSelectRaw(l) //{{{1383{1384Coords.setPressed([l[0], l[1]]);1385Coords.setCurrent([l[2], l[3]]);1386Selection.update();1387}1388//}}}1389function tellSelect() //{{{1390{1391return unscale(Coords.getFixed());1392}1393//}}}1394function tellScaled() //{{{1395{1396return Coords.getFixed();1397}1398//}}}1399function setOptionsNew(opt) //{{{1400{1401setOptions(opt);1402interfaceUpdate();1403}1404//}}}1405function disableCrop() //{{{1406{1407options.disabled = true;1408Selection.disableHandles();1409Selection.setCursor('default');1410Tracker.setCursor('default');1411}1412//}}}1413function enableCrop() //{{{1414{1415options.disabled = false;1416interfaceUpdate();1417}1418//}}}1419function cancelCrop() //{{{1420{1421Selection.done();1422Tracker.activateHandlers(null, null);1423}1424//}}}1425function destroy() //{{{1426{1427$div.remove();1428$origimg.show();1429$origimg.css('visibility','visible');1430$(obj).removeData('Jcrop');1431}1432//}}}1433function setImage(src, callback) //{{{1434{1435Selection.release();1436disableCrop();1437var img = new Image();1438img.onload = function () {1439var iw = img.width;1440var ih = img.height;1441var bw = options.boxWidth;1442var bh = options.boxHeight;1443$img.width(iw).height(ih);1444$img.attr('src', src);1445$img2.attr('src', src);1446presize($img, bw, bh);1447boundx = $img.width();1448boundy = $img.height();1449$img2.width(boundx).height(boundy);1450$trk.width(boundx + (bound * 2)).height(boundy + (bound * 2));1451$div.width(boundx).height(boundy);1452Shade.resize(boundx,boundy);1453enableCrop();14541455if (typeof(callback) === 'function') {1456callback.call(api);1457}1458};1459img.src = src;1460}1461//}}}1462function colorChangeMacro($obj,color,now) {1463var mycolor = color || options.bgColor;1464if (options.bgFade && supportsColorFade() && options.fadeTime && !now) {1465$obj.animate({1466backgroundColor: mycolor1467}, {1468queue: false,1469duration: options.fadeTime1470});1471} else {1472$obj.css('backgroundColor', mycolor);1473}1474}1475function interfaceUpdate(alt) //{{{1476// This method tweaks the interface based on options object.1477// Called when options are changed and at end of initialization.1478{1479if (options.allowResize) {1480if (alt) {1481Selection.enableOnly();1482} else {1483Selection.enableHandles();1484}1485} else {1486Selection.disableHandles();1487}14881489Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default');1490Selection.setCursor(options.allowMove ? 'move' : 'default');14911492if (options.hasOwnProperty('trueSize')) {1493xscale = options.trueSize[0] / boundx;1494yscale = options.trueSize[1] / boundy;1495}14961497if (options.hasOwnProperty('setSelect')) {1498setSelect(options.setSelect);1499Selection.done();1500delete(options.setSelect);1501}15021503Shade.refresh();15041505if (options.bgColor != bgcolor) {1506colorChangeMacro(1507options.shade? Shade.getShades(): $div,1508options.shade?1509(options.shadeColor || options.bgColor):1510options.bgColor1511);1512bgcolor = options.bgColor;1513}15141515if (bgopacity != options.bgOpacity) {1516bgopacity = options.bgOpacity;1517if (options.shade) Shade.refresh();1518else Selection.setBgOpacity(bgopacity);1519}15201521xlimit = options.maxSize[0] || 0;1522ylimit = options.maxSize[1] || 0;1523xmin = options.minSize[0] || 0;1524ymin = options.minSize[1] || 0;15251526if (options.hasOwnProperty('outerImage')) {1527$img.attr('src', options.outerImage);1528delete(options.outerImage);1529}15301531Selection.refresh();1532}1533//}}}1534//}}}15351536if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection);15371538$hdl_holder.hide();1539interfaceUpdate(true);15401541var api = {1542setImage: setImage,1543animateTo: animateTo,1544setSelect: setSelect,1545setOptions: setOptionsNew,1546tellSelect: tellSelect,1547tellScaled: tellScaled,1548setClass: setClass,15491550disable: disableCrop,1551enable: enableCrop,1552cancel: cancelCrop,1553release: Selection.release,1554destroy: destroy,15551556focus: KeyManager.watchKeys,15571558getBounds: function () {1559return [boundx * xscale, boundy * yscale];1560},1561getWidgetSize: function () {1562return [boundx, boundy];1563},1564getScaleFactor: function () {1565return [xscale, yscale];1566},1567getOptions: function() {1568// careful: internal values are returned1569return options;1570},15711572ui: {1573holder: $div,1574selection: $sel1575}1576};15771578if (is_msie) $div.bind('selectstart', function () { return false; });15791580$origimg.data('Jcrop', api);1581return api;1582};1583$.fn.Jcrop = function (options, callback) //{{{1584{1585var api;1586// Iterate over each object, attach Jcrop1587this.each(function () {1588// If we've already attached to this object1589if ($(this).data('Jcrop')) {1590// The API can be requested this way (undocumented)1591if (options === 'api') return $(this).data('Jcrop');1592// Otherwise, we just reset the options...1593else $(this).data('Jcrop').setOptions(options);1594}1595// If we haven't been attached, preload and attach1596else {1597if (this.tagName == 'IMG')1598$.Jcrop.Loader(this,function(){1599$(this).css({display:'block',visibility:'hidden'});1600api = $.Jcrop(this, options);1601if ($.isFunction(callback)) callback.call(api);1602});1603else {1604$(this).css({display:'block',visibility:'hidden'});1605api = $.Jcrop(this, options);1606if ($.isFunction(callback)) callback.call(api);1607}1608}1609});16101611// Return "this" so the object is chainable (jQuery-style)1612return this;1613};1614//}}}1615// $.Jcrop.Loader - basic image loader {{{16161617$.Jcrop.Loader = function(imgobj,success,error){1618var $img = $(imgobj), img = $img[0];16191620function completeCheck(){1621if (img.complete) {1622$img.unbind('.jcloader');1623if ($.isFunction(success)) success.call(img);1624}1625else window.setTimeout(completeCheck,50);1626}16271628$img1629.bind('load.jcloader',completeCheck)1630.bind('error.jcloader',function(e){1631$img.unbind('.jcloader');1632if ($.isFunction(error)) error.call(img);1633});16341635if (img.complete && $.isFunction(success)){1636$img.unbind('.jcloader');1637success.call(img);1638}1639};16401641//}}}1642// Global Defaults {{{1643$.Jcrop.defaults = {16441645// Basic Settings1646allowSelect: true,1647allowMove: true,1648allowResize: true,16491650trackDocument: true,16511652// Styling Options1653baseClass: 'jcrop',1654addClass: null,1655bgColor: 'black',1656bgOpacity: 0.6,1657bgFade: false,1658borderOpacity: 0.4,1659handleOpacity: 0.5,1660handleSize: null,16611662aspectRatio: 0,1663keySupport: true,1664createHandles: ['n','s','e','w','nw','ne','se','sw'],1665createDragbars: ['n','s','e','w'],1666createBorders: ['n','s','e','w'],1667drawBorders: true,1668dragEdges: true,1669fixedSupport: true,1670touchSupport: null,16711672shade: null,16731674boxWidth: 0,1675boxHeight: 0,1676boundary: 2,1677fadeTime: 400,1678animationDelay: 20,1679swingSpeed: 3,16801681minSelect: [0, 0],1682maxSize: [0, 0],1683minSize: [0, 0],16841685// Callbacks / Event Handlers1686onChange: function () {},1687onSelect: function () {},1688onDblClick: function () {},1689onRelease: function () {}1690};16911692// }}}1693}(jQuery));169416951696