Merge remote branch 'kc/master' into new/enh/bug_5917
[koha.git] / koha-tt / intranet-tmpl / prog / en / lib / yui / imagecropper / imagecropper-debug.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.8.0r4
6 */
7 /**
8  * @description <p>Creates a Image Cropper control.</p>
9  * @namespace YAHOO.widget
10  * @requires yahoo, dom, dragdrop, element, event, resize
11  * @module imagecropper
12  * @beta
13  */
14 (function() {
15 var Dom = YAHOO.util.Dom,
16     Event = YAHOO.util.Event,
17     Lang = YAHOO.lang;
18
19     /**
20      * @constructor
21      * @class ImageCropper
22      * @description <p>Creates a Image Cropper control.</p>
23      * @extends YAHOO.util.Element
24      * @param {String/HTMLElement} el The image element to make croppable.
25      * @param {Object} attrs Object liternal containing configuration parameters.
26     */
27     var Crop = function(el, config) {
28         YAHOO.log('Initializing', 'log', 'ImageCropper');
29         var oConfig = {
30             element: el,
31             attributes: config || {}
32         };
33
34         Crop.superclass.constructor.call(this, oConfig.element, oConfig.attributes);    
35     };
36
37     /**
38     * @private
39     * @static
40     * @property _instances
41     * @description Internal hash table for all ImageCropper instances
42     * @type Object
43     */ 
44     Crop._instances = {};
45     /**
46     * @static
47     * @method getCropperById 
48     * @description Get's an ImageCropper object by the HTML id of the image associated with the ImageCropper object.
49     * @return {Object} The ImageCropper Object
50     */ 
51     Crop.getCropperById = function(id) {
52         if (Crop._instances[id]) {
53             return Crop._instances[id];
54         }
55         return false;
56     };
57
58     YAHOO.extend(Crop, YAHOO.util.Element, {
59         /**
60         * @private
61         * @property CSS_MAIN
62         * @description The CSS class used to wrap the element 
63         * @type String
64         */
65         CSS_MAIN: 'yui-crop',
66         /**
67         * @private
68         * @property CSS_MASK
69         * @description The CSS class for the mask element
70         * @type String
71         */
72         CSS_MASK: 'yui-crop-mask',
73         /**
74         * @private
75         * @property CSS_RESIZE_MASK
76         * @description The CSS class for the mask inside the resize element
77         * @type String
78         */
79         CSS_RESIZE_MASK: 'yui-crop-resize-mask',
80
81         /**
82         * @private
83         * @property _image
84         * @description The url of the image we are cropping
85         * @type String
86         */
87         _image: null,
88         /**
89         * @private
90         * @property _active
91         * @description Flag to determine if the crop region is active
92         * @type Boolean
93         */
94         _active: null,
95         /**
96         * @private
97         * @property _resize
98         * @description A reference to the Resize Utility used in this Cropper Instance
99         * @type Object
100         */
101         _resize: null,
102         /**
103         * @private
104         * @property _resizeEl
105         * @description The HTML Element used to create the Resize Oject
106         * @type HTMLElement
107         */
108         _resizeEl: null,
109         /**
110         * @private
111         * @property _resizeMaskEl
112         * @description The HTML Element used to create the Resize mask
113         * @type HTMLElement
114         */
115         _resizeMaskEl: null,
116         /**
117         * @private
118         * @property _wrap
119         * @description The HTML Element created to wrap the image
120         * @type HTMLElement
121         */
122         _wrap: null,
123         /**
124         * @private
125         * @property _mask
126         * @description The HTML Element created to "mask" the image being cropped
127         * @type HTMLElement
128         */
129         _mask: null,
130         /**
131         * @private
132         * @method _createWrap
133         * @description Creates the wrapper element used to wrap the image
134         */
135         _createWrap: function() {
136             YAHOO.log('Creating the wrap element', 'log', 'ImageCropper');
137             this._wrap = document.createElement('div');
138             this._wrap.id = this.get('element').id + '_wrap';
139             this._wrap.className = this.CSS_MAIN;
140             var el = this.get('element');
141             this._wrap.style.width = el.width ? el.width + 'px' : Dom.getStyle(el, 'width');
142             this._wrap.style.height = el.height ? el.height + 'px' : Dom.getStyle(el, 'height');
143             
144             var par = this.get('element').parentNode;
145             par.replaceChild(this._wrap, this.get('element'));
146             this._wrap.appendChild(this.get('element'));
147
148             Event.on(this._wrap, 'mouseover', this._handleMouseOver, this, true);
149             Event.on(this._wrap, 'mouseout', this._handleMouseOut, this, true);
150
151             Event.on(this._wrap, 'click', function(ev) { Event.stopEvent(ev); }, this, true);
152         },
153
154         /**
155         * @private
156         * @method _createMask
157         * @description Creates the mask element used to mask the image
158         */
159         _createMask: function() {
160             YAHOO.log('Creating the Mask', 'log', 'ImageCropper');
161             this._mask = document.createElement('div');
162             this._mask.className = this.CSS_MASK;
163             this._wrap.appendChild(this._mask);
164         },
165
166         /**
167         * @private
168         * @method _createResize
169         * @description Creates the resize element and the instance of the Resize Utility
170         */
171         _createResize: function() {
172             YAHOO.log('Creating the Resize element', 'log', 'ImageCropper');
173             this._resizeEl = document.createElement('div');
174             this._resizeEl.className = YAHOO.util.Resize.prototype.CSS_RESIZE;
175             this._resizeEl.style.position = 'absolute';
176             
177             this._resizeEl.innerHTML = '<div class="' + this.CSS_RESIZE_MASK + '"></div>';
178             this._resizeMaskEl = this._resizeEl.firstChild;
179             this._wrap.appendChild(this._resizeEl);
180             this._resizeEl.style.top = this.get('initialXY')[1] + 'px';
181             this._resizeEl.style.left = this.get('initialXY')[0] + 'px';
182             this._resizeMaskEl.style.height = Math.floor(this.get('initHeight')) + 'px';
183             this._resizeMaskEl.style.width = Math.floor(this.get('initWidth')) + 'px';
184
185             this._resize = new YAHOO.util.Resize(this._resizeEl, {
186                 knobHandles: true,
187                 handles: 'all',
188                 draggable: true,
189                 status: this.get('status'),
190                 minWidth: this.get('minWidth'),
191                 minHeight: this.get('minHeight'),
192                 ratio: this.get('ratio'),
193                 autoRatio: this.get('autoRatio'),
194                 height: this.get('initHeight'),
195                 width: this.get('initWidth')
196             });
197
198             this._setBackgroundImage(this.get('element').getAttribute('src', 2));
199             this._setBackgroundPosition(-(this.get('initialXY')[0]),  -(this.get('initialXY')[1]));
200
201             this._resize.on('startResize', this._handleStartResizeEvent, this, true);
202             this._resize.on('endResize', this._handleEndResizeEvent, this, true);
203             this._resize.on('dragEvent', this._handleDragEvent, this, true);
204             this._resize.on('beforeResize', this._handleBeforeResizeEvent, this, true);
205             this._resize.on('resize', this._handleResizeEvent, this, true);
206             this._resize.dd.on('b4StartDragEvent', this._handleB4DragEvent, this, true);
207         },
208
209         /**
210         * @private
211         * @method _handleMouseOver
212         * @description Handles the mouseover event
213         */
214         _handleMouseOver: function(ev) {
215             var evType = 'keydown';
216             if (YAHOO.env.ua.gecko || YAHOO.env.ua.opera) {
217                 evType = 'keypress';
218             }
219             if (!this._active) {
220                 this._active = true;
221                 if (this.get('useKeys')) {
222                     Event.on(document, evType, this._handleKeyPress, this, true);
223                 }
224             }
225         },
226         /**
227         * @private
228         * @method _handleMouseOut
229         * @description Handles the mouseout event
230         */
231         _handleMouseOut: function(ev) {
232             var evType = 'keydown';
233             if (YAHOO.env.ua.gecko || YAHOO.env.ua.opera) {
234                 evType = 'keypress';
235             }
236             this._active = false;
237             if (this.get('useKeys')) {
238                 Event.removeListener(document, evType, this._handleKeyPress);
239             }
240         },
241
242         /**
243         * @private
244         * @method _moveEl
245         * @description Moves the resize element based on the arrow keys
246         */
247         _moveEl: function(dir, inc) {
248             YAHOO.log('Moving the element', 'log', 'ImageCropper');
249             var t = 0, l = 0,
250                 region = this._setConstraints(),
251                 resize = true;
252
253             switch (dir) {
254                 case 'down':
255                     t = -(inc);
256                     if ((region.bottom - inc) < 0) {
257                         resize = false;
258                         this._resizeEl.style.top = (region.top + region.bottom) + 'px';
259                     }
260                     break;
261                 case 'up':
262                     t = (inc);
263                     if ((region.top - inc) < 0) {
264                         resize = false;
265                         this._resizeEl.style.top = '0px';
266                     }
267                     break;
268                 case 'right':
269                     l = -(inc);
270                     if ((region.right - inc) < 0) {
271                         resize = false;
272                         this._resizeEl.style.left = (region.left + region.right) + 'px';
273                     }
274                     break;
275                 case 'left':
276                     l = inc;
277                     if ((region.left - inc) < 0) {
278                         resize = false;
279                         this._resizeEl.style.left = '0px';
280                     }
281                     break;
282             }
283
284             if (resize) {
285                 YAHOO.log('Moving via Key Listener: ' + dir, 'log', 'ImageCropper');
286                 this._resizeEl.style.left = (parseInt(this._resizeEl.style.left, 10) - l) + 'px';
287                 this._resizeEl.style.top = (parseInt(this._resizeEl.style.top, 10) - t) + 'px';
288                 this.fireEvent('moveEvent', { target: 'keypress' });
289             } else {
290                 this._setConstraints();
291             }
292             this._syncBackgroundPosition();
293         },
294
295         /**
296         * @private
297         * @method _handleKeyPress
298         * @description Handles the keypress event
299         */
300         _handleKeyPress: function(ev) {
301             var kc = Event.getCharCode(ev),
302                 stopEvent = false,
303                 inc = ((ev.shiftKey) ? this.get('shiftKeyTick') : this.get('keyTick'));
304
305             switch (kc) {
306                 case 0x25: // left
307                     this._moveEl('left', inc);
308                     stopEvent = true;
309                     break;
310                 case 0x26: // up
311                     this._moveEl('up', inc);
312                     stopEvent = true;
313                     break;
314                 case 0x27: // right
315                     this._moveEl('right', inc);
316                     stopEvent = true;
317                     break;
318                 case 0x28: // down
319                     this._moveEl('down', inc);
320                     stopEvent = true;
321                     break;
322                 default:
323             }
324             if (stopEvent) {
325                 Event.preventDefault(ev);
326             }
327         },
328
329         /**
330         * @private
331         * @method _handleB4DragEvent
332         * @description Handles the DragDrop b4DragEvent event
333         */
334         _handleB4DragEvent: function() {
335             this._setConstraints();
336         },
337
338         /**
339         * @private
340         * @method _handleDragEvent
341         * @description Handles the DragDrop DragEvent event
342         */
343         _handleDragEvent: function() {
344             this._syncBackgroundPosition();
345             this.fireEvent('dragEvent', arguments);
346             this.fireEvent('moveEvent', { target: 'dragevent' });
347         },
348
349         /**
350         * @private
351         * @method _handleBeforeResizeEvent
352         * @description Handles the Resize Utilitys beforeResize event
353         */
354         _handleBeforeResizeEvent: function(args) {
355             var region = Dom.getRegion(this.get('element')),
356                 c = this._resize._cache,
357                 ch = this._resize._currentHandle, h = 0, w = 0;
358
359             if (args.top && (args.top < region.top)) {
360                 h = (c.height + c.top) - region.top;
361                 Dom.setY(this._resize.getWrapEl(), region.top);
362                 this._resize.getWrapEl().style.height = h + 'px';
363                 this._resize._cache.height = h;
364                 this._resize._cache.top = region.top;
365                 this._syncBackgroundPosition();
366                 return false;
367             }
368             if (args.left && (args.left < region.left)) {
369                 w = (c.width + c.left) - region.left;
370                 Dom.setX(this._resize.getWrapEl(), region.left);
371                 this._resize._cache.left = region.left;
372                 this._resize.getWrapEl().style.width = w + 'px';
373                 this._resize._cache.width = w;
374                 this._syncBackgroundPosition();
375                 return false;
376             }
377             if (ch != 'tl' && ch != 'l' && ch != 'bl') {
378                 if (c.left && args.width && ((c.left + args.width) > region.right)) {
379                     w = (region.right - c.left);
380                     Dom.setX(this._resize.getWrapEl(), (region.right - w));
381                     this._resize.getWrapEl().style.width = w + 'px';
382                     this._resize._cache.left = (region.right - w);
383                     this._resize._cache.width = w;
384                     this._syncBackgroundPosition();
385                     return false;
386                 }
387             }
388             if (ch != 't' && ch != 'tr' && ch != 'tl') {
389                 if (c.top && args.height && ((c.top + args.height) > region.bottom)) {
390                     h = (region.bottom - c.top);
391                     Dom.setY(this._resize.getWrapEl(), (region.bottom - h));
392                     this._resize.getWrapEl().style.height = h + 'px';
393                     this._resize._cache.height = h;
394                     this._resize._cache.top = (region.bottom - h);
395                     this._syncBackgroundPosition();
396                     return false;
397                 }
398             }
399         },
400         /**
401         * @private
402         * @method _handleResizeMaskEl
403         * @description Resizes the inner mask element
404         */
405         _handleResizeMaskEl: function() {
406             var a = this._resize._cache;
407             this._resizeMaskEl.style.height = Math.floor(a.height) + 'px';
408             this._resizeMaskEl.style.width = Math.floor(a.width) + 'px';
409         },
410         /**
411         * @private
412         * @method _handleResizeEvent
413         * @param Event ev The Resize Utilitys resize event.
414         * @description Handles the Resize Utilitys Resize event
415         */
416         _handleResizeEvent: function(ev) {
417             this._setConstraints(true);
418             this._syncBackgroundPosition();
419             this.fireEvent('resizeEvent', arguments);
420             this.fireEvent('moveEvent', { target: 'resizeevent' });
421         },
422
423         /**
424         * @private
425         * @method _syncBackgroundPosition
426         * @description Syncs the packground position of the resize element with the resize elements top and left style position
427         */
428         _syncBackgroundPosition: function() {
429             this._handleResizeMaskEl();
430             this._setBackgroundPosition(-(parseInt(this._resizeEl.style.left, 10)), -(parseInt(this._resizeEl.style.top, 10)));
431         },
432
433         /**
434         * @private
435         * @method _setBackgroundPosition
436         * @param Number l The left position
437         * @param Number t The top position
438         * @description Sets the background image position to the top and left position
439         */
440         _setBackgroundPosition: function(l, t) {
441             //YAHOO.log('Setting the image background position of the mask to: (' + l + ', ' + t + ')', 'log', 'ImageCropper');
442             var bl = parseInt(Dom.getStyle(this._resize.get('element'), 'borderLeftWidth'), 10);
443             var bt = parseInt(Dom.getStyle(this._resize.get('element'), 'borderTopWidth'), 10);
444             if (isNaN(bl)) {
445                 bl = 0;
446             }
447             if (isNaN(bt)) {
448                 bt = 0;
449             }
450             var mask = this._resize.getWrapEl().firstChild;
451             var pos = (l - bl) + 'px ' + (t - bt) + 'px';
452             this._resizeMaskEl.style.backgroundPosition = pos;
453         },
454
455         /**
456         * @private
457         * @method _setBackgroundImage
458         * @param String url The url of the image
459         * @description Sets the background image of the resize element
460         */
461         _setBackgroundImage: function(url) {
462             YAHOO.log('Setting the background image', 'log', 'ImageCropper');
463             var mask = this._resize.getWrapEl().firstChild;
464             this._image = url;
465             mask.style.backgroundImage = 'url(' + url + '#)';
466         },
467         
468         /**
469         * @private
470         * @method _handleEndResizeEvent
471         * @description Handles the Resize Utilitys endResize event
472         */
473         _handleEndResizeEvent: function() {
474             this._setConstraints(true);
475         },
476         /**
477         * @private
478         * @method _handleStartResizeEvent
479         * @description Handles the Resize Utilitys startResize event
480         */
481         _handleStartResizeEvent: function() {
482             this._setConstraints(true);
483
484             var h = this._resize._cache.height,
485                  w = this._resize._cache.width,
486                  t = parseInt(this._resize.getWrapEl().style.top, 10),
487                  l = parseInt(this._resize.getWrapEl().style.left, 10),
488                  maxH = 0, maxW = 0;
489  
490             switch (this._resize._currentHandle) {
491                 case 'b':
492                     maxH = (h + this._resize.dd.bottomConstraint);
493                     break;
494                 case 'l':
495                     maxW = (w + this._resize.dd.leftConstraint);
496                     break;
497                 case 'r':
498                     maxH = (h + t);
499                     maxW = (w + this._resize.dd.rightConstraint);
500                     break;
501                  case 'br':
502                      maxH = (h + this._resize.dd.bottomConstraint);
503                      maxW = (w + this._resize.dd.rightConstraint);
504                      break;
505                  case 'tr':
506                      maxH = (h + t);
507                      maxW = (w + this._resize.dd.rightConstraint);
508                      break;
509
510              }
511             
512              if (maxH) {
513                 YAHOO.log('Setting the maxHeight on the resize object to: ' + maxH, 'log', 'ImageCropper');
514                  //this._resize.set('maxHeight', maxH);
515              }
516              if (maxW) {
517                 YAHOO.log('Setting the maxWidth on the resize object to: ' + maxW, 'log', 'ImageCropper');
518                  //this._resize.set('maxWidth', maxW);
519              }
520
521             this.fireEvent('startResizeEvent', arguments);
522         },
523         
524         /**
525         * @private
526         * @method _setConstraints
527         * @param Boolean inside Used when called from inside a resize event, false by default (dragging)
528         * @description Set the DragDrop constraints to keep the element inside the crop area.
529         * @return {Object} Object containing Top, Right, Bottom and Left constraints
530         */
531         _setConstraints: function(inside) {
532             YAHOO.log('Setting Contraints', 'log', 'ImageCropper');
533             var resize = this._resize;
534             resize.dd.resetConstraints();
535             var height = parseInt(resize.get('height'), 10),
536                 width = parseInt(resize.get('width'), 10);
537             if (inside) {
538                 //Called from inside the resize callback
539                 height = resize._cache.height;
540                 width = resize._cache.width;
541             }
542
543             //Get the top, right, bottom and left positions
544             var region = Dom.getRegion(this.get('element'));
545             //Get the element we are working on
546             var el = resize.getWrapEl();
547
548             //Get the xy position of it
549             var xy = Dom.getXY(el);
550
551             //Set left to x minus left
552             var left = xy[0] - region.left;
553
554             //Set right to right minus x minus width
555             var right = region.right - xy[0] - width;
556
557             //Set top to y minus top
558             var top = xy[1] - region.top;
559
560             //Set bottom to bottom minus y minus height
561             var bottom = region.bottom - xy[1] - height;
562
563             if (top < 0) {
564                 top = 0;
565             }
566             
567             resize.dd.setXConstraint(left, right); 
568             resize.dd.setYConstraint(top, bottom);
569             YAHOO.log('Constraints: ' + top + ',' + right + ',' + bottom + ',' + left, 'log', 'ImageCropper');
570
571             return {
572                 top: top,
573                 right: right,
574                 bottom: bottom,
575                 left: left
576             };
577
578             
579             
580         },
581         /**
582         * @method getCropCoords
583         * @description Returns the coordinates needed to crop the image
584         * @return {Object} The top, left, height, width and image url of the image being cropped
585         */
586         getCropCoords: function() {
587             var coords = {
588                 top: parseInt(this._resize.getWrapEl().style.top, 10),
589                 left: parseInt(this._resize.getWrapEl().style.left, 10),
590                 height: this._resize._cache.height,
591                 width: this._resize._cache.width,
592                 image: this._image
593             };
594             YAHOO.log('Getting the crop coordinates: ' + Lang.dump(coords), 'log', 'ImageCropper');
595             return coords;
596         },
597         /**
598         * @method reset
599         * @description Resets the crop element back to it's original position
600         * @return {<a href="YAHOO.widget.ImageCropper.html">YAHOO.widget.ImageCropper</a>} The ImageCropper instance
601         */
602         reset: function() {
603             YAHOO.log('Resetting the control', 'log', 'ImageCropper');
604             this._resize.resize(null, this.get('initHeight'), this.get('initWidth'), 0, 0, true);
605             this._resizeEl.style.top = this.get('initialXY')[1] + 'px';
606             this._resizeEl.style.left = this.get('initialXY')[0] + 'px';
607             this._syncBackgroundPosition();
608             return this;
609         },
610
611         /**
612         * @method getEl
613         * @description Get the HTML reference for the image element.
614         * @return {HTMLElement} The image element
615         */      
616         getEl: function() {
617             return this.get('element');
618         },
619         /**
620         * @method getResizeEl
621         * @description Get the HTML reference for the resize element.
622         * @return {HTMLElement} The resize element
623         */      
624         getResizeEl: function() {
625             return this._resizeEl;
626         },
627         /**
628         * @method getWrapEl
629         * @description Get the HTML reference for the wrap element.
630         * @return {HTMLElement} The wrap element
631         */      
632         getWrapEl: function() {
633             return this._wrap;
634         },
635
636         /**
637         * @method getMaskEl
638         * @description Get the HTML reference for the mask element.
639         * @return {HTMLElement} The mask element
640         */      
641         getMaskEl: function() {
642             return this._mask;
643         },
644
645         /**
646         * @method getResizeMaskEl
647         * @description Get the HTML reference for the resizable object's mask element.
648         * @return {HTMLElement} The resize objects mask element.
649         */      
650         getResizeMaskEl: function() {
651             return this._resizeMaskEl;
652         },
653
654         /**
655         * @method getResizeObject
656         * @description Get the Resize Utility object.
657         * @return {<a href="YAHOO.util.Resize.html">YAHOO.util.Resize</a>} The Resize instance
658         */      
659         getResizeObject: function() {
660             return this._resize;
661         },
662
663         /** 
664         * @private
665         * @method init
666         * @description The ImageCropper class's initialization method
667         */        
668         init: function(p_oElement, p_oAttributes) {
669             YAHOO.log('init', 'info', 'ImageCropper');
670             Crop.superclass.init.call(this, p_oElement, p_oAttributes);
671
672             var id = p_oElement;
673
674             if (!Lang.isString(id)) {
675                 if (id.tagName && (id.tagName.toLowerCase() == 'img')) {
676                     id = Dom.generateId(id);                    
677                 } else {
678                     YAHOO.log('Element is not an image.', 'error', 'ImageCropper');
679                     return false;
680                 }
681             } else {
682                 var el = Dom.get(id);
683                 if (el.tagName && el.tagName.toLowerCase() == 'img') {
684                     //All good
685                 } else {
686                     YAHOO.log('Element is not an image.', 'error', 'ImageCropper');
687                     return false;
688                 }
689             }
690             
691
692
693             Crop._instances[id] = this;
694             this._createWrap();
695             this._createMask();
696             this._createResize();
697             this._setConstraints();
698
699         },
700         /**
701         * @private
702         * @method initAttributes
703         * @description Initializes all of the configuration attributes used to create a croppable element.
704         * @param {Object} attr Object literal specifying a set of 
705         * configuration attributes used to create the widget.
706         */      
707
708         initAttributes: function(attr) {
709             Crop.superclass.initAttributes.call(this, attr);
710
711             /**
712             * @attribute initialXY
713             * @description Array of the XY position that we need to set the crop element to when we build it. Defaults to [10, 10]
714             * @type Array
715             */
716             this.setAttributeConfig('initialXY', {
717                 writeOnce: true,
718                 validator: YAHOO.lang.isArray,
719                 value: attr.initialXY || [10, 10]
720             });
721             /**
722             * @attribute keyTick
723             * @description The pixel tick for the arrow keys, defaults to 1
724             * @type Number
725             */
726             this.setAttributeConfig('keyTick', {
727                 validator: YAHOO.lang.isNumber,
728                 value: attr.keyTick || 1
729             });
730
731             /**
732             * @attribute shiftKeyTick
733             * @description The pixel tick for shift + the arrow keys, defaults to 10
734             * @type Number
735             */
736             this.setAttributeConfig('shiftKeyTick', {
737                 validator: YAHOO.lang.isNumber,
738                 value: attr.shiftKeyTick || 10
739             });
740
741             /**
742             * @attribute useKeys
743             * @description Should we use the Arrow keys to position the crop element, defaults to true
744             * @type Boolean
745             */
746             this.setAttributeConfig('useKeys', {
747                 validator: YAHOO.lang.isBoolean,
748                 value: ((attr.useKeys === false) ? false : true)
749             });
750
751             /**
752             * @attribute status
753             * @description Show the Resize Utility status, defaults to true
754             * @type Boolean
755             */
756             this.setAttributeConfig('status', {
757                 validator: YAHOO.lang.isBoolean,
758                 value: ((attr.status === false) ? false : true),
759                 method: function(status) {
760                     if (this._resize) {
761                         this._resize.set('status', status);
762                     }
763                 }
764             });
765
766             /**
767             * @attribute minHeight
768             * @description MinHeight of the crop area, default 50
769             * @type Number
770             */
771             this.setAttributeConfig('minHeight', {
772                 validator: YAHOO.lang.isNumber,
773                 value: attr.minHeight || 50,
774                 method: function(h) {
775                     if (this._resize) {
776                         this._resize.set('minHeight', h);
777                     }
778                 }
779             });
780
781             /**
782             * @attribute minWidth
783             * @description MinWidth of the crop area, default 50.
784             * @type Number
785             */
786             this.setAttributeConfig('minWidth', {
787                 validator: YAHOO.lang.isNumber,
788                 value: attr.minWidth || 50,
789                 method: function(w) {
790                     if (this._resize) {
791                         this._resize.set('minWidth', w);
792                     }
793                 }
794             });
795
796             /**
797             * @attribute ratio
798             * @description Set the ratio config option of the Resize Utlility, default false
799             * @type Boolean
800             */
801             this.setAttributeConfig('ratio', {
802                 validator: YAHOO.lang.isBoolean,
803                 value: attr.ratio || false,
804                 method: function(r) {
805                     if (this._resize) {
806                         this._resize.set('ratio', r);
807                     }
808                 }
809             });
810
811             /**
812             * @attribute ratio
813             * @description Set the autoRatio config option of the Resize Utlility, default true
814             * @type Boolean
815             */
816             this.setAttributeConfig('autoRatio', {
817                 validator: YAHOO.lang.isBoolean,
818                 value: ((attr.autoRatio === false) ? false : true),
819                 method: function(a) {
820                     if (this._resize) {
821                         this._resize.set('autoRatio', a);
822                     }
823                 }
824             });
825
826             /**
827             * @attribute initHeight
828             * @description Set the initlal height of the crop area, defaults to 1/4 of the image height
829             * @type Number
830             */
831             this.setAttributeConfig('initHeight', {
832                 writeOnce: true,
833                 validator: YAHOO.lang.isNumber,
834                 value: attr.initHeight || (this.get('element').height / 4)
835             });
836
837             /**
838             * @attribute initWidth
839             * @description Set the initlal width of the crop area, defaults to 1/4 of the image width
840             * @type Number
841             */
842             this.setAttributeConfig('initWidth', {
843                 validator: YAHOO.lang.isNumber,
844                 writeOnce: true,
845                 value: attr.initWidth || (this.get('element').width / 4)
846             });
847
848         },
849         /**
850         * @method destroy
851         * @description Destroys the ImageCropper object and all of it's elements & listeners.
852         */        
853         destroy: function() {
854             YAHOO.log('Destroying the ImageCropper', 'info', 'ImageCropper');
855             this._resize.destroy();
856             this._resizeEl.parentNode.removeChild(this._resizeEl);
857             this._mask.parentNode.removeChild(this._mask);
858             Event.purgeElement(this._wrap);
859             this._wrap.parentNode.replaceChild(this.get('element'), this._wrap);
860             
861             //Brutal Object Destroy
862             for (var i in this) {
863                 if (Lang.hasOwnProperty(this, i)) {
864                     this[i] = null;
865                 }
866             }
867                        
868         },
869         /**
870         * @method toString
871         * @description Returns a string representing the ImageCropper Object.
872         * @return {String}
873         */        
874         toString: function() {
875             if (this.get) {
876                 return 'ImageCropper (#' + this.get('id') + ')';
877             }
878             return 'Image Cropper';
879         }
880     });
881
882     YAHOO.widget.ImageCropper = Crop;
883
884 /**
885 * @event dragEvent
886 * @description Fires when the DragDrop dragEvent
887 * @type YAHOO.util.CustomEvent
888 */
889 /**
890 * @event startResizeEvent
891 * @description Fires when when a resize action is started.
892 * @type YAHOO.util.CustomEvent
893 */
894 /**
895 * @event resizeEvent
896 * @description Fires on every element resize.
897 * @type YAHOO.util.CustomEvent
898 */
899 /**
900 * @event moveEvent
901 * @description Fires on every element move. Inside these methods: _handleKeyPress, _handleDragEvent, _handleResizeEvent
902 * @type YAHOO.util.CustomEvent
903 */
904
905 })();
906
907 YAHOO.register("imagecropper", YAHOO.widget.ImageCropper, {version: "2.8.0r4", build: "2449"});