123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859 |
- /*! Jcrop.js v2.0.4 - build: 20151117
- * @copyright 2008-2015 Tapmodo Interactive LLC
- * @license Free software under MIT License
- * @website http://jcrop.org/
- **/
- (function($){
- 'use strict';
- // Jcrop constructor
- var Jcrop = function(element,opt){
- var _ua = navigator.userAgent.toLowerCase();
- this.opt = $.extend({},Jcrop.defaults,opt || {});
- this.container = $(element);
- this.opt.is_msie = /msie/.test(_ua);
- this.opt.is_ie_lt9 = /msie [1-8]\./.test(_ua);
- this.container.addClass(this.opt.css_container);
- this.ui = {};
- this.state = null;
- this.ui.multi = [];
- this.ui.selection = null;
- this.filter = {};
- this.init();
- this.setOptions(opt);
- this.applySizeConstraints();
- this.container.trigger('cropinit',this);
-
- // IE<9 doesn't work if mouse events are attached to window
- if (this.opt.is_ie_lt9)
- this.opt.dragEventTarget = document.body;
- };
- // Jcrop static functions
- $.extend(Jcrop,{
- component: { },
- filter: { },
- stage: { },
- registerComponent: function(name,component){
- Jcrop.component[name] = component;
- },
- registerFilter: function(name,filter){
- Jcrop.filter[name] = filter;
- },
- registerStageType: function(name,stage){
- Jcrop.stage[name] = stage;
- },
- // attach: function(element,opt){{{
- attach: function(element,opt){
- var obj = new $.Jcrop(element,opt);
- return obj;
- },
- // }}}
- // imgCopy: function(imgel){{{
- imgCopy: function(imgel){
- var img = new Image;
- img.src = imgel.src;
- return img;
- },
- // }}}
- // imageClone: function(imgel){{{
- imageClone: function(imgel){
- return $.Jcrop.supportsCanvas?
- Jcrop.canvasClone(imgel):
- Jcrop.imgCopy(imgel);
- },
- // }}}
- // canvasClone: function(imgel){{{
- canvasClone: function(imgel){
- var canvas = document.createElement('canvas'),
- ctx = canvas.getContext('2d');
- $(canvas).width(imgel.width).height(imgel.height),
- canvas.width = imgel.naturalWidth;
- canvas.height = imgel.naturalHeight;
- ctx.drawImage(imgel,0,0,imgel.naturalWidth,imgel.naturalHeight);
- return canvas;
- },
- // }}}
- // propagate: function(plist,config,obj){{{
- propagate: function(plist,config,obj){
- for(var i=0,l=plist.length;i<l;i++)
- if (config.hasOwnProperty(plist[i]))
- obj[plist[i]] = config[plist[i]];
- },
- // }}}
- // getLargestBox: function(ratio,w,h){{{
- getLargestBox: function(ratio,w,h){
- if ((w/h) > ratio)
- return [ h * ratio, h ];
- else return [ w, w / ratio ];
- },
- // }}}
- // stageConstructor: function(el,options,callback){{{
- stageConstructor: function(el,options,callback){
- // Get a priority-ordered list of available stages
- var stages = [];
- $.each(Jcrop.stage,function(i,e){
- stages.push(e);
- });
- stages.sort(function(a,b){ return a.priority - b.priority; });
- // Find the first one that supports this element
- for(var i=0,l=stages.length;i<l;i++){
- if (stages[i].isSupported(el,options)){
- stages[i].create(el,options,function(obj,opt){
- if (typeof callback == 'function') callback(obj,opt);
- });
- break;
- }
- }
- },
- // }}}
- // supportsColorFade: function(){{{
- supportsColorFade: function(){
- return $.fx.step.hasOwnProperty('backgroundColor');
- },
- // }}}
- // wrapFromXywh: function(xywh){{{
- wrapFromXywh: function(xywh){
- var b = { x: xywh[0], y: xywh[1], w: xywh[2], h: xywh[3] };
- b.x2 = b.x + b.w;
- b.y2 = b.y + b.h;
- return b;
- }
- // }}}
- });
- var AbstractStage = function(){
- };
- $.extend(AbstractStage,{
- isSupported: function(el,o){
- // @todo: should actually check if it's an HTML element
- return true;
- },
- // A higher priority means less desirable
- // AbstractStage is the last one we want to use
- priority: 100,
- create: function(el,options,callback){
- var obj = new AbstractStage;
- obj.element = el;
- callback.call(this,obj,options);
- },
- prototype: {
- attach: function(core){
- this.init(core);
- core.ui.stage = this;
- },
- triggerEvent: function(ev){
- $(this.element).trigger(ev);
- return this;
- },
- getElement: function(){
- return this.element;
- }
- }
- });
- Jcrop.registerStageType('Block',AbstractStage);
- var ImageStage = function(){
- };
- ImageStage.prototype = new AbstractStage();
- $.extend(ImageStage,{
- isSupported: function(el,o){
- if (el.tagName == 'IMG') return true;
- },
- priority: 90,
- create: function(el,options,callback){
- $.Jcrop.component.ImageLoader.attach(el,function(w,h){
- var obj = new ImageStage;
- obj.element = $(el).wrap('<div />').parent();
- obj.element.width(w).height(h);
- obj.imgsrc = el;
- if (typeof callback == 'function')
- callback.call(this,obj,options);
- });
- }
- });
- Jcrop.registerStageType('Image',ImageStage);
- var CanvasStage = function(){
- this.angle = 0;
- this.scale = 1;
- this.scaleMin = 0.2;
- this.scaleMax = 1.25;
- this.offset = [0,0];
- };
- CanvasStage.prototype = new ImageStage();
- $.extend(CanvasStage,{
- isSupported: function(el,o){
- if ($.Jcrop.supportsCanvas && (el.tagName == 'IMG')) return true;
- },
- priority: 60,
- create: function(el,options,callback){
- var $el = $(el);
- var opt = $.extend({},options);
- $.Jcrop.component.ImageLoader.attach(el,function(w,h){
- var obj = new CanvasStage;
- $el.hide();
- obj.createCanvas(el,w,h);
- $el.before(obj.element);
- obj.imgsrc = el;
- opt.imgsrc = el;
- if (typeof callback == 'function'){
- callback(obj,opt);
- obj.redraw();
- }
- });
- }
- });
- $.extend(CanvasStage.prototype,{
- init: function(core){
- this.core = core;
- },
- // setOffset: function(x,y) {{{
- setOffset: function(x,y) {
- this.offset = [x,y];
- return this;
- },
- // }}}
- // setAngle: function(v) {{{
- setAngle: function(v) {
- this.angle = v;
- return this;
- },
- // }}}
- // setScale: function(v) {{{
- setScale: function(v) {
- this.scale = this.boundScale(v);
- return this;
- },
- // }}}
- boundScale: function(v){
- if (v<this.scaleMin) v = this.scaleMin;
- else if (v>this.scaleMax) v = this.scaleMax;
- return v;
- },
- createCanvas: function(img,w,h){
- this.width = w;
- this.height = h;
- this.canvas = document.createElement('canvas');
- this.canvas.width = w;
- this.canvas.height = h;
- this.$canvas = $(this.canvas).width('100%').height('100%');
- this.context = this.canvas.getContext('2d');
- this.fillstyle = "rgb(0,0,0)";
- this.element = this.$canvas.wrap('<div />').parent().width(w).height(h);
- },
- triggerEvent: function(ev){
- this.$canvas.trigger(ev);
- return this;
- },
- // clear: function() {{{
- clear: function() {
- this.context.fillStyle = this.fillstyle;
- this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
- return this;
- },
- // }}}
- // redraw: function() {{{
- redraw: function() {
- // Save the current context
- this.context.save();
- this.clear();
- // Translate to the center point of our image
- this.context.translate(parseInt(this.width * 0.5), parseInt(this.height * 0.5));
- // Perform the rotation and scaling
- this.context.translate(this.offset[0]/this.core.opt.xscale,this.offset[1]/this.core.opt.yscale);
- this.context.rotate(this.angle * (Math.PI/180));
- this.context.scale(this.scale,this.scale);
- // Translate back to the top left of our image
- this.context.translate(-parseInt(this.width * 0.5), -parseInt(this.height * 0.5));
- // Finally we draw the image
- this.context.drawImage(this.imgsrc,0,0,this.width,this.height);
- // And restore the updated context
- this.context.restore();
- this.$canvas.trigger('cropredraw');
- return this;
- },
- // }}}
- // setFillStyle: function(v) {{{
- setFillStyle: function(v) {
- this.fillstyle = v;
- return this;
- }
- // }}}
- });
- Jcrop.registerStageType('Canvas',CanvasStage);
- /**
- * BackoffFilter
- * move out-of-bounds selection into allowed position at same size
- */
- var BackoffFilter = function(){
- this.minw = 40;
- this.minh = 40;
- this.maxw = 0;
- this.maxh = 0;
- this.core = null;
- };
- $.extend(BackoffFilter.prototype,{
- tag: 'backoff',
- priority: 22,
- filter: function(b){
- var r = this.bound;
- if (b.x < r.minx) { b.x = r.minx; b.x2 = b.w + b.x; }
- if (b.y < r.miny) { b.y = r.miny; b.y2 = b.h + b.y; }
- if (b.x2 > r.maxx) { b.x2 = r.maxx; b.x = b.x2 - b.w; }
- if (b.y2 > r.maxy) { b.y2 = r.maxy; b.y = b.y2 - b.h; }
- return b;
- },
- refresh: function(sel){
- this.elw = sel.core.container.width();
- this.elh = sel.core.container.height();
- this.bound = {
- minx: 0 + sel.edge.w,
- miny: 0 + sel.edge.n,
- maxx: this.elw + sel.edge.e,
- maxy: this.elh + sel.edge.s
- };
- }
- });
- Jcrop.registerFilter('backoff',BackoffFilter);
- /**
- * ConstrainFilter
- * a filter to constrain crop selection to bounding element
- */
- var ConstrainFilter = function(){
- this.core = null;
- };
- $.extend(ConstrainFilter.prototype,{
- tag: 'constrain',
- priority: 5,
- filter: function(b,ord){
- if (ord == 'move') {
- if (b.x < this.minx) { b.x = this.minx; b.x2 = b.w + b.x; }
- if (b.y < this.miny) { b.y = this.miny; b.y2 = b.h + b.y; }
- if (b.x2 > this.maxx) { b.x2 = this.maxx; b.x = b.x2 - b.w; }
- if (b.y2 > this.maxy) { b.y2 = this.maxy; b.y = b.y2 - b.h; }
- } else {
- if (b.x < this.minx) { b.x = this.minx; }
- if (b.y < this.miny) { b.y = this.miny; }
- if (b.x2 > this.maxx) { b.x2 = this.maxx; }
- if (b.y2 > this.maxy) { b.y2 = this.maxy; }
- }
- b.w = b.x2 - b.x;
- b.h = b.y2 - b.y;
- return b;
- },
- refresh: function(sel){
- this.elw = sel.core.container.width();
- this.elh = sel.core.container.height();
- this.minx = 0 + sel.edge.w;
- this.miny = 0 + sel.edge.n;
- this.maxx = this.elw + sel.edge.e;
- this.maxy = this.elh + sel.edge.s;
- }
- });
- Jcrop.registerFilter('constrain',ConstrainFilter);
- /**
- * ExtentFilter
- * a filter to implement minimum or maximum size
- */
- var ExtentFilter = function(){
- this.core = null;
- };
- $.extend(ExtentFilter.prototype,{
- tag: 'extent',
- priority: 12,
- offsetFromCorner: function(corner,box,b){
- var w = box[0], h = box[1];
- switch(corner){
- case 'bl': return [ b.x2 - w, b.y, w, h ];
- case 'tl': return [ b.x2 - w , b.y2 - h, w, h ];
- case 'br': return [ b.x, b.y, w, h ];
- case 'tr': return [ b.x, b.y2 - h, w, h ];
- }
- },
- getQuadrant: function(s){
- var relx = s.opposite[0]-s.offsetx
- var rely = s.opposite[1]-s.offsety;
- if ((relx < 0) && (rely < 0)) return 'br';
- else if ((relx >= 0) && (rely >= 0)) return 'tl';
- else if ((relx < 0) && (rely >= 0)) return 'tr';
- return 'bl';
- },
- filter: function(b,ord,sel){
- if (ord == 'move') return b;
- var w = b.w, h = b.h, st = sel.state, r = this.limits;
- var quad = st? this.getQuadrant(st): 'br';
- if (r.minw && (w < r.minw)) w = r.minw;
- if (r.minh && (h < r.minh)) h = r.minh;
- if (r.maxw && (w > r.maxw)) w = r.maxw;
- if (r.maxh && (h > r.maxh)) h = r.maxh;
- if ((w == b.w) && (h == b.h)) return b;
- return Jcrop.wrapFromXywh(this.offsetFromCorner(quad,[w,h],b));
- },
- refresh: function(sel){
- this.elw = sel.core.container.width();
- this.elh = sel.core.container.height();
- this.limits = {
- minw: sel.minSize[0],
- minh: sel.minSize[1],
- maxw: sel.maxSize[0],
- maxh: sel.maxSize[1]
- };
- }
- });
- Jcrop.registerFilter('extent',ExtentFilter);
- /**
- * GridFilter
- * a rudimentary grid effect
- */
- var GridFilter = function(){
- this.stepx = 1;
- this.stepy = 1;
- this.core = null;
- };
- $.extend(GridFilter.prototype,{
- tag: 'grid',
- priority: 19,
- filter: function(b){
-
- var n = {
- x: Math.round(b.x / this.stepx) * this.stepx,
- y: Math.round(b.y / this.stepy) * this.stepy,
- x2: Math.round(b.x2 / this.stepx) * this.stepx,
- y2: Math.round(b.y2 / this.stepy) * this.stepy
- };
-
- n.w = n.x2 - n.x;
- n.h = n.y2 - n.y;
- return n;
- }
- });
- Jcrop.registerFilter('grid',GridFilter);
- /**
- * RatioFilter
- * implements aspectRatio locking
- */
- var RatioFilter = function(){
- this.ratio = 0;
- this.core = null;
- };
- $.extend(RatioFilter.prototype,{
- tag: 'ratio',
- priority: 15,
- offsetFromCorner: function(corner,box,b){
- var w = box[0], h = box[1];
- switch(corner){
- case 'bl': return [ b.x2 - w, b.y, w, h ];
- case 'tl': return [ b.x2 - w , b.y2 - h, w, h ];
- case 'br': return [ b.x, b.y, w, h ];
- case 'tr': return [ b.x, b.y2 - h, w, h ];
- }
- },
- getBoundRatio: function(b,quad){
- var box = Jcrop.getLargestBox(this.ratio,b.w,b.h);
- return Jcrop.wrapFromXywh(this.offsetFromCorner(quad,box,b));
- },
- getQuadrant: function(s){
- var relx = s.opposite[0]-s.offsetx
- var rely = s.opposite[1]-s.offsety;
- if ((relx < 0) && (rely < 0)) return 'br';
- else if ((relx >= 0) && (rely >= 0)) return 'tl';
- else if ((relx < 0) && (rely >= 0)) return 'tr';
- return 'bl';
- },
- filter: function(b,ord,sel){
- if (!this.ratio) return b;
- var rt = b.w / b.h;
- var st = sel.state;
- var quad = st? this.getQuadrant(st): 'br';
- ord = ord || 'se';
- if (ord == 'move') return b;
- switch(ord) {
- case 'n':
- b.x2 = this.elw;
- b.w = b.x2 - b.x;
- quad = 'tr';
- break;
- case 's':
- b.x2 = this.elw;
- b.w = b.x2 - b.x;
- quad = 'br';
- break;
- case 'e':
- b.y2 = this.elh;
- b.h = b.y2 - b.y;
- quad = 'br';
- break;
- case 'w':
- b.y2 = this.elh;
- b.h = b.y2 - b.y;
- quad = 'bl';
- break;
- }
- return this.getBoundRatio(b,quad);
- },
- refresh: function(sel){
- this.ratio = sel.aspectRatio;
- this.elw = sel.core.container.width();
- this.elh = sel.core.container.height();
- }
- });
- Jcrop.registerFilter('ratio',RatioFilter);
- /**
- * RoundFilter
- * rounds coordinate values to integers
- */
- var RoundFilter = function(){
- this.core = null;
- };
- $.extend(RoundFilter.prototype,{
- tag: 'round',
- priority: 90,
- filter: function(b){
-
- var n = {
- x: Math.round(b.x),
- y: Math.round(b.y),
- x2: Math.round(b.x2),
- y2: Math.round(b.y2)
- };
-
- n.w = n.x2 - n.x;
- n.h = n.y2 - n.y;
- return n;
- }
- });
- Jcrop.registerFilter('round',RoundFilter);
- /**
- * ShadeFilter
- * A filter that implements div-based shading on any element
- *
- * The shading you see is actually four semi-opaque divs
- * positioned inside the container, around the selection
- */
- var ShadeFilter = function(opacity,color){
- this.color = color || 'black';
- this.opacity = opacity || 0.5;
- this.core = null;
- this.shades = {};
- };
- $.extend(ShadeFilter.prototype,{
- tag: 'shader',
- fade: true,
- fadeEasing: 'swing',
- fadeSpeed: 320,
- priority: 95,
- init: function(){
- var t = this;
- if (!t.attached) {
- t.visible = false;
- t.container = $('<div />').addClass(t.core.opt.css_shades)
- .prependTo(this.core.container).hide();
- t.elh = this.core.container.height();
- t.elw = this.core.container.width();
- t.shades = {
- top: t.createShade(),
- right: t.createShade(),
- left: t.createShade(),
- bottom: t.createShade()
- };
- t.attached = true;
- }
- },
- destroy: function(){
- this.container.remove();
- },
- setColor: function(color,instant){
- var t = this;
- if (color == t.color) return t;
- this.color = color;
- var colorfade = Jcrop.supportsColorFade();
- $.each(t.shades,function(u,i){
- if (!t.fade || instant || !colorfade) i.css('backgroundColor',color);
- else i.animate({backgroundColor:color},{queue:false,duration:t.fadeSpeed,easing:t.fadeEasing});
- });
- return t;
- },
- setOpacity: function(opacity,instant){
- var t = this;
- if (opacity == t.opacity) return t;
- t.opacity = opacity;
- $.each(t.shades,function(u,i){
- if (!t.fade || instant) i.css({opacity:opacity});
- else i.animate({opacity:opacity},{queue:false,duration:t.fadeSpeed,easing:t.fadeEasing});
- });
- return t;
- },
- createShade: function(){
- return $('<div />').css({
- position: 'absolute',
- backgroundColor: this.color,
- opacity: this.opacity
- }).appendTo(this.container);
- },
- refresh: function(sel){
- var m = this.core, s = this.shades;
- this.setColor(sel.bgColor?sel.bgColor:this.core.opt.bgColor);
- this.setOpacity(sel.bgOpacity?sel.bgOpacity:this.core.opt.bgOpacity);
-
- this.elh = m.container.height();
- this.elw = m.container.width();
- s.right.css('height',this.elh+'px');
- s.left.css('height',this.elh+'px');
- },
- filter: function(b,ord,sel){
- if (!sel.active) return b;
- var t = this,
- s = t.shades;
-
- s.top.css({
- left: Math.round(b.x)+'px',
- width: Math.round(b.w)+'px',
- height: Math.round(b.y)+'px'
- });
- s.bottom.css({
- top: Math.round(b.y2)+'px',
- left: Math.round(b.x)+'px',
- width: Math.round(b.w)+'px',
- height: (t.elh-Math.round(b.y2))+'px'
- });
- s.right.css({
- left: Math.round(b.x2)+'px',
- width: (t.elw-Math.round(b.x2))+'px'
- });
- s.left.css({
- width: Math.round(b.x)+'px'
- });
- if (!t.visible) {
- t.container.show();
- t.visible = true;
- }
- return b;
- }
- });
- Jcrop.registerFilter('shader',ShadeFilter);
-
- /**
- * CanvasAnimator
- * manages smooth cropping animation
- *
- * This object is called internally to manage animation.
- * An in-memory div is animated and a progress callback
- * is used to update the selection coordinates of the
- * visible selection in realtime.
- */
- var CanvasAnimator = function(stage){
- this.stage = stage;
- this.core = stage.core;
- this.cloneStagePosition();
- };
- CanvasAnimator.prototype = {
- cloneStagePosition: function(){
- var s = this.stage;
- this.angle = s.angle;
- this.scale = s.scale;
- this.offset = s.offset;
- },
- getElement: function(){
- var s = this.stage;
- return $('<div />')
- .css({
- position: 'absolute',
- top: s.offset[0]+'px',
- left: s.offset[1]+'px',
- width: s.angle+'px',
- height: s.scale+'px'
- });
- },
- animate: function(cb){
- var t = this;
- this.scale = this.stage.boundScale(this.scale);
- t.stage.triggerEvent('croprotstart');
- t.getElement().animate({
- top: t.offset[0]+'px',
- left: t.offset[1]+'px',
- width: t.angle+'px',
- height: t.scale+'px'
- },{
- easing: t.core.opt.animEasing,
- duration: t.core.opt.animDuration,
- complete: function(){
- t.stage.triggerEvent('croprotend');
- (typeof cb == 'function') && cb.call(this);
- },
- progress: function(anim){
- var props = {}, i, tw = anim.tweens;
- for(i=0;i<tw.length;i++){
- props[tw[i].prop] = tw[i].now; }
- t.stage.setAngle(props.width)
- .setScale(props.height)
- .setOffset(props.top,props.left)
- .redraw();
- }
- });
- }
- };
- Jcrop.stage.Canvas.prototype.getAnimator = function(){
- return new CanvasAnimator(this);
- };
- Jcrop.registerComponent('CanvasAnimator',CanvasAnimator);
- /**
- * CropAnimator
- * manages smooth cropping animation
- *
- * This object is called internally to manage animation.
- * An in-memory div is animated and a progress callback
- * is used to update the selection coordinates of the
- * visible selection in realtime.
- */
- // var CropAnimator = function(selection){{{
- var CropAnimator = function(selection){
- this.selection = selection;
- this.core = selection.core;
- };
- // }}}
- CropAnimator.prototype = {
- getElement: function(){
- var b = this.selection.get();
- return $('<div />')
- .css({
- position: 'absolute',
- top: b.y+'px',
- left: b.x+'px',
- width: b.w+'px',
- height: b.h+'px'
- });
- },
- animate: function(x,y,w,h,cb){
- var t = this;
- t.selection.allowResize(false);
- t.getElement().animate({
- top: y+'px',
- left: x+'px',
- width: w+'px',
- height: h+'px'
- },{
- easing: t.core.opt.animEasing,
- duration: t.core.opt.animDuration,
- complete: function(){
- t.selection.allowResize(true);
- cb && cb.call(this);
- },
- progress: function(anim){
- var props = {}, i, tw = anim.tweens;
- for(i=0;i<tw.length;i++){
- props[tw[i].prop] = tw[i].now; }
- var b = {
- x: parseInt(props.left),
- y: parseInt(props.top),
- w: parseInt(props.width),
- h: parseInt(props.height)
- };
- b.x2 = b.x + b.w;
- b.y2 = b.y + b.h;
- t.selection.updateRaw(b,'se');
- }
- });
- }
- };
- Jcrop.registerComponent('Animator',CropAnimator);
- /**
- * DragState
- * an object that handles dragging events
- *
- * This object is used by the built-in selection object to
- * track a dragging operation on a selection
- */
- // var DragState = function(e,selection,ord){{{
- var DragState = function(e,selection,ord){
- var t = this;
- t.x = e.pageX;
- t.y = e.pageY;
- t.selection = selection;
- t.eventTarget = selection.core.opt.dragEventTarget;
- t.orig = selection.get();
- selection.callFilterFunction('refresh');
- var p = selection.core.container.position();
- t.elx = p.left;
- t.ely = p.top;
- t.offsetx = 0;
- t.offsety = 0;
- t.ord = ord;
- t.opposite = t.getOppositeCornerOffset();
- t.initEvents(e);
- };
- // }}}
- DragState.prototype = {
- // getOppositeCornerOffset: function(){{{
- // Calculate relative offset of locked corner
- getOppositeCornerOffset: function(){
- var o = this.orig;
- var relx = this.x - this.elx - o.x;
- var rely = this.y - this.ely - o.y;
- switch(this.ord){
- case 'nw':
- case 'w':
- return [ o.w - relx, o.h - rely ];
- return [ o.x + o.w, o.y + o.h ];
- case 'sw':
- return [ o.w - relx, -rely ];
- return [ o.x + o.w, o.y ];
- case 'se':
- case 's':
- case 'e':
- return [ -relx, -rely ];
- return [ o.x, o.y ];
- case 'ne':
- case 'n':
- return [ -relx, o.h - rely ];
- return [ o.w, o.y + o.h ];
- }
- return [ null, null ];
- },
- // }}}
- // initEvents: function(e){{{
- initEvents: function(e){
- $(this.eventTarget)
- .on('mousemove.jcrop',this.createDragHandler())
- .on('mouseup.jcrop',this.createStopHandler());
- },
- // }}}
- // dragEvent: function(e){{{
- dragEvent: function(e){
- this.offsetx = e.pageX - this.x;
- this.offsety = e.pageY - this.y;
- this.selection.updateRaw(this.getBox(),this.ord);
- },
- // }}}
- // endDragEvent: function(e){{{
- endDragEvent: function(e){
- var sel = this.selection;
- sel.core.container.removeClass('jcrop-dragging');
- sel.element.trigger('cropend',[sel,sel.core.unscale(sel.get())]);
- sel.focus();
- },
- // }}}
- // createStopHandler: function(){{{
- createStopHandler: function(){
- var t = this;
- return function(e){
- $(t.eventTarget).off('.jcrop');
- t.endDragEvent(e);
- return false;
- };
- },
- // }}}
- // createDragHandler: function(){{{
- createDragHandler: function(){
- var t = this;
- return function(e){
- t.dragEvent(e);
- return false;
- };
- },
- // }}}
- //update: function(x,y){{{
- update: function(x,y){
- var t = this;
- t.offsetx = x - t.x;
- t.offsety = y - t.y;
- },
- //}}}
- //resultWrap: function(d){{{
- resultWrap: function(d){
- var b = {
- x: Math.min(d[0],d[2]),
- y: Math.min(d[1],d[3]),
- x2: Math.max(d[0],d[2]),
- y2: Math.max(d[1],d[3])
- };
- b.w = b.x2 - b.x;
- b.h = b.y2 - b.y;
- return b;
- },
- //}}}
- //getBox: function(){{{
- getBox: function(){
- var t = this;
- var o = t.orig;
- var _c = { x2: o.x + o.w, y2: o.y + o.h };
- switch(t.ord){
- case 'n': return t.resultWrap([ o.x, t.offsety + o.y, _c.x2, _c.y2 ]);
- case 's': return t.resultWrap([ o.x, o.y, _c.x2, t.offsety + _c.y2 ]);
- case 'e': return t.resultWrap([ o.x, o.y, t.offsetx + _c.x2, _c.y2 ]);
- case 'w': return t.resultWrap([ o.x + t.offsetx, o.y, _c.x2, _c.y2 ]);
- case 'sw': return t.resultWrap([ t.offsetx + o.x, o.y, _c.x2, t.offsety + _c.y2 ]);
- case 'se': return t.resultWrap([ o.x, o.y, t.offsetx + _c.x2, t.offsety + _c.y2 ]);
- case 'ne': return t.resultWrap([ o.x, t.offsety + o.y, t.offsetx + _c.x2, _c.y2 ]);
- case 'nw': return t.resultWrap([ t.offsetx + o.x, t.offsety + o.y, _c.x2, _c.y2 ]);
- case 'move':
- _c.nx = o.x + t.offsetx;
- _c.ny = o.y + t.offsety;
- return t.resultWrap([ _c.nx, _c.ny, _c.nx + o.w, _c.ny + o.h ]);
- }
- }
- //}}}
- };
- Jcrop.registerComponent('DragState',DragState);
- /**
- * EventManager
- * provides internal event support
- */
- var EventManager = function(core){
- this.core = core;
- };
- EventManager.prototype = {
- on: function(n,cb){ $(this).on(n,cb); },
- off: function(n){ $(this).off(n); },
- trigger: function(n){ $(this).trigger(n); }
- };
- Jcrop.registerComponent('EventManager',EventManager);
- /**
- * Image Loader
- * Reliably pre-loads images
- */
- // var ImageLoader = function(src,element,cb){{{
- var ImageLoader = function(src,element,cb){
- this.src = src;
- if (!element) element = new Image;
- this.element = element;
- this.callback = cb;
- this.load();
- };
- // }}}
- $.extend(ImageLoader,{
- // attach: function(el,cb){{{
- attach: function(el,cb){
- return new ImageLoader(el.src,el,cb);
- },
- // }}}
- // prototype: {{{
- prototype: {
- getDimensions: function(){
- var el = this.element;
- if (el.naturalWidth)
- return [ el.naturalWidth, el. naturalHeight ];
- if (el.width)
- return [ el.width, el.height ];
- return null;
- },
- fireCallback: function(){
- this.element.onload = null;
- if (typeof this.callback == 'function')
- this.callback.apply(this,this.getDimensions());
- },
- isLoaded: function(){
- return this.element.complete;
- },
- load: function(){
- var t = this;
- var el = t.element;
- el.src = t.src;
- if (t.isLoaded()) t.fireCallback();
- else t.element.onload = function(e){
- t.fireCallback();
- };
- }
- }
- // }}}
- });
- Jcrop.registerComponent('ImageLoader',ImageLoader);
- /**
- * JcropTouch
- * Detects and enables mobile touch support
- */
- // var JcropTouch = function(core){{{
- var JcropTouch = function(core){
- this.core = core;
- this.init();
- };
- // }}}
- $.extend(JcropTouch,{
- // support: function(){{{
- support: function(){
- if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch)
- return true;
- },
- // }}}
- prototype: {
- // init: function(){{{
- init: function(){
- var t = this,
- p = $.Jcrop.component.DragState.prototype;
- // A bit of an ugly hack to make sure we modify prototype
- // only once, store a key on the prototype
- if (!p.touch) {
- t.initEvents();
- t.shimDragState();
- t.shimStageDrag();
- p.touch = true;
- }
- },
- // }}}
- // shimDragState: function(){{{
- shimDragState: function(){
- var t = this;
- $.Jcrop.component.DragState.prototype.initEvents = function(e){
-
- // Attach subsequent drag event handlers based on initial
- // event type - avoids collecting "pseudo-mouse" events
- // generated by some mobile browsers in some circumstances
- if (e.type.substr(0,5) == 'touch') {
- $(this.eventTarget)
- .on('touchmove.jcrop.jcrop-touch',t.dragWrap(this.createDragHandler()))
- .on('touchend.jcrop.jcrop-touch',this.createStopHandler());
- }
-
- // For other events, use the mouse handlers that
- // the default DragState.initEvents() method sets...
- else {
- $(this.eventTarget)
- .on('mousemove.jcrop',this.createDragHandler())
- .on('mouseup.jcrop',this.createStopHandler());
- }
- };
- },
- // }}}
- // shimStageDrag: function(){{{
- shimStageDrag: function(){
- this.core.container
- .addClass('jcrop-touch')
- .on('touchstart.jcrop.jcrop-stage',this.dragWrap(this.core.ui.manager.startDragHandler()));
- },
- // }}}
- // dragWrap: function(cb){{{
- dragWrap: function(cb){
- return function(e){
- e.preventDefault();
- e.stopPropagation();
- if (e.type.substr(0,5) == 'touch') {
- e.pageX = e.originalEvent.changedTouches[0].pageX;
- e.pageY = e.originalEvent.changedTouches[0].pageY;
- return cb(e);
- }
- return false;
- };
- },
- // }}}
- // initEvents: function(){{{
- initEvents: function(){
- var t = this, c = t.core;
- c.container.on(
- 'touchstart.jcrop.jcrop-touch',
- '.'+c.opt.css_drag,
- t.dragWrap(c.startDrag())
- );
- }
- // }}}
- }
- });
- Jcrop.registerComponent('Touch',JcropTouch);
- /**
- * KeyWatcher
- * provides keyboard support
- */
- // var KeyWatcher = function(core){{{
- var KeyWatcher = function(core){
- this.core = core;
- this.init();
- };
- // }}}
- $.extend(KeyWatcher,{
- // defaults: {{{
- defaults: {
- eventName: 'keydown.jcrop',
- passthru: [ 9 ],
- debug: false
- },
- // }}}
- prototype: {
- // init: function(){{{
- init: function(){
- $.extend(this,KeyWatcher.defaults);
- this.enable();
- },
- // }}}
- // disable: function(){{{
- disable: function(){
- this.core.container.off(this.eventName);
- },
- // }}}
- // enable: function(){{{
- enable: function(){
- var t = this, m = t.core;
- m.container.on(t.eventName,function(e){
- var nudge = e.shiftKey? 16: 2;
- if ($.inArray(e.keyCode,t.passthru) >= 0)
- return true;
- switch(e.keyCode){
- case 37: m.nudge(-nudge,0); break;
- case 38: m.nudge(0,-nudge); break;
- case 39: m.nudge(nudge,0); break;
- case 40: m.nudge(0,nudge); break;
- case 46:
- case 8:
- m.requestDelete();
- return false;
- break;
- default:
- if (t.debug) console.log('keycode: ' + e.keyCode);
- break;
- }
- if (!e.metaKey && !e.ctrlKey)
- e.preventDefault();
- });
- }
- // }}}
- }
- });
- Jcrop.registerComponent('Keyboard',KeyWatcher);
- /**
- * Selection
- * Built-in selection object
- */
- var Selection = function(){};
- $.extend(Selection,{
- // defaults: {{{
- defaults: {
- minSize: [ 8, 8 ],
- maxSize: [ 0, 0 ],
- aspectRatio: 0,
- edge: { n: 0, s: 0, e: 0, w: 0 },
- bgColor: null,
- bgOpacity: null,
- last: null,
- state: null,
- active: true,
- linked: true,
- canDelete: true,
- canDrag: true,
- canResize: true,
- canSelect: true
- },
- // }}}
- prototype: {
- // init: function(core){{{
- init: function(core){
- this.core = core;
- this.startup();
- this.linked = this.core.opt.linked;
- this.attach();
- this.setOptions(this.core.opt);
- core.container.trigger('cropcreate',[this]);
- },
- // }}}
- // attach: function(){{{
- attach: function(){
- // For extending init() sequence
- },
- // }}}
- // startup: function(){{{
- startup: function(){
- var t = this, o = t.core.opt;
- $.extend(t,Selection.defaults);
- t.filter = t.core.getDefaultFilters();
- t.element = $('<div />').addClass(o.css_selection).data({ selection: t });
- t.frame = $('<button />').addClass(o.css_button).data('ord','move').attr('type','button');
- t.element.append(t.frame).appendTo(t.core.container);
- // IE background/draggable hack
- if (t.core.opt.is_msie) t.frame.css({
- opacity: 0,
- backgroundColor: 'white'
- });
- t.insertElements();
- // Bind focus and blur events for this selection
- t.frame.on('focus.jcrop',function(e){
- t.core.setSelection(t);
- t.element.trigger('cropfocus',t);
- t.element.addClass('jcrop-focus');
- }).on('blur.jcrop',function(e){
- t.element.removeClass('jcrop-focus');
- t.element.trigger('cropblur',t);
- });
- },
- // }}}
- // propagate: [{{{
- propagate: [
- 'canDelete', 'canDrag', 'canResize', 'canSelect',
- 'minSize', 'maxSize', 'aspectRatio', 'edge'
- ],
- // }}}
- // setOptions: function(opt){{{
- setOptions: function(opt){
- Jcrop.propagate(this.propagate,opt,this);
- this.refresh();
- return this;
- },
- // }}}
- // refresh: function(){{{
- refresh: function(){
- this.allowResize();
- this.allowDrag();
- this.allowSelect();
- this.callFilterFunction('refresh');
- this.updateRaw(this.get(),'se');
- },
- // }}}
- // callFilterFunction: function(f,args){{{
- callFilterFunction: function(f,args){
- for(var i=0;i<this.filter.length;i++)
- if (this.filter[i][f]) this.filter[i][f](this);
- return this;
- },
- // }}}
- //addFilter: function(filter){{{
- addFilter: function(filter){
- filter.core = this.core;
- if (!this.hasFilter(filter)) {
- this.filter.push(filter);
- this.sortFilters();
- if (filter.init) filter.init();
- this.refresh();
- }
- },
- //}}}
- // hasFilter: function(filter){{{
- hasFilter: function(filter){
- var i, f = this.filter, n = [];
- for(i=0;i<f.length;i++) if (f[i] === filter) return true;
- },
- // }}}
- // sortFilters: function(){{{
- sortFilters: function(){
- this.filter.sort(
- function(x,y){ return x.priority - y.priority; }
- );
- },
- // }}}
- //clearFilters: function(){{{
- clearFilters: function(){
- var i, f = this.filter;
- for(var i=0;i<f.length;i++)
- if (f[i].destroy) f[i].destroy();
- this.filter = [];
- },
- //}}}
- // removeFiltersByTag: function(tag){{{
- removeFilter: function(tag){
- var i, f = this.filter, n = [];
- for(var i=0;i<f.length;i++)
- if ((f[i].tag && (f[i].tag == tag)) || (tag === f[i])){
- if (f[i].destroy) f[i].destroy();
- }
- else n.push(f[i]);
- this.filter = n;
- },
- // }}}
- // runFilters: function(b,ord){{{
- runFilters: function(b,ord){
- for(var i=0;i<this.filter.length;i++)
- b = this.filter[i].filter(b,ord,this);
- return b;
- },
- // }}}
- //endDrag: function(){{{
- endDrag: function(){
- if (this.state) {
- $(document.body).off('.jcrop');
- this.focus();
- this.state = null;
- }
- },
- //}}}
- // startDrag: function(e,ord){{{
- startDrag: function(e,ord){
- var t = this;
- var m = t.core;
- ord = ord || $(e.target).data('ord');
- this.focus();
- if ((ord == 'move') && t.element.hasClass(t.core.opt.css_nodrag))
- return false;
- this.state = new Jcrop.component.DragState(e,this,ord);
- return false;
- },
- // }}}
- // allowSelect: function(v){{{
- allowSelect: function(v){
- if (v === undefined) v = this.canSelect;
- if (v && this.canSelect) this.frame.attr('disabled',false);
- else this.frame.attr('disabled','disabled');
- return this;
- },
- // }}}
- // allowDrag: function(v){{{
- allowDrag: function(v){
- var t = this, o = t.core.opt;
- if (v == undefined) v = t.canDrag;
- if (v && t.canDrag) t.element.removeClass(o.css_nodrag);
- else t.element.addClass(o.css_nodrag);
- return this;
- },
- // }}}
- // allowResize: function(v){{{
- allowResize: function(v){
- var t = this, o = t.core.opt;
- if (v == undefined) v = t.canResize;
- if (v && t.canResize) t.element.removeClass(o.css_noresize);
- else t.element.addClass(o.css_noresize);
- return this;
- },
- // }}}
- // remove: function(){{{
- remove: function(){
- this.element.trigger('cropremove',this);
- this.element.remove();
- },
- // }}}
- // toBack: function(){{{
- toBack: function(){
- this.active = false;
- this.element.removeClass('jcrop-current jcrop-focus');
- },
- // }}}
- // toFront: function(){{{
- toFront: function(){
- this.active = true;
- this.element.addClass('jcrop-current');
- this.callFilterFunction('refresh');
- this.refresh();
- },
- // }}}
- // redraw: function(b){{{
- redraw: function(b){
- this.moveTo(b.x,b.y);
- this.resize(b.w,b.h);
- this.last = b;
- return this;
- },
- // }}}
- // update: function(b,ord){{{
- update: function(b,ord){
- return this.updateRaw(this.core.scale(b),ord);
- },
- // }}}
- // update: function(b,ord){{{
- updateRaw: function(b,ord){
- b = this.runFilters(b,ord);
- this.redraw(b);
- this.element.trigger('cropmove',[this,this.core.unscale(b)]);
- return this;
- },
- // }}}
- // animateTo: function(box,cb){{{
- animateTo: function(box,cb){
- var ca = new Jcrop.component.Animator(this),
- b = this.core.scale(Jcrop.wrapFromXywh(box));
- ca.animate(b.x,b.y,b.w,b.h,cb);
- },
- // }}}
- // center: function(instant){{{
- center: function(instant){
- var b = this.get(), m = this.core;
- var elw = m.container.width(), elh = m.container.height();
- var box = [ (elw-b.w)/2, (elh-b.h)/2, b.w, b.h ];
- return this[instant?'setSelect':'animateTo'](box);
- },
- // }}}
- //createElement: function(type,ord){{{
- createElement: function(type,ord){
- return $('<div />').addClass(type+' ord-'+ord).data('ord',ord);
- },
- //}}}
- //moveTo: function(x,y){{{
- moveTo: function(x,y){
- this.element.css({top: y+'px', left: x+'px'});
- },
- //}}}
- // blur: function(){{{
- blur: function(){
- this.element.blur();
- return this;
- },
- // }}}
- // focus: function(){{{
- focus: function(){
- this.core.setSelection(this);
- this.frame.focus();
- return this;
- },
- // }}}
- //resize: function(w,h){{{
- resize: function(w,h){
- this.element.css({width: w+'px', height: h+'px'});
- },
- //}}}
- //get: function(){{{
- get: function(){
- var b = this.element,
- o = b.position(),
- w = b.width(),
- h = b.height(),
- rv = { x: o.left, y: o.top };
- rv.x2 = rv.x + w;
- rv.y2 = rv.y + h;
- rv.w = w;
- rv.h = h;
- return rv;
- },
- //}}}
- //insertElements: function(){{{
- insertElements: function(){
- var t = this, i,
- m = t.core,
- fr = t.element,
- o = t.core.opt,
- b = o.borders,
- h = o.handles,
- d = o.dragbars;
- for(i=0; i<d.length; i++)
- fr.append(t.createElement(o.css_dragbars,d[i]));
- for(i=0; i<h.length; i++)
- fr.append(t.createElement(o.css_handles,h[i]));
- for(i=0; i<b.length; i++)
- fr.append(t.createElement(o.css_borders,b[i]));
- }
- //}}}
- }
- });
- Jcrop.registerComponent('Selection',Selection);
- /**
- * StageDrag
- * Facilitates dragging
- */
- // var StageDrag = function(manager,opt){{{
- var StageDrag = function(manager,opt){
- $.extend(this,StageDrag.defaults,opt || {});
- this.manager = manager;
- this.core = manager.core;
- };
- // }}}
- // StageDrag.defaults = {{{
- StageDrag.defaults = {
- offset: [ -8, -8 ],
- active: true,
- minsize: [ 20, 20 ]
- };
- // }}}
- $.extend(StageDrag.prototype,{
- // start: function(e){{{
- start: function(e){
- var c = this.core;
- // Do nothing if allowSelect is off
- if (!c.opt.allowSelect) return;
- // Also do nothing if we can't draw any more selections
- if (c.opt.multi && c.opt.multiMax && (c.ui.multi.length >= c.opt.multiMax)) return false;
- // calculate a few variables for this drag operation
- var o = $(e.currentTarget).offset();
- var origx = e.pageX - o.left + this.offset[0];
- var origy = e.pageY - o.top + this.offset[1];
- var m = c.ui.multi;
- // Determine newly dragged crop behavior if multi disabled
- if (!c.opt.multi) {
- // For multiCleaanup true, remove all existing selections
- if (c.opt.multiCleanup){
- for(var i=0;i<m.length;i++) m[i].remove();
- c.ui.multi = [];
- }
- // If not, only remove the currently active selection
- else {
- c.removeSelection(c.ui.selection);
- }
- }
- c.container.addClass('jcrop-dragging');
- // Create the new selection
- var sel = c.newSelection()
- // and position it
- .updateRaw(Jcrop.wrapFromXywh([origx,origy,1,1]));
- sel.element.trigger('cropstart',[sel,this.core.unscale(sel.get())]);
-
- return sel.startDrag(e,'se');
- },
- // }}}
- // end: function(x,y){{{
- end: function(x,y){
- this.drag(x,y);
- var b = this.sel.get();
- this.core.container.removeClass('jcrop-dragging');
- if ((b.w < this.minsize[0]) || (b.h < this.minsize[1]))
- this.core.requestDelete();
- else this.sel.focus();
- }
- // }}}
- });
- Jcrop.registerComponent('StageDrag',StageDrag);
- /**
- * StageManager
- * Provides basic stage-specific functionality
- */
- // var StageManager = function(core){{{
- var StageManager = function(core){
- this.core = core;
- this.ui = core.ui;
- this.init();
- };
- // }}}
- $.extend(StageManager.prototype,{
- // init: function(){{{
- init: function(){
- this.setupEvents();
- this.dragger = new StageDrag(this);
- },
- // }}}
- // tellConfigUpdate: function(options){{{
- tellConfigUpdate: function(options){
- for(var i=0,m=this.ui.multi,l=m.length;i<l;i++)
- if (m[i].setOptions && (m[i].linked || (this.core.opt.linkCurrent && m[i] == this.ui.selection)))
- m[i].setOptions(options);
- },
- // }}}
- // startDragHandler: function(){{{
- startDragHandler: function(){
- var t = this;
- return function(e){
- if (!e.button || t.core.opt.is_ie_lt9) return t.dragger.start(e);
- };
- },
- // }}}
- // removeEvents: function(){{{
- removeEvents: function(){
- this.core.event.off('.jcrop-stage');
- this.core.container.off('.jcrop-stage');
- },
- // }}}
- // shimLegacyHandlers: function(options){{{
- // This method uses the legacyHandlers configuration object to
- // gracefully wrap old-style Jcrop events with new ones
- shimLegacyHandlers: function(options){
- var _x = {}, core = this.core, tmp;
- $.each(core.opt.legacyHandlers,function(k,i){
- if (k in options) {
- tmp = options[k];
- core.container.off('.jcrop-'+k)
- .on(i+'.jcrop.jcrop-'+k,function(e,s,c){
- tmp.call(core,c);
- });
- delete options[k];
- }
- });
- },
- // }}}
- // setupEvents: function(){{{
- setupEvents: function(){
- var t = this, c = t.core;
- c.event.on('configupdate.jcrop-stage',function(e){
- t.shimLegacyHandlers(c.opt);
- t.tellConfigUpdate(c.opt)
- c.container.trigger('cropconfig',[c,c.opt]);
- });
- this.core.container
- .on('mousedown.jcrop.jcrop-stage',this.startDragHandler());
- }
- // }}}
- });
- Jcrop.registerComponent('StageManager',StageManager);
- var Thumbnailer = function(){
- };
- $.extend(Thumbnailer,{
- defaults: {
- // Set to a specific Selection object
- // If this value is set, the preview will only track that Selection
- selection: null,
- fading: true,
- fadeDelay: 1000,
- fadeDuration: 1000,
- autoHide: false,
- width: 80,
- height: 80,
- _hiding: null
- },
- prototype: {
- recopyCanvas: function(){
- var s = this.core.ui.stage, cxt = s.context;
- this.context.putImageData(cxt.getImageData(0,0,s.canvas.width,s.canvas.height),0,0);
- },
- init: function(core,options){
- var t = this;
- this.core = core;
- $.extend(this,Thumbnailer.defaults,options);
- t.initEvents();
- t.refresh();
- t.insertElements();
- if (t.selection) {
- t.renderSelection(t.selection);
- t.selectionTarget = t.selection.element[0];
- } else if (t.core.ui.selection) {
- t.renderSelection(t.core.ui.selection);
- }
- if (t.core.ui.stage.canvas) {
- t.context = t.preview[0].getContext('2d');
- t.core.container.on('cropredraw',function(e){
- t.recopyCanvas();
- t.refresh();
- });
- }
- },
- updateImage: function(imgel){
- this.preview.remove();
- this.preview = $($.Jcrop.imageClone(imgel));
- this.element.append(this.preview);
- this.refresh();
- return this;
- },
- insertElements: function(){
- this.preview = $($.Jcrop.imageClone(this.core.ui.stage.imgsrc));
- this.element = $('<div />').addClass('jcrop-thumb')
- .width(this.width).height(this.height)
- .append(this.preview)
- .appendTo(this.core.container);
- },
- resize: function(w,h){
- this.width = w;
- this.height = h;
- this.element.width(w).height(h);
- this.renderCoords(this.last);
- },
- refresh: function(){
- this.cw = (this.core.opt.xscale * this.core.container.width());
- this.ch = (this.core.opt.yscale * this.core.container.height());
- if (this.last) {
- this.renderCoords(this.last);
- }
- },
- renderCoords: function(c){
- var rx = this.width / c.w;
- var ry = this.height / c.h;
- this.preview.css({
- width: Math.round(rx * this.cw) + 'px',
- height: Math.round(ry * this.ch) + 'px',
- marginLeft: '-' + Math.round(rx * c.x) + 'px',
- marginTop: '-' + Math.round(ry * c.y) + 'px'
- });
- this.last = c;
- return this;
- },
- renderSelection: function(s){
- return this.renderCoords(s.core.unscale(s.get()));
- },
- selectionStart: function(s){
- this.renderSelection(s);
- },
- show: function(){
- if (this._hiding) clearTimeout(this._hiding);
- if (!this.fading) this.element.stop().css({ opacity: 1 });
- else this.element.stop().animate({ opacity: 1 },{ duration: 80, queue: false });
- },
- hide: function(){
- var t = this;
- if (!t.fading) t.element.hide();
- else t._hiding = setTimeout(function(){
- t._hiding = null;
- t.element.stop().animate({ opacity: 0 },{ duration: t.fadeDuration, queue: false });
- },t.fadeDelay);
- },
- initEvents: function(){
- var t = this;
- t.core.container.on('croprotstart croprotend cropimage cropstart cropmove cropend',function(e,s,c){
- if (t.selectionTarget && (t.selectionTarget !== e.target)) return false;
- switch(e.type){
- case 'cropimage':
- t.updateImage(c);
- break;
- case 'cropstart':
- t.selectionStart(s);
- case 'croprotstart':
- t.show();
- break;
- case 'cropend':
- t.renderCoords(c);
- case 'croprotend':
- if (t.autoHide) t.hide();
- break;
- case 'cropmove':
- t.renderCoords(c);
- break;
- }
- });
- }
- }
- });
- Jcrop.registerComponent('Thumbnailer',Thumbnailer);
- /**
- * DialDrag component
- * This is a little hacky, it was adapted from some previous/old code
- * Plan to update this API in the future
- */
- var DialDrag = function() { };
- DialDrag.prototype = {
- init: function(core,actuator,callback){
- var that = this;
- if (!actuator) actuator = core.container;
- this.$btn = $(actuator);
- this.$targ = $(actuator);
- this.core = core;
- this.$btn
- .addClass('dialdrag')
- .on('mousedown.dialdrag',this.mousedown())
- .data('dialdrag',this);
- if (!$.isFunction(callback)) callback = function(){ };
- this.callback = callback;
- this.ondone = callback;
- },
- remove: function(){
- this.$btn
- .removeClass('dialdrag')
- .off('.dialdrag')
- .data('dialdrag',null);
- return this;
- },
- setTarget: function(obj){
- this.$targ = $(obj);
- return this;
- },
- getOffset: function(){
- var targ = this.$targ, pos = targ.offset();
- return [
- pos.left + (targ.width()/2),
- pos.top + (targ.height()/2)
- ];
- },
- relMouse: function(e){
- var x = e.pageX - this.offset[0],
- y = e.pageY - this.offset[1],
- ang = Math.atan2(y,x) * (180 / Math.PI),
- vec = Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
- return [ x, y, ang, vec ];
- },
- mousedown: function(){
- var that = this;
- function mouseUp(e){
- $(window).off('.dialdrag');
- that.ondone.call(that,that.relMouse(e));
- that.core.container.trigger('croprotend');
- }
- function mouseMove(e){
- that.callback.call(that,that.relMouse(e));
- }
- return function(e) {
- that.offset = that.getOffset();
- var rel = that.relMouse(e);
- that.angleOffset = -that.core.ui.stage.angle+rel[2];
- that.distOffset = rel[3];
- that.dragOffset = [rel[0],rel[1]];
- that.core.container.trigger('croprotstart');
- $(window)
- .on('mousemove.dialdrag',mouseMove)
- .on('mouseup.dialdrag',mouseUp);
- that.callback.call(that,that.relMouse(e));
- return false;
- };
- }
-
- };
- Jcrop.registerComponent('DialDrag',DialDrag);
- /////////////////////////////////
- // DEFAULT SETTINGS
- Jcrop.defaults = {
- // Selection Behavior
- edge: { n: 0, s: 0, e: 0, w: 0 },
- setSelect: null,
- linked: true,
- linkCurrent: true,
- canDelete: true,
- canSelect: true,
- canDrag: true,
- canResize: true,
- // Component constructors
- eventManagerComponent: Jcrop.component.EventManager,
- keyboardComponent: Jcrop.component.Keyboard,
- dragstateComponent: Jcrop.component.DragState,
- stagemanagerComponent: Jcrop.component.StageManager,
- animatorComponent: Jcrop.component.Animator,
- selectionComponent: Jcrop.component.Selection,
- // This is a function that is called, which returns a stage object
- stageConstructor: Jcrop.stageConstructor,
- // Stage Behavior
- allowSelect: true,
- multi: false,
- multiMax: false,
- multiCleanup: true,
- animation: true,
- animEasing: 'swing',
- animDuration: 400,
- fading: true,
- fadeDuration: 300,
- fadeEasing: 'swing',
- bgColor: 'black',
- bgOpacity: .5,
- // Startup options
- applyFilters: [ 'constrain', 'extent', 'backoff', 'ratio', 'shader', 'round' ],
- borders: [ 'e', 'w', 's', 'n' ],
- handles: [ 'n', 's', 'e', 'w', 'sw', 'ne', 'nw', 'se' ],
- dragbars: [ 'n', 'e', 'w', 's' ],
- dragEventTarget: window,
- xscale: 1,
- yscale: 1,
- boxWidth: null,
- boxHeight: null,
- // CSS Classes
- // @todo: These need to be moved to top-level object keys
- // for better customization. Currently if you try to extend one
- // via an options object to Jcrop, it will wipe out all
- // the others you don't specify. Be careful for now!
- css_nodrag: 'jcrop-nodrag',
- css_drag: 'jcrop-drag',
- css_container: 'jcrop-active',
- css_shades: 'jcrop-shades',
- css_selection: 'jcrop-selection',
- css_borders: 'jcrop-border',
- css_handles: 'jcrop-handle jcrop-drag',
- css_button: 'jcrop-box jcrop-drag',
- css_noresize: 'jcrop-noresize',
- css_dragbars: 'jcrop-dragbar jcrop-drag',
- legacyHandlers: {
- onChange: 'cropmove',
- onSelect: 'cropend'
- }
- };
- // Jcrop API methods
- $.extend(Jcrop.prototype,{
- //init: function(){{{
- init: function(){
- this.event = new this.opt.eventManagerComponent(this);
- this.ui.keyboard = new this.opt.keyboardComponent(this);
- this.ui.manager = new this.opt.stagemanagerComponent(this);
- this.applyFilters();
- if ($.Jcrop.supportsTouch)
- new $.Jcrop.component.Touch(this);
- this.initEvents();
- },
- //}}}
- // applySizeConstraints: function(){{{
- applySizeConstraints: function(){
- var o = this.opt,
- img = this.opt.imgsrc;
- if (img){
- var iw = img.naturalWidth || img.width,
- ih = img.naturalHeight || img.height,
- bw = o.boxWidth || iw,
- bh = o.boxHeight || ih;
- if (img && ((iw > bw) || (ih > bh))){
- var bx = Jcrop.getLargestBox(iw/ih,bw,bh);
- $(img).width(bx[0]).height(bx[1]);
- this.resizeContainer(bx[0],bx[1]);
- this.opt.xscale = iw / bx[0];
- this.opt.yscale = ih / bx[1];
- }
-
- }
- if (this.opt.trueSize){
- var dw = this.opt.trueSize[0];
- var dh = this.opt.trueSize[1];
- var cs = this.getContainerSize();
- this.opt.xscale = dw / cs[0];
- this.opt.yscale = dh / cs[1];
- }
- },
- // }}}
- initComponent: function(name){
- if (Jcrop.component[name]) {
- var args = Array.prototype.slice.call(arguments);
- var obj = new Jcrop.component[name];
- args.shift();
- args.unshift(this);
- obj.init.apply(obj,args);
- return obj;
- }
- },
- // setOptions: function(opt){{{
- setOptions: function(opt,proptype){
- if (!$.isPlainObject(opt)) opt = {};
- $.extend(this.opt,opt);
- // Handle a setSelect value
- if (this.opt.setSelect) {
- // If there is no current selection
- // passing setSelect will create one
- if (!this.ui.multi.length)
- this.newSelection();
- // Use these values to update the current selection
- this.setSelect(this.opt.setSelect);
- // Set to null so it doesn't get called again
- this.opt.setSelect = null;
- }
- this.event.trigger('configupdate');
- return this;
- },
- // }}}
- //destroy: function(){{{
- destroy: function(){
- if (this.opt.imgsrc) {
- this.container.before(this.opt.imgsrc);
- this.container.remove();
- $(this.opt.imgsrc).removeData('Jcrop').show();
- } else {
- // @todo: more elegant destroy() process for non-image containers
- this.container.remove();
- }
- },
- // }}}
- // applyFilters: function(){{{
- applyFilters: function(){
- var obj;
- for(var i=0,f=this.opt.applyFilters,l=f.length; i<l; i++){
- if ($.Jcrop.filter[f[i]])
- obj = new $.Jcrop.filter[f[i]];
- obj.core = this;
- if (obj.init) obj.init();
- this.filter[f[i]] = obj;
- }
- },
- // }}}
- // getDefaultFilters: function(){{{
- getDefaultFilters: function(){
- var rv = [];
- for(var i=0,f=this.opt.applyFilters,l=f.length; i<l; i++)
- if(this.filter.hasOwnProperty(f[i]))
- rv.push(this.filter[f[i]]);
- rv.sort(function(x,y){ return x.priority - y.priority; });
- return rv;
- },
- // }}}
- // setSelection: function(sel){{{
- setSelection: function(sel){
- var m = this.ui.multi;
- var n = [];
- for(var i=0;i<m.length;i++) {
- if (m[i] !== sel) n.push(m[i]);
- m[i].toBack();
- }
- n.unshift(sel);
- this.ui.multi = n;
- this.ui.selection = sel;
- sel.toFront();
- return sel;
- },
- // }}}
- // getSelection: function(raw){{{
- getSelection: function(raw){
- var b = this.ui.selection.get();
- return b;
- },
- // }}}
- // newSelection: function(){{{
- newSelection: function(sel){
- if (!sel)
- sel = new this.opt.selectionComponent();
- sel.init(this);
- this.setSelection(sel);
- return sel;
- },
- // }}}
- // hasSelection: function(sel){{{
- hasSelection: function(sel){
- for(var i=0;i<this.ui.multi;i++)
- if (sel === this.ui.multi[i]) return true;
- },
- // }}}
- // removeSelection: function(sel){{{
- removeSelection: function(sel){
- var i, n = [], m = this.ui.multi;
- for(var i=0;i<m.length;i++){
- if (sel !== m[i])
- n.push(m[i]);
- else m[i].remove();
- }
- return this.ui.multi = n;
- },
- // }}}
- //addFilter: function(filter){{{
- addFilter: function(filter){
- for(var i=0,m=this.ui.multi,l=m.length; i<l; i++)
- m[i].addFilter(filter);
- return this;
- },
- //}}}
- // removeFiltersByTag: function(tag){{{
- removeFilter: function(filter){
- for(var i=0,m=this.ui.multi,l=m.length; i<l; i++)
- m[i].removeFilter(filter);
- return this;
- },
- // }}}
- // blur: function(){{{
- blur: function(){
- this.ui.selection.blur();
- return this;
- },
- // }}}
- // focus: function(){{{
- focus: function(){
- this.ui.selection.focus();
- return this;
- },
- // }}}
- //initEvents: function(){{{
- initEvents: function(){
- var t = this;
- t.container.on('selectstart',function(e){ return false; })
- .on('mousedown','.'+t.opt.css_drag,t.startDrag());
- },
- //}}}
- // maxSelect: function(){{{
- maxSelect: function(){
- this.setSelect([0,0,this.elw,this.elh]);
- },
- // }}}
- // nudge: function(x,y){{{
- nudge: function(x,y){
- var s = this.ui.selection, b = s.get();
- b.x += x;
- b.x2 += x;
- b.y += y;
- b.y2 += y;
- if (b.x < 0) { b.x2 = b.w; b.x = 0; }
- else if (b.x2 > this.elw) { b.x2 = this.elw; b.x = b.x2 - b.w; }
- if (b.y < 0) { b.y2 = b.h; b.y = 0; }
- else if (b.y2 > this.elh) { b.y2 = this.elh; b.y = b.y2 - b.h; }
-
- s.element.trigger('cropstart',[s,this.unscale(b)]);
- s.updateRaw(b,'move');
- s.element.trigger('cropend',[s,this.unscale(b)]);
- },
- // }}}
- // refresh: function(){{{
- refresh: function(){
- for(var i=0,s=this.ui.multi,l=s.length;i<l;i++)
- s[i].refresh();
- },
- // }}}
- // blurAll: function(){{{
- blurAll: function(){
- var m = this.ui.multi;
- for(var i=0;i<m.length;i++) {
- if (m[i] !== sel) n.push(m[i]);
- m[i].toBack();
- }
- },
- // }}}
- // scale: function(b){{{
- scale: function(b){
- var xs = this.opt.xscale,
- ys = this.opt.yscale;
- return {
- x: b.x / xs,
- y: b.y / ys,
- x2: b.x2 / xs,
- y2: b.y2 / ys,
- w: b.w / xs,
- h: b.h / ys
- };
- },
- // }}}
- // unscale: function(b){{{
- unscale: function(b){
- var xs = this.opt.xscale,
- ys = this.opt.yscale;
- return {
- x: b.x * xs,
- y: b.y * ys,
- x2: b.x2 * xs,
- y2: b.y2 * ys,
- w: b.w * xs,
- h: b.h * ys
- };
- },
- // }}}
- // requestDelete: function(){{{
- requestDelete: function(){
- if ((this.ui.multi.length > 1) && (this.ui.selection.canDelete))
- return this.deleteSelection();
- },
- // }}}
- // deleteSelection: function(){{{
- deleteSelection: function(){
- if (this.ui.selection) {
- this.removeSelection(this.ui.selection);
- if (this.ui.multi.length) this.ui.multi[0].focus();
- this.ui.selection.refresh();
- }
- },
- // }}}
- // animateTo: function(box){{{
- animateTo: function(box){
- if (this.ui.selection)
- this.ui.selection.animateTo(box);
- return this;
- },
- // }}}
- // setselect: function(box){{{
- setSelect: function(box){
- if (this.ui.selection)
- this.ui.selection.update(Jcrop.wrapFromXywh(box));
- return this;
- },
- // }}}
- //startDrag: function(){{{
- startDrag: function(){
- var t = this;
- return function(e){
- var $targ = $(e.target);
- var selection = $targ.closest('.'+t.opt.css_selection).data('selection');
- var ord = $targ.data('ord');
- t.container.trigger('cropstart',[selection,t.unscale(selection.get())]);
- selection.startDrag(e,ord);
- return false;
- };
- },
- //}}}
- // getContainerSize: function(){{{
- getContainerSize: function(){
- return [ this.container.width(), this.container.height() ];
- },
- // }}}
- // resizeContainer: function(w,h){{{
- resizeContainer: function(w,h){
- this.container.width(w).height(h);
- this.refresh();
- },
- // }}}
- // setImage: function(src,cb){{{
- setImage: function(src,cb){
- var t = this, targ = t.opt.imgsrc;
- if (!targ) return false;
- new $.Jcrop.component.ImageLoader(src,null,function(w,h){
- t.resizeContainer(w,h);
- targ.src = src;
- $(targ).width(w).height(h);
- t.applySizeConstraints();
- t.refresh();
- t.container.trigger('cropimage',[t,targ]);
- if (typeof cb == 'function')
- cb.call(t,w,h);
- });
- },
- // }}}
- // update: function(b){{{
- update: function(b){
- if (this.ui.selection)
- this.ui.selection.update(b);
- }
- // }}}
- });
- // Jcrop jQuery plugin function
- $.fn.Jcrop = function(options,callback){
- options = options || {};
- var first = this.eq(0).data('Jcrop');
- var args = Array.prototype.slice.call(arguments);
- // Return API if requested
- if (options == 'api') { return first; }
- // Allow calling API methods (with arguments)
- else if (first && (typeof options == 'string')) {
- // Call method if it exists
- if (first[options]) {
- args.shift();
- first[options].apply(first,args);
- return first;
- }
- // Unknown input/method does not exist
- return false;
- }
- // Otherwise, loop over selected elements
- this.each(function(){
- var t = this, $t = $(this);
- var exists = $t.data('Jcrop');
- var obj;
- // If Jcrop already exists on this element only setOptions()
- if (exists)
- exists.setOptions(options);
- else {
- if (!options.stageConstructor)
- options.stageConstructor = $.Jcrop.stageConstructor;
- options.stageConstructor(this,options,function(stage,options){
- var selection = options.setSelect;
- if (selection) delete(options.setSelect);
- var obj = $.Jcrop.attach(stage.element,options);
- if (typeof stage.attach == 'function')
- stage.attach(obj);
- $t.data('Jcrop',obj);
- if (selection) {
- obj.newSelection();
- obj.setSelect(selection);
- }
- if (typeof callback == 'function')
- callback.call(obj);
- });
- }
- return this;
- });
- };
- /* Modernizr 2.7.1 (Custom Build) | MIT & BSD
- * Build: http://modernizr.com/download/#-csstransforms-canvas-canvastext-draganddrop-inlinesvg-svg-svgclippaths-touch-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-url_data_uri
- */
- ;
- var Modernizr = (function( window, document, undefined ) {
- var version = '2.7.1',
- Modernizr = {},
- docElement = document.documentElement,
- mod = 'modernizr',
- modElem = document.createElement(mod),
- mStyle = modElem.style,
- inputElem ,
- toString = {}.toString,
- prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
- omPrefixes = 'Webkit Moz O ms',
- cssomPrefixes = omPrefixes.split(' '),
- domPrefixes = omPrefixes.toLowerCase().split(' '),
- ns = {'svg': 'http://www.w3.org/2000/svg'},
- tests = {},
- inputs = {},
- attrs = {},
- classes = [],
- slice = classes.slice,
- featureName,
- injectElementWithStyles = function( rule, callback, nodes, testnames ) {
- var style, ret, node, docOverflow,
- div = document.createElement('div'),
- body = document.body,
- fakeBody = body || document.createElement('body');
- if ( parseInt(nodes, 10) ) {
- while ( nodes-- ) {
- node = document.createElement('div');
- node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
- div.appendChild(node);
- }
- }
- style = ['­','<style id="s', mod, '">', rule, '</style>'].join('');
- div.id = mod;
- (body ? div : fakeBody).innerHTML += style;
- fakeBody.appendChild(div);
- if ( !body ) {
- fakeBody.style.background = '';
- fakeBody.style.overflow = 'hidden';
- docOverflow = docElement.style.overflow;
- docElement.style.overflow = 'hidden';
- docElement.appendChild(fakeBody);
- }
- ret = callback(div, rule);
- if ( !body ) {
- fakeBody.parentNode.removeChild(fakeBody);
- docElement.style.overflow = docOverflow;
- } else {
- div.parentNode.removeChild(div);
- }
- return !!ret;
- },
- isEventSupported = (function() {
- var TAGNAMES = {
- 'select': 'input', 'change': 'input',
- 'submit': 'form', 'reset': 'form',
- 'error': 'img', 'load': 'img', 'abort': 'img'
- };
- function isEventSupported( eventName, element ) {
- element = element || document.createElement(TAGNAMES[eventName] || 'div');
- eventName = 'on' + eventName;
- var isSupported = eventName in element;
- if ( !isSupported ) {
- if ( !element.setAttribute ) {
- element = document.createElement('div');
- }
- if ( element.setAttribute && element.removeAttribute ) {
- element.setAttribute(eventName, '');
- isSupported = is(element[eventName], 'function');
- if ( !is(element[eventName], 'undefined') ) {
- element[eventName] = undefined;
- }
- element.removeAttribute(eventName);
- }
- }
- element = null;
- return isSupported;
- }
- return isEventSupported;
- })(),
- _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
- if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
- hasOwnProp = function (object, property) {
- return _hasOwnProperty.call(object, property);
- };
- }
- else {
- hasOwnProp = function (object, property) {
- return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
- };
- }
- if (!Function.prototype.bind) {
- Function.prototype.bind = function bind(that) {
- var target = this;
- if (typeof target != "function") {
- throw new TypeError();
- }
- var args = slice.call(arguments, 1),
- bound = function () {
- if (this instanceof bound) {
- var F = function(){};
- F.prototype = target.prototype;
- var self = new F();
- var result = target.apply(
- self,
- args.concat(slice.call(arguments))
- );
- if (Object(result) === result) {
- return result;
- }
- return self;
- } else {
- return target.apply(
- that,
- args.concat(slice.call(arguments))
- );
- }
- };
- return bound;
- };
- }
- function setCss( str ) {
- mStyle.cssText = str;
- }
- function setCssAll( str1, str2 ) {
- return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
- }
- function is( obj, type ) {
- return typeof obj === type;
- }
- function contains( str, substr ) {
- return !!~('' + str).indexOf(substr);
- }
- function testProps( props, prefixed ) {
- for ( var i in props ) {
- var prop = props[i];
- if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
- return prefixed == 'pfx' ? prop : true;
- }
- }
- return false;
- }
- function testDOMProps( props, obj, elem ) {
- for ( var i in props ) {
- var item = obj[props[i]];
- if ( item !== undefined) {
- if (elem === false) return props[i];
- if (is(item, 'function')){
- return item.bind(elem || obj);
- }
- return item;
- }
- }
- return false;
- }
- function testPropsAll( prop, prefixed, elem ) {
- var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
- props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
- if(is(prefixed, "string") || is(prefixed, "undefined")) {
- return testProps(props, prefixed);
- } else {
- props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
- return testDOMProps(props, prefixed, elem);
- }
- }
- tests['canvas'] = function() {
- var elem = document.createElement('canvas');
- return !!(elem.getContext && elem.getContext('2d'));
- };
- tests['canvastext'] = function() {
- return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
- };
- tests['touch'] = function() {
- var bool;
- if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
- bool = true;
- } else {
- injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
- bool = node.offsetTop === 9;
- });
- }
- return bool;
- };
- tests['draganddrop'] = function() {
- var div = document.createElement('div');
- return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
- };
- tests['csstransforms'] = function() {
- return !!testPropsAll('transform');
- };
- tests['svg'] = function() {
- return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
- };
- tests['inlinesvg'] = function() {
- var div = document.createElement('div');
- div.innerHTML = '<svg/>';
- return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
- };
- tests['svgclippaths'] = function() {
- return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
- };
- for ( var feature in tests ) {
- if ( hasOwnProp(tests, feature) ) {
- featureName = feature.toLowerCase();
- Modernizr[featureName] = tests[feature]();
- classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
- }
- }
- Modernizr.addTest = function ( feature, test ) {
- if ( typeof feature == 'object' ) {
- for ( var key in feature ) {
- if ( hasOwnProp( feature, key ) ) {
- Modernizr.addTest( key, feature[ key ] );
- }
- }
- } else {
- feature = feature.toLowerCase();
- if ( Modernizr[feature] !== undefined ) {
- return Modernizr;
- }
- test = typeof test == 'function' ? test() : test;
- if (typeof enableClasses !== "undefined" && enableClasses) {
- docElement.className += ' ' + (test ? '' : 'no-') + feature;
- }
- Modernizr[feature] = test;
- }
- return Modernizr;
- };
- setCss('');
- modElem = inputElem = null;
- Modernizr._version = version;
- Modernizr._prefixes = prefixes;
- Modernizr._domPrefixes = domPrefixes;
- Modernizr._cssomPrefixes = cssomPrefixes;
- Modernizr.hasEvent = isEventSupported;
- Modernizr.testProp = function(prop){
- return testProps([prop]);
- };
- Modernizr.testAllProps = testPropsAll;
- Modernizr.testStyles = injectElementWithStyles;
- return Modernizr;
- })(window, window.document);
- // data uri test.
- // https://github.com/Modernizr/Modernizr/issues/14
- // This test is asynchronous. Watch out.
- // in IE7 in HTTPS this can cause a Mixed Content security popup.
- // github.com/Modernizr/Modernizr/issues/362
- // To avoid that you can create a new iframe and inject this.. perhaps..
- (function(){
- var datauri = new Image();
- datauri.onerror = function() {
- Modernizr.addTest('datauri', function () { return false; });
- };
- datauri.onload = function() {
- Modernizr.addTest('datauri', function () { return (datauri.width == 1 && datauri.height == 1); });
- };
- datauri.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
- })();
- ;
- // Attach to jQuery object
- $.Jcrop = Jcrop;
- $.Jcrop.supportsCanvas = Modernizr.canvas;
- $.Jcrop.supportsCanvasText = Modernizr.canvastext;
- $.Jcrop.supportsDragAndDrop = Modernizr.draganddrop;
- $.Jcrop.supportsDataURI = Modernizr.datauri;
- $.Jcrop.supportsSVG = Modernizr.svg;
- $.Jcrop.supportsInlineSVG = Modernizr.inlinesvg;
- $.Jcrop.supportsSVGClipPaths = Modernizr.svgclippaths;
- $.Jcrop.supportsCSSTransforms = Modernizr.csstransforms;
- $.Jcrop.supportsTouch = Modernizr.touch;
- })(jQuery);
|