2 * Copyright (c) 2006, David Spurr (http://www.defusion.org.uk/)
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
\r
7 * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
\r
8 * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
\r
9 * * Neither the name of the David Spurr nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
\r
11 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
13 * http://www.opensource.org/licenses/bsd-license.php
\r
15 * See scriptaculous.js for full scriptaculous licence
\r
17 * Modified 2013/06/01 Zach P to change $() to $PR() for eliminating conflicts with jQuery
\r
20 var CropDraggable=Class.create();
\r
21 Object.extend(Object.extend(CropDraggable.prototype,Draggable.prototype),{initialize:function(_1){
\r
22 this.options=Object.extend({drawMethod:function(){
\r
23 }},arguments[1]||{});
\r
24 this.element=$PR(_1);
\r
25 this.handle=this.element;
\r
26 this.delta=this.currentDelta();
\r
27 this.dragging=false;
\r
28 this.eventMouseDown=this.initDrag.bindAsEventListener(this);
\r
29 Event.observe(this.handle,"mousedown",this.eventMouseDown);
\r
30 Draggables.register(this);
\r
31 },draw:function(_2){
\r
32 var _3=Position.cumulativeOffset(this.element);
\r
33 var d=this.currentDelta();
\r
36 var p=[0,1].map(function(i){
\r
37 return (_2[i]-_3[i]-this.offset[i]);
\r
39 this.options.drawMethod(p);
\r
42 Cropper.Img=Class.create();
\r
43 Cropper.Img.prototype={initialize:function(_7,_8){
\r
44 this.options=Object.extend({ratioDim:{x:0,y:0},minWidth:0,minHeight:0,displayOnInit:false,onEndCrop:Prototype.emptyFunction,captureKeys:true,onloadCoords:null,maxWidth:0,maxHeight:0},_8||{});
\r
46 this.clickCoords={x:0,y:0};
\r
47 this.dragging=false;
\r
48 this.resizing=false;
\r
49 this.isWebKit=/Konqueror|Safari|KHTML/.test(navigator.userAgent);
\r
50 this.isIE=/MSIE/.test(navigator.userAgent);
\r
51 this.isOpera8=/Opera\s[1-8]/.test(navigator.userAgent);
\r
54 this.attached=false;
\r
55 this.fixedWidth=(this.options.maxWidth>0&&(this.options.minWidth>=this.options.maxWidth));
\r
56 this.fixedHeight=(this.options.maxHeight>0&&(this.options.minHeight>=this.options.maxHeight));
\r
57 if(typeof this.img=="undefined"){
\r
60 $A(document.getElementsByTagName("script")).each(function(s){
\r
61 if(s.src.match(/cropper\.js/)){
\r
62 var _a=s.src.replace(/cropper\.js(.*)?/,"");
\r
63 var _b=document.createElement("link");
\r
64 _b.rel="stylesheet";
\r
66 _b.href=_a+"cropper.css";
\r
68 document.getElementsByTagName("head")[0].appendChild(_b);
\r
71 if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
\r
72 var _c=this.getGCD(this.options.ratioDim.x,this.options.ratioDim.y);
\r
73 this.ratioX=this.options.ratioDim.x/_c;
\r
74 this.ratioY=this.options.ratioDim.y/_c;
\r
76 this.subInitialize();
\r
77 if(this.img.complete||this.isWebKit){
\r
80 Event.observe(this.img,"load",this.onLoad.bindAsEventListener(this));
\r
82 },getGCD:function(a,b){
\r
86 return this.getGCD(b,a%b);
\r
87 },onLoad:function(){
\r
89 var _10=this.img.parentNode;
\r
94 this.imgWrap=Builder.node("div",{"class":_f+"wrap"+_11});
\r
95 this.north=Builder.node("div",{"class":_f+"overlay "+_f+"north"},[Builder.node("span")]);
\r
96 this.east=Builder.node("div",{"class":_f+"overlay "+_f+"east"},[Builder.node("span")]);
\r
97 this.south=Builder.node("div",{"class":_f+"overlay "+_f+"south"},[Builder.node("span")]);
\r
98 this.west=Builder.node("div",{"class":_f+"overlay "+_f+"west"},[Builder.node("span")]);
\r
99 var _12=[this.north,this.east,this.south,this.west];
\r
100 this.dragArea=Builder.node("div",{"class":_f+"dragArea"},_12);
\r
101 this.handleN=Builder.node("div",{"class":_f+"handle "+_f+"handleN"});
\r
102 this.handleNE=Builder.node("div",{"class":_f+"handle "+_f+"handleNE"});
\r
103 this.handleE=Builder.node("div",{"class":_f+"handle "+_f+"handleE"});
\r
104 this.handleSE=Builder.node("div",{"class":_f+"handle "+_f+"handleSE"});
\r
105 this.handleS=Builder.node("div",{"class":_f+"handle "+_f+"handleS"});
\r
106 this.handleSW=Builder.node("div",{"class":_f+"handle "+_f+"handleSW"});
\r
107 this.handleW=Builder.node("div",{"class":_f+"handle "+_f+"handleW"});
\r
108 this.handleNW=Builder.node("div",{"class":_f+"handle "+_f+"handleNW"});
\r
109 this.selArea=Builder.node("div",{"class":_f+"selArea"},[Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeNorth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeEast"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeHoriz "+_f+"marqueeSouth"},[Builder.node("span")]),Builder.node("div",{"class":_f+"marqueeVert "+_f+"marqueeWest"},[Builder.node("span")]),this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW,Builder.node("div",{"class":_f+"clickArea"})]);
\r
110 this.imgWrap.appendChild(this.img);
\r
111 this.imgWrap.appendChild(this.dragArea);
\r
112 this.dragArea.appendChild(this.selArea);
\r
113 this.dragArea.appendChild(Builder.node("div",{"class":_f+"clickArea"}));
\r
114 _10.appendChild(this.imgWrap);
\r
115 this.startDragBind=this.startDrag.bindAsEventListener(this);
\r
116 Event.observe(this.dragArea,"mousedown",this.startDragBind);
\r
117 this.onDragBind=this.onDrag.bindAsEventListener(this);
\r
118 Event.observe(document,"mousemove",this.onDragBind);
\r
119 this.endCropBind=this.endCrop.bindAsEventListener(this);
\r
120 Event.observe(document,"mouseup",this.endCropBind);
\r
121 this.resizeBind=this.startResize.bindAsEventListener(this);
\r
122 this.handles=[this.handleN,this.handleNE,this.handleE,this.handleSE,this.handleS,this.handleSW,this.handleW,this.handleNW];
\r
123 this.registerHandles(true);
\r
124 if(this.options.captureKeys){
\r
125 this.keysBind=this.handleKeys.bindAsEventListener(this);
\r
126 Event.observe(document,"keypress",this.keysBind);
\r
128 new CropDraggable(this.selArea,{drawMethod:this.moveArea.bindAsEventListener(this)});
\r
130 },registerHandles:function(_13){
\r
131 for(var i=0;i<this.handles.length;i++){
\r
132 var _15=$PR(this.handles[i]);
\r
135 if(this.fixedWidth&&this.fixedHeight){
\r
138 if(this.fixedWidth||this.fixedHeight){
\r
139 var _17=_15.className.match(/([S|N][E|W])$/);
\r
140 var _18=_15.className.match(/(E|W)$/);
\r
141 var _19=_15.className.match(/(N|S)$/);
\r
145 if(this.fixedWidth&&_18){
\r
148 if(this.fixedHeight&&_19){
\r
158 Event.observe(_15,"mousedown",this.resizeBind);
\r
162 Event.stopObserving(_15,"mousedown",this.resizeBind);
\r
165 },setParams:function(){
\r
166 this.imgW=this.img.width;
\r
167 this.imgH=this.img.height;
\r
168 $PR(this.north).setStyle({height:0});
\r
169 $PR(this.east).setStyle({width:0,height:0});
\r
170 $PR(this.south).setStyle({height:0});
\r
171 $PR(this.west).setStyle({width:0,height:0});
\r
172 $PR(this.imgWrap).setStyle({"width":this.imgW+"px","height":this.imgH+"px"});
\r
173 $PR(this.selArea).hide();
\r
174 var _1a={x1:0,y1:0,x2:0,y2:0};
\r
176 if(this.options.onloadCoords!=null){
\r
177 _1a=this.cloneCoords(this.options.onloadCoords);
\r
180 if(this.options.ratioDim.x>0&&this.options.ratioDim.y>0){
\r
181 _1a.x1=Math.ceil((this.imgW-this.options.ratioDim.x)/2);
\r
182 _1a.y1=Math.ceil((this.imgH-this.options.ratioDim.y)/2);
\r
183 _1a.x2=_1a.x1+this.options.ratioDim.x;
\r
184 _1a.y2=_1a.y1+this.options.ratioDim.y;
\r
188 this.setAreaCoords(_1a,false,false,1);
\r
189 if(this.options.displayOnInit&&_1b){
\r
190 this.selArea.show();
\r
194 this.attached=true;
\r
195 },remove:function(){
\r
197 this.attached=false;
\r
198 this.imgWrap.parentNode.insertBefore(this.img,this.imgWrap);
\r
199 this.imgWrap.parentNode.removeChild(this.imgWrap);
\r
200 Event.stopObserving(this.dragArea,"mousedown",this.startDragBind);
\r
201 Event.stopObserving(document,"mousemove",this.onDragBind);
\r
202 Event.stopObserving(document,"mouseup",this.endCropBind);
\r
203 this.registerHandles(false);
\r
204 if(this.options.captureKeys){
\r
205 Event.stopObserving(document,"keypress",this.keysBind);
\r
208 },reset:function(){
\r
209 if(!this.attached){
\r
215 },handleKeys:function(e){
\r
217 if(!this.dragging){
\r
232 if(dir.x!=0||dir.y!=0){
\r
237 this.moveArea([this.areaCoords.x1+dir.x,this.areaCoords.y1+dir.y]);
\r
241 },calcW:function(){
\r
242 return (this.areaCoords.x2-this.areaCoords.x1);
\r
243 },calcH:function(){
\r
244 return (this.areaCoords.y2-this.areaCoords.y1);
\r
245 },moveArea:function(_1e){
\r
246 this.setAreaCoords({x1:_1e[0],y1:_1e[1],x2:_1e[0]+this.calcW(),y2:_1e[1]+this.calcH()},true,false);
\r
248 },cloneCoords:function(_1f){
\r
249 return {x1:_1f.x1,y1:_1f.y1,x2:_1f.x2,y2:_1f.y2};
\r
250 },setAreaCoords:function(_20,_21,_22,_23,_24){
\r
252 var _25=_20.x2-_20.x1;
\r
253 var _26=_20.y2-_20.y1;
\r
262 if(_20.x2>this.imgW){
\r
264 _20.x1=this.imgW-_25;
\r
266 if(_20.y2>this.imgH){
\r
268 _20.y1=this.imgH-_26;
\r
277 if(_20.x2>this.imgW){
\r
280 if(_20.y2>this.imgH){
\r
285 this.applyRatio(_20,{x:this.ratioX,y:this.ratioY},_23,_24);
\r
288 this.applyRatio(_20,{x:1,y:1},_23,_24);
\r
291 var _27=[this.options.minWidth,this.options.minHeight];
\r
292 var _28=[this.options.maxWidth,this.options.maxHeight];
\r
293 if(_27[0]>0||_27[1]>0||_28[0]>0||_28[1]>0){
\r
294 var _29={a1:_20.x1,a2:_20.x2};
\r
295 var _2a={a1:_20.y1,a2:_20.y2};
\r
296 var _2b={min:0,max:this.imgW};
\r
297 var _2c={min:0,max:this.imgH};
\r
298 if((_27[0]!=0||_27[1]!=0)&&_22){
\r
307 if((_28[0]!=0||_28[0]!=0)&&_22){
\r
308 if(_28[0]>0&&_28[0]<=_28[1]){
\r
311 if(_28[1]>0&&_28[1]<=_28[0]){
\r
317 this.applyDimRestriction(_29,_27[0],_23.x,_2b,"min");
\r
320 this.applyDimRestriction(_2a,_27[1],_23.y,_2c,"min");
\r
323 this.applyDimRestriction(_29,_28[0],_23.x,_2b,"max");
\r
326 this.applyDimRestriction(_2a,_28[1],_23.y,_2c,"max");
\r
328 _20={x1:_29.a1,y1:_2a.a1,x2:_29.a2,y2:_2a.a2};
\r
332 this.areaCoords=_20;
\r
333 },applyDimRestriction:function(_2d,val,_2f,_30,_31){
\r
336 _32=((_2d.a2-_2d.a1)<val);
\r
338 _32=((_2d.a2-_2d.a1)>val);
\r
346 if(_2d.a1<_30.min){
\r
350 if(_2d.a2>_30.max){
\r
351 _2d.a1=_30.max-val;
\r
356 },applyRatio:function(_33,_34,_35,_36){
\r
358 if(_36=="N"||_36=="S"){
\r
359 _37=this.applyRatioToAxis({a1:_33.y1,b1:_33.x1,a2:_33.y2,b2:_33.x2},{a:_34.y,b:_34.x},{a:_35.y,b:_35.x},{min:0,max:this.imgW});
\r
365 _37=this.applyRatioToAxis({a1:_33.x1,b1:_33.y1,a2:_33.x2,b2:_33.y2},{a:_34.x,b:_34.y},{a:_35.x,b:_35.y},{min:0,max:this.imgH});
\r
371 },applyRatioToAxis:function(_38,_39,_3a,_3b){
\r
372 var _3c=Object.extend(_38,{});
\r
373 var _3d=_3c.a2-_3c.a1;
\r
374 var _3e=Math.floor(_3d*_39.b/_39.a);
\r
394 _40=Math.floor(_41*_39.a/_39.b);
\r
398 _3c.a1=_3c.a1=_3c.a2-_40;
\r
402 },drawArea:function(){
\r
403 var _42=this.calcW();
\r
404 var _43=this.calcH();
\r
406 var _45=[this.areaCoords.x1+px,this.areaCoords.y1+px,_42+px,_43+px,this.areaCoords.x2+px,this.areaCoords.y2+px,(this.img.width-this.areaCoords.x2)+px,(this.img.height-this.areaCoords.y2)+px];
\r
407 var _46=this.selArea.style;
\r
412 var _47=Math.ceil((_42-6)/2)+px;
\r
413 var _48=Math.ceil((_43-6)/2)+px;
\r
414 this.handleN.style.left=_47;
\r
415 this.handleE.style.top=_48;
\r
416 this.handleS.style.left=_47;
\r
417 this.handleW.style.top=_48;
\r
418 this.north.style.height=_45[1];
\r
419 var _49=this.east.style;
\r
424 var _4a=this.south.style;
\r
427 var _4b=this.west.style;
\r
431 this.subDrawArea();
\r
432 this.forceReRender();
\r
433 },forceReRender:function(){
\r
434 if(this.isIE||this.isWebKit){
\r
435 var n=document.createTextNode(" ");
\r
438 fixEl=this.selArea;
\r
441 fixEl=document.getElementsByClassName("imgCrop_marqueeSouth",this.imgWrap)[0];
\r
442 d=Builder.node("div","");
\r
443 d.style.visibility="hidden";
\r
444 var _4e=["SE","S","SW"];
\r
445 for(i=0;i<_4e.length;i++){
\r
446 el=document.getElementsByClassName("imgCrop_handle"+_4e[i],this.selArea)[0];
\r
447 if(el.childNodes.length){
\r
448 el.removeChild(el.childNodes[0]);
\r
454 fixEl.appendChild(n);
\r
455 fixEl.removeChild(n);
\r
457 },startResize:function(e){
\r
458 this.startCoords=this.cloneCoords(this.areaCoords);
\r
459 this.resizing=true;
\r
460 this.resizeHandle=Event.element(e).classNames().toString().replace(/([^N|NE|E|SE|S|SW|W|NW])+/,"");
\r
462 },startDrag:function(e){
\r
463 this.selArea.show();
\r
464 this.clickCoords=this.getCurPos(e);
\r
465 this.setAreaCoords({x1:this.clickCoords.x,y1:this.clickCoords.y,x2:this.clickCoords.x,y2:this.clickCoords.y},false,false,null);
\r
466 this.dragging=true;
\r
469 },getCurPos:function(e){
\r
470 var el=this.imgWrap,wrapOffsets=Position.cumulativeOffset(el);
\r
471 while(el.nodeName!="BODY"){
\r
472 wrapOffsets[1]-=el.scrollTop||0;
\r
473 wrapOffsets[0]-=el.scrollLeft||0;
\r
476 return curPos={x:Event.pointerX(e)-wrapOffsets[0],y:Event.pointerY(e)-wrapOffsets[1]};
\r
477 },onDrag:function(e){
\r
478 if(this.dragging||this.resizing){
\r
480 var _55=this.getCurPos(e);
\r
481 var _56=this.cloneCoords(this.areaCoords);
\r
484 if(_55.x<this.clickCoords.x){
\r
487 if(_55.y<this.clickCoords.y){
\r
490 this.transformCoords(_55.x,this.clickCoords.x,_56,"x");
\r
491 this.transformCoords(_55.y,this.clickCoords.y,_56,"y");
\r
494 _54=this.resizeHandle;
\r
495 if(_54.match(/E/)){
\r
496 this.transformCoords(_55.x,this.startCoords.x1,_56,"x");
\r
497 if(_55.x<this.startCoords.x1){
\r
501 if(_54.match(/W/)){
\r
502 this.transformCoords(_55.x,this.startCoords.x2,_56,"x");
\r
503 if(_55.x<this.startCoords.x2){
\r
508 if(_54.match(/N/)){
\r
509 this.transformCoords(_55.y,this.startCoords.y2,_56,"y");
\r
510 if(_55.y<this.startCoords.y2){
\r
514 if(_54.match(/S/)){
\r
515 this.transformCoords(_55.y,this.startCoords.y1,_56,"y");
\r
516 if(_55.y<this.startCoords.y1){
\r
523 this.setAreaCoords(_56,false,e.shiftKey,_57,_54);
\r
527 },transformCoords:function(_58,_59,_5a,_5b){
\r
532 _5a[_5b+"1"]=_5c[0];
\r
533 _5a[_5b+"2"]=_5c[1];
\r
534 },endCrop:function(){
\r
535 this.dragging=false;
\r
536 this.resizing=false;
\r
537 this.options.onEndCrop(this.areaCoords,{width:this.calcW(),height:this.calcH()});
\r
538 },subInitialize:function(){
\r
539 },subDrawArea:function(){
\r
541 Cropper.ImgWithPreview=Class.create();
\r
542 Object.extend(Object.extend(Cropper.ImgWithPreview.prototype,Cropper.Img.prototype),{subInitialize:function(){
\r
543 this.hasPreviewImg=false;
\r
544 if(typeof (this.options.previewWrap)!="undefined"&&this.options.minWidth>0&&this.options.minHeight>0){
\r
545 this.previewWrap=$PR(this.options.previewWrap);
\r
546 this.previewImg=this.img.cloneNode(false);
\r
547 this.previewImg.id="imgCrop_"+this.previewImg.id;
\r
548 this.options.displayOnInit=true;
\r
549 this.hasPreviewImg=true;
\r
550 this.previewWrap.addClassName("imgCrop_previewWrap");
\r
551 this.previewWrap.setStyle({width:this.options.minWidth+"px",height:this.options.minHeight+"px"});
\r
552 this.previewWrap.appendChild(this.previewImg);
\r
554 },subDrawArea:function(){
\r
555 if(this.hasPreviewImg){
\r
556 var _5d=this.calcW();
\r
557 var _5e=this.calcH();
\r
558 var _5f={x:this.imgW/_5d,y:this.imgH/_5e};
\r
559 var _60={x:_5d/this.options.minWidth,y:_5e/this.options.minHeight};
\r
560 var _61={w:Math.ceil(this.options.minWidth*_5f.x)+"px",h:Math.ceil(this.options.minHeight*_5f.y)+"px",x:"-"+Math.ceil(this.areaCoords.x1/_60.x)+"px",y:"-"+Math.ceil(this.areaCoords.y1/_60.y)+"px"};
\r
561 var _62=this.previewImg.style;
\r