Merge remote branch 'kc/master' into new/enh/bug_5917
[koha.git] / koha-tt / intranet-tmpl / prog / en / lib / yui / resize / resize-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>Makes an element resizable</p>
9  * @namespace YAHOO.util
10  * @requires yahoo, dom, dragdrop, element, event
11  * @optional animation
12  * @module resize
13  */
14 (function() {
15 var D = YAHOO.util.Dom,
16     Event = YAHOO.util.Event,
17     Lang = YAHOO.lang;
18
19     /**
20      * @constructor
21      * @class Resize
22      * @extends YAHOO.util.Element
23      * @description <p>Makes an element resizable</p>
24      * @param {String/HTMLElement} el The element to make resizable.
25      * @param {Object} attrs Object liternal containing configuration parameters.
26     */
27
28     var Resize = function(el, config) {
29         YAHOO.log('Creating Resize Object', 'info', 'Resize');
30         var oConfig = {
31             element: el,
32             attributes: config || {}
33         };
34
35         Resize.superclass.constructor.call(this, oConfig.element, oConfig.attributes);    
36     };
37
38     /**
39     * @private
40     * @static
41     * @property _instances
42     * @description Internal hash table for all resize instances
43     * @type Object
44     */ 
45     Resize._instances = {};
46     /**
47     * @static
48     * @method getResizeById 
49     * @description Get's a resize object by the HTML id of the element associated with the Resize object.
50     * @return {Object} The Resize Object
51     */ 
52     Resize.getResizeById = function(id) {
53         if (Resize._instances[id]) {
54             return Resize._instances[id];
55         }
56         YAHOO.log('No Instance Found', 'error', 'Resize');
57         return false;
58     };
59
60     YAHOO.extend(Resize, YAHOO.util.Element, {
61         /**
62         * @private
63         * @property CSS_RESIZE
64         * @description Base CSS class name
65         * @type String
66         */ 
67         CSS_RESIZE: 'yui-resize',
68         /**
69         * @private
70         * @property CSS_DRAG
71         * @description Class name added when dragging is enabled
72         * @type String
73         */ 
74         CSS_DRAG: 'yui-draggable',
75         /**
76         * @private
77         * @property CSS_HOVER
78         * @description Class name used for hover only handles
79         * @type String
80         */ 
81         CSS_HOVER: 'yui-resize-hover',
82         /**
83         * @private
84         * @property CSS_PROXY
85         * @description Class name given to the proxy element
86         * @type String
87         */ 
88         CSS_PROXY: 'yui-resize-proxy',
89         /**
90         * @private
91         * @property CSS_WRAP
92         * @description Class name given to the wrap element
93         * @type String
94         */ 
95         CSS_WRAP: 'yui-resize-wrap',
96         /**
97         * @private
98         * @property CSS_KNOB
99         * @description Class name used to make the knob style handles
100         * @type String
101         */ 
102         CSS_KNOB: 'yui-resize-knob',
103         /**
104         * @private
105         * @property CSS_HIDDEN
106         * @description Class name given to the wrap element to make all handles hidden
107         * @type String
108         */ 
109         CSS_HIDDEN: 'yui-resize-hidden',
110         /**
111         * @private
112         * @property CSS_HANDLE
113         * @description Class name given to all handles, used as a base for single handle names as well.. Handle "t" will get this.CSS_HANDLE + '-t' as well as this.CSS_HANDLE
114         * @type String
115         */ 
116         CSS_HANDLE: 'yui-resize-handle',
117         /**
118         * @private
119         * @property CSS_STATUS
120         * @description Class name given to the status element
121         * @type String
122         */ 
123         CSS_STATUS: 'yui-resize-status',
124         /**
125         * @private
126         * @property CSS_GHOST
127         * @description Class name given to the wrap element when the ghost property is active
128         * @type String
129         */ 
130         CSS_GHOST: 'yui-resize-ghost',
131         /**
132         * @private
133         * @property CSS_RESIZING
134         * @description Class name given to the wrap element when a resize action is taking place.
135         * @type String
136         */ 
137         CSS_RESIZING: 'yui-resize-resizing',
138         /**
139         * @private
140         * @property _resizeEvent
141         * @description The mouse event used to resize with
142         * @type Event
143         */ 
144         _resizeEvent: null,
145         /**
146         * @private
147         * @property dd
148         * @description The <a href="YAHOO.util.DragDrop.html">YAHOO.util.DragDrop</a> instance used if draggable is true
149         * @type Object
150         */ 
151         dd: null,
152         /** 
153         * @private
154         * @property browser
155         * @description A copy of the YAHOO.env.ua property
156         * @type Object
157         */
158         browser: YAHOO.env.ua,
159         /** 
160         * @private
161         * @property _locked
162         * @description A flag to show if the resize is locked
163         * @type Boolean
164         */
165         _locked: null,
166         /** 
167         * @private
168         * @property _positioned
169         * @description A flag to show if the element is absolutely positioned
170         * @type Boolean
171         */
172         _positioned: null,
173         /** 
174         * @private
175         * @property _dds
176         * @description An Object containing references to all of the <a href="YAHOO.util.DragDrop.html">YAHOO.util.DragDrop</a> instances used for the resize handles
177         * @type Object
178         */
179         _dds: null,
180         /** 
181         * @private
182         * @property _wrap
183         * @description The HTML reference of the element wrapper
184         * @type HTMLElement
185         */
186         _wrap: null,
187         /** 
188         * @private
189         * @property _proxy
190         * @description The HTML reference of the element proxy
191         * @type HTMLElement
192         */
193         _proxy: null,
194         /** 
195         * @private
196         * @property _handles
197         * @description An object containing references to all of the resize handles.
198         * @type Object
199         */
200         _handles: null,
201         /** 
202         * @private
203         * @property _currentHandle
204         * @description The string identifier of the currently active handle. e.g. 'r', 'br', 'tl'
205         * @type String
206         */
207         _currentHandle: null,
208         /** 
209         * @private
210         * @property _currentDD
211         * @description A link to the currently active DD object
212         * @type Object
213         */
214         _currentDD: null,
215         /** 
216         * @private
217         * @property _cache
218         * @description An lookup table containing key information for the element being resized. e.g. height, width, x position, y position, etc..
219         * @type Object
220         */
221         _cache: null,
222         /** 
223         * @private
224         * @property _active
225         * @description Flag to show if the resize is active. Used for events.
226         * @type Boolean
227         */
228         _active: null,
229         /** 
230         * @private
231         * @method _createProxy
232         * @description Creates the proxy element if the proxy config is true
233         */
234         _createProxy: function() {
235             if (this.get('proxy')) {
236                 YAHOO.log('Creating the Proxy Element', 'info', 'Resize');
237                 this._proxy = document.createElement('div');
238                 this._proxy.className = this.CSS_PROXY;
239                 this._proxy.style.height = this.get('element').clientHeight + 'px';
240                 this._proxy.style.width = this.get('element').clientWidth + 'px';
241                 this._wrap.parentNode.appendChild(this._proxy);
242             } else {
243                 YAHOO.log('No proxy element, turn off animate config option', 'info', 'Resize');
244                 this.set('animate', false);
245             }
246         },
247         /** 
248         * @private
249         * @method _createWrap
250         * @description Creates the wrap element if the wrap config is true. It will auto wrap the following element types: img, textarea, input, iframe, select
251         */
252         _createWrap: function() {
253             YAHOO.log('Create the wrap element', 'info', 'Resize');
254             this._positioned = false;
255             //Force wrap for elements that can't have children 
256             if (this.get('wrap') === false) {
257                 switch (this.get('element').tagName.toLowerCase()) {
258                     case 'img':
259                     case 'textarea':
260                     case 'input':
261                     case 'iframe':
262                     case 'select':
263                         YAHOO.log('Auto-wrapping the element (' + this.get('element').tagName.toLowerCase() + ')', 'warn', 'Resize');
264                         this.set('wrap', true);
265                         break;
266                 }
267             }
268             if (this.get('wrap') === true) {
269                 YAHOO.log('Creating the wrap element', 'info', 'Resize');
270                 this._wrap = document.createElement('div');
271                 this._wrap.id = this.get('element').id + '_wrap';
272                 this._wrap.className = this.CSS_WRAP;
273                 if (this.get('element').tagName.toLowerCase() == 'textarea') {
274                     D.addClass(this._wrap, 'yui-resize-textarea');
275                 }
276                 D.setStyle(this._wrap, 'width', this.get('width') + 'px');
277                 D.setStyle(this._wrap, 'height', this.get('height') + 'px');
278                 D.setStyle(this._wrap, 'z-index', this.getStyle('z-index'));
279                 this.setStyle('z-index', 0);
280                 var pos = D.getStyle(this.get('element'), 'position');
281                 D.setStyle(this._wrap, 'position', ((pos == 'static') ? 'relative' : pos));
282                 D.setStyle(this._wrap, 'top', D.getStyle(this.get('element'), 'top'));
283                 D.setStyle(this._wrap, 'left', D.getStyle(this.get('element'), 'left'));
284                 if (D.getStyle(this.get('element'), 'position') == 'absolute') {
285                     this._positioned = true;
286                     YAHOO.log('The element is positioned absolute', 'info', 'Resize');
287                     D.setStyle(this.get('element'), 'position', 'relative');
288                     D.setStyle(this.get('element'), 'top', '0');
289                     D.setStyle(this.get('element'), 'left', '0');
290                 }
291                 var par = this.get('element').parentNode;
292                 par.replaceChild(this._wrap, this.get('element'));
293                 this._wrap.appendChild(this.get('element'));
294             } else {
295                 this._wrap = this.get('element');
296                 if (D.getStyle(this._wrap, 'position') == 'absolute') {
297                     this._positioned = true;
298                 }
299             }
300             if (this.get('draggable')) {
301                 this._setupDragDrop();
302             }
303             if (this.get('hover')) {
304                 D.addClass(this._wrap, this.CSS_HOVER);
305             }
306             if (this.get('knobHandles')) {
307                 D.addClass(this._wrap, this.CSS_KNOB);
308             }
309             if (this.get('hiddenHandles')) {
310                 D.addClass(this._wrap, this.CSS_HIDDEN);
311             }
312             D.addClass(this._wrap, this.CSS_RESIZE);
313         },
314         /** 
315         * @private
316         * @method _setupDragDrop
317         * @description Setup the <a href="YAHOO.util.DragDrop.html">YAHOO.util.DragDrop</a> instance on the element
318         */
319         _setupDragDrop: function() {
320             YAHOO.log('Setting up the dragdrop instance on the element', 'info', 'Resize');
321             D.addClass(this._wrap, this.CSS_DRAG);
322             this.dd = new YAHOO.util.DD(this._wrap, this.get('id') + '-resize', { dragOnly: true, useShim: this.get('useShim') });
323             this.dd.on('dragEvent', function() {
324                 this.fireEvent('dragEvent', arguments);
325             }, this, true);
326         },
327         /** 
328         * @private
329         * @method _createHandles
330         * @description Creates the handles as specified in the config
331         */
332         _createHandles: function() {
333             YAHOO.log('Creating the handles', 'info', 'Resize');
334             this._handles = {};
335             this._dds = {};
336             var h = this.get('handles');
337             for (var i = 0; i < h.length; i++) {
338                 YAHOO.log('Creating handle position: ' + h[i], 'info', 'Resize');
339                 this._handles[h[i]] = document.createElement('div');
340                 this._handles[h[i]].id = D.generateId(this._handles[h[i]]);
341                 this._handles[h[i]].className = this.CSS_HANDLE + ' ' + this.CSS_HANDLE + '-' + h[i];
342                 var k = document.createElement('div');
343                 k.className = this.CSS_HANDLE + '-inner-' + h[i];
344                 this._handles[h[i]].appendChild(k);
345                 this._wrap.appendChild(this._handles[h[i]]);
346                 Event.on(this._handles[h[i]], 'mouseover', this._handleMouseOver, this, true);
347                 Event.on(this._handles[h[i]], 'mouseout', this._handleMouseOut, this, true);
348                 this._dds[h[i]] = new YAHOO.util.DragDrop(this._handles[h[i]], this.get('id') + '-handle-' + h, { useShim: this.get('useShim') });
349                 this._dds[h[i]].setPadding(15, 15, 15, 15);
350                 this._dds[h[i]].on('startDragEvent', this._handleStartDrag, this._dds[h[i]], this);
351                 this._dds[h[i]].on('mouseDownEvent', this._handleMouseDown, this._dds[h[i]], this);
352             }
353             YAHOO.log('Creating the Status box', 'info', 'Resize');
354             this._status = document.createElement('span');
355             this._status.className = this.CSS_STATUS;
356             document.body.insertBefore(this._status, document.body.firstChild);
357         },
358         /** 
359         * @private
360         * @method _ieSelectFix
361         * @description The function we use as the onselectstart handler when we start a drag in Internet Explorer
362         */
363         _ieSelectFix: function() {
364             return false;
365         },
366         /** 
367         * @private
368         * @property _ieSelectBack
369         * @description We will hold a copy of the current "onselectstart" method on this property, and reset it after we are done using it.
370         */
371         _ieSelectBack: null,
372         /** 
373         * @private
374         * @method _setAutoRatio
375         * @param {Event} ev A mouse event.
376         * @description This method checks to see if the "autoRatio" config is set. If it is, we will check to see if the "Shift Key" is pressed. If so, we will set the config ratio to true.
377         */
378         _setAutoRatio: function(ev) {
379             if (this.get('autoRatio')) {
380                 YAHOO.log('Setting up AutoRatio', 'info', 'Resize');
381                 if (ev && ev.shiftKey) {
382                     //Shift Pressed
383                     YAHOO.log('Shift key presses, turning on ratio', 'info', 'Resize');
384                     this.set('ratio', true);
385                 } else {
386                     YAHOO.log('Resetting ratio back to default', 'info', 'Resize');
387                     this.set('ratio', this._configs.ratio._initialConfig.value);
388                 }
389             }
390         },
391         /** 
392         * @private
393         * @method _handleMouseDown
394         * @param {Event} ev A mouse event.
395         * @description This method preps the autoRatio on MouseDown.
396         */
397         _handleMouseDown: function(ev) {
398             if (this._locked) {
399                 YAHOO.log('Resize Locked', 'info', 'Resize');
400                 return false;
401             }
402             if (D.getStyle(this._wrap, 'position') == 'absolute') {
403                 this._positioned = true;
404             }
405             if (ev) {
406                 this._setAutoRatio(ev);
407             }
408             if (this.browser.ie) {
409                 this._ieSelectBack = document.body.onselectstart;
410                 document.body.onselectstart = this._ieSelectFix;
411             }
412         },
413         /** 
414         * @private
415         * @method _handleMouseOver
416         * @param {Event} ev A mouse event.
417         * @description Adds CSS class names to the handles
418         */
419         _handleMouseOver: function(ev) {
420             if (this._locked) {
421                 YAHOO.log('Resize Locked', 'info', 'Resize');
422                 return false;
423             }
424             D.removeClass(this._wrap, this.CSS_RESIZE);
425
426             if (this.get('hover')) {
427                 D.removeClass(this._wrap, this.CSS_HOVER);
428             }
429             var tar = Event.getTarget(ev);
430             if (!D.hasClass(tar, this.CSS_HANDLE)) {
431                 tar = tar.parentNode;
432             }
433             if (D.hasClass(tar, this.CSS_HANDLE) && !this._active) {
434                 D.addClass(tar, this.CSS_HANDLE + '-active');
435                 for (var i in this._handles) {
436                     if (Lang.hasOwnProperty(this._handles, i)) {
437                         if (this._handles[i] == tar) {
438                             D.addClass(tar, this.CSS_HANDLE + '-' + i + '-active');
439                             break;
440                         }
441                     }
442                 }
443             }
444
445             D.addClass(this._wrap, this.CSS_RESIZE);
446         },
447         /** 
448         * @private
449         * @method _handleMouseOut
450         * @param {Event} ev A mouse event.
451         * @description Removes CSS class names to the handles
452         */
453         _handleMouseOut: function(ev) {
454             D.removeClass(this._wrap, this.CSS_RESIZE);
455             if (this.get('hover') && !this._active) {
456                 D.addClass(this._wrap, this.CSS_HOVER);
457             }
458             var tar = Event.getTarget(ev);
459             if (!D.hasClass(tar, this.CSS_HANDLE)) {
460                 tar = tar.parentNode;
461             }
462             if (D.hasClass(tar, this.CSS_HANDLE) && !this._active) {
463                 D.removeClass(tar, this.CSS_HANDLE + '-active');
464                 for (var i in this._handles) {
465                     if (Lang.hasOwnProperty(this._handles, i)) {
466                         if (this._handles[i] == tar) {
467                             D.removeClass(tar, this.CSS_HANDLE + '-' + i + '-active');
468                             break;
469                         }
470                     }
471                 }
472             }
473             D.addClass(this._wrap, this.CSS_RESIZE);
474         },
475         /** 
476         * @private
477         * @method _handleStartDrag
478         * @param {Object} args The args passed from the CustomEvent.
479         * @param {Object} dd The <a href="YAHOO.util.DragDrop.html">YAHOO.util.DragDrop</a> object we are working with.
480         * @description Resizes the proxy, sets up the <a href="YAHOO.util.DragDrop.html">YAHOO.util.DragDrop</a> handlers, updates the status div and preps the cache
481         */
482         _handleStartDrag: function(args, dd) {
483             YAHOO.log('startDrag', 'info', 'Resize');
484             var tar = dd.getDragEl();
485             if (D.hasClass(tar, this.CSS_HANDLE)) {
486                 if (D.getStyle(this._wrap, 'position') == 'absolute') {
487                     this._positioned = true;
488                 }
489                 this._active = true;
490                 this._currentDD = dd;
491                 if (this._proxy) {
492                     YAHOO.log('Activate proxy element', 'info', 'Resize');
493                     this._proxy.style.visibility = 'visible';
494                     this._proxy.style.zIndex = '1000';
495                     this._proxy.style.height = this.get('element').clientHeight + 'px';
496                     this._proxy.style.width = this.get('element').clientWidth + 'px';
497                 }
498
499                 for (var i in this._handles) {
500                     if (Lang.hasOwnProperty(this._handles, i)) {
501                         if (this._handles[i] == tar) {
502                             this._currentHandle = i;
503                             var handle = '_handle_for_' + i;
504                             D.addClass(tar, this.CSS_HANDLE + '-' + i + '-active');
505                             dd.on('dragEvent', this[handle], this, true);
506                             dd.on('mouseUpEvent', this._handleMouseUp, this, true);
507                             YAHOO.log('Adding DragEvents to: ' + i, 'info', 'Resize');
508                             break;
509                         }
510                     }
511                 }
512
513
514                 D.addClass(tar, this.CSS_HANDLE + '-active');
515
516                 if (this.get('proxy')) {
517                     YAHOO.log('Posiiton Proxy Element', 'info', 'Resize');
518                     var xy = D.getXY(this.get('element'));
519                     D.setXY(this._proxy, xy);
520                     if (this.get('ghost')) {
521                         YAHOO.log('Add Ghost Class', 'info', 'Resize');
522                         this.addClass(this.CSS_GHOST);
523                     }
524                 }
525                 D.addClass(this._wrap, this.CSS_RESIZING);
526                 this._setCache();
527                 this._updateStatus(this._cache.height, this._cache.width, this._cache.top, this._cache.left);
528                 YAHOO.log('Firing startResize Event', 'info', 'Resize');
529                 this.fireEvent('startResize', { type: 'startresize', target: this});
530             }
531         },
532         /** 
533         * @private
534         * @method _setCache
535         * @description Sets up the this._cache hash table.
536         */
537         _setCache: function() {
538             YAHOO.log('Setting up property cache', 'info', 'Resize');
539             this._cache.xy = D.getXY(this._wrap);
540             D.setXY(this._wrap, this._cache.xy);
541             this._cache.height = this.get('clientHeight');
542             this._cache.width = this.get('clientWidth');
543             this._cache.start.height = this._cache.height;
544             this._cache.start.width = this._cache.width;
545             this._cache.start.top = this._cache.xy[1];
546             this._cache.start.left = this._cache.xy[0];
547             this._cache.top = this._cache.xy[1];
548             this._cache.left = this._cache.xy[0];
549             this.set('height', this._cache.height, true);
550             this.set('width', this._cache.width, true);
551         },
552         /** 
553         * @private
554         * @method _handleMouseUp
555         * @param {Event} ev A mouse event.
556         * @description Cleans up listeners, hides proxy element and removes class names.
557         */
558         _handleMouseUp: function(ev) {
559             this._active = false;
560
561             var handle = '_handle_for_' + this._currentHandle;
562             this._currentDD.unsubscribe('dragEvent', this[handle], this, true);
563             this._currentDD.unsubscribe('mouseUpEvent', this._handleMouseUp, this, true);
564
565             if (this._proxy) {
566                 YAHOO.log('Hide Proxy Element', 'info', 'Resize');
567                 this._proxy.style.visibility = 'hidden';
568                 this._proxy.style.zIndex = '-1';
569                 if (this.get('setSize')) {
570                     YAHOO.log('Setting Size', 'info', 'Resize');
571                     this.resize(ev, this._cache.height, this._cache.width, this._cache.top, this._cache.left, true);
572                 } else {
573                     YAHOO.log('Firing Resize Event', 'info', 'Resize');
574                     this.fireEvent('resize', { ev: 'resize', target: this, height: this._cache.height, width: this._cache.width, top: this._cache.top, left: this._cache.left });
575                 }
576
577                 if (this.get('ghost')) {
578                     YAHOO.log('Removing Ghost Class', 'info', 'Resize');
579                     this.removeClass(this.CSS_GHOST);
580                 }
581             }
582
583             if (this.get('hover')) {
584                 D.addClass(this._wrap, this.CSS_HOVER);
585             }
586             if (this._status) {
587                 D.setStyle(this._status, 'display', 'none');
588             }
589             if (this.browser.ie) {
590                 YAHOO.log('Resetting IE onselectstart function', 'info', 'Resize');
591                 document.body.onselectstart = this._ieSelectBack;
592             }
593
594             if (this.browser.ie) {
595                 D.removeClass(this._wrap, this.CSS_RESIZE);
596             }
597
598             for (var i in this._handles) {
599                 if (Lang.hasOwnProperty(this._handles, i)) {
600                     D.removeClass(this._handles[i], this.CSS_HANDLE + '-active');
601                 }
602             }
603             if (this.get('hover') && !this._active) {
604                 D.addClass(this._wrap, this.CSS_HOVER);
605             }
606             D.removeClass(this._wrap, this.CSS_RESIZING);
607
608             D.removeClass(this._handles[this._currentHandle], this.CSS_HANDLE + '-' + this._currentHandle + '-active');
609             D.removeClass(this._handles[this._currentHandle], this.CSS_HANDLE + '-active');
610
611             if (this.browser.ie) {
612                 D.addClass(this._wrap, this.CSS_RESIZE);
613             }
614
615             this._resizeEvent = null;
616             this._currentHandle = null;
617             
618             if (!this.get('animate')) {
619                 this.set('height', this._cache.height, true);
620                 this.set('width', this._cache.width, true);
621             }
622
623             YAHOO.log('Firing endResize Event', 'info', 'Resize');
624             this.fireEvent('endResize', { ev: 'endResize', target: this, height: this._cache.height, width: this._cache.width, top: this._cache.top, left: this._cache.left });
625         },
626         /** 
627         * @private
628         * @method _setRatio
629         * @param {Number} h The height offset.
630         * @param {Number} w The with offset.
631         * @param {Number} t The top offset.
632         * @param {Number} l The left offset.
633         * @description Using the Height, Width, Top & Left, it recalcuates them based on the original element size.
634         * @return {Array} The new Height, Width, Top & Left settings
635         */
636         _setRatio: function(h, w, t, l) {
637             YAHOO.log('Setting Ratio', 'info', 'Resize');
638             var oh = h, ow = w;
639             if (this.get('ratio')) {
640                 var orgH = this._cache.height,
641                     orgW = this._cache.width,
642                     nh = parseInt(this.get('height'), 10),
643                     nw = parseInt(this.get('width'), 10),
644                     maxH = this.get('maxHeight'),
645                     minH = this.get('minHeight'),
646                     maxW = this.get('maxWidth'),
647                     minW = this.get('minWidth');
648
649                 switch (this._currentHandle) {
650                     case 'l':
651                         h = nh * (w / nw);
652                         h = Math.min(Math.max(minH, h), maxH);                        
653                         w = nw * (h / nh);
654                         t = (this._cache.start.top - (-((nh - h) / 2)));
655                         l = (this._cache.start.left - (-((nw - w))));
656                         break;
657                     case 'r':
658                         h = nh * (w / nw);
659                         h = Math.min(Math.max(minH, h), maxH);                        
660                         w = nw * (h / nh);
661                         t = (this._cache.start.top - (-((nh - h) / 2)));
662                         break;
663                     case 't':
664                         w = nw * (h / nh);
665                         h = nh * (w / nw);
666                         l = (this._cache.start.left - (-((nw - w) / 2)));
667                         t = (this._cache.start.top - (-((nh - h))));
668                         break;
669                     case 'b':
670                         w = nw * (h / nh);
671                         h = nh * (w / nw);
672                         l = (this._cache.start.left - (-((nw - w) / 2)));
673                         break;
674                     case 'bl':
675                         h = nh * (w / nw);
676                         w = nw * (h / nh);
677                         l = (this._cache.start.left - (-((nw - w))));
678                         break;
679                     case 'br':
680                         h = nh * (w / nw);
681                         w = nw * (h / nh);
682                         break;
683                     case 'tl':
684                         h = nh * (w / nw);
685                         w = nw * (h / nh);
686                         l = (this._cache.start.left - (-((nw - w))));
687                         t = (this._cache.start.top - (-((nh - h))));
688                         break;
689                     case 'tr':
690                         h = nh * (w / nw);
691                         w = nw * (h / nh);
692                         l = (this._cache.start.left);
693                         t = (this._cache.start.top - (-((nh - h))));
694                         break;
695                 }
696                 oh = this._checkHeight(h);
697                 ow = this._checkWidth(w);
698                 if ((oh != h) || (ow != w)) {
699                     t = 0;
700                     l = 0;
701                     if (oh != h) {
702                         ow = this._cache.width;
703                     }
704                     if (ow != w) {
705                         oh = this._cache.height;
706                     }
707                 }
708             }
709             return [oh, ow, t, l];
710         },
711         /** 
712         * @private
713         * @method _updateStatus
714         * @param {Number} h The new height setting.
715         * @param {Number} w The new width setting.
716         * @param {Number} t The new top setting.
717         * @param {Number} l The new left setting.
718         * @description Using the Height, Width, Top & Left, it updates the status element with the elements sizes.
719         */
720         _updateStatus: function(h, w, t, l) {
721             if (this._resizeEvent && (!Lang.isString(this._resizeEvent))) {
722                 YAHOO.log('Updating Status Box', 'info', 'Resize');
723                 h = ((h === 0) ? this._cache.start.height : h);
724                 w = ((w === 0) ? this._cache.start.width : w);
725                 var h1 = parseInt(this.get('height'), 10),
726                     w1 = parseInt(this.get('width'), 10);
727                 
728                 if (isNaN(h1)) {
729                     h1 = parseInt(h, 10);
730                 }
731                 if (isNaN(w1)) {
732                     w1 = parseInt(w, 10);
733                 }
734                 var diffH = (parseInt(h, 10) - h1);
735                 var diffW = (parseInt(w, 10) - w1);
736                 this._cache.offsetHeight = diffH;
737                 this._cache.offsetWidth = diffW;
738                 if (this.get('status')) {
739                     YAHOO.log('Showing Status Box', 'info', 'Resize');
740                     D.setStyle(this._status, 'display', 'inline');
741                     //This will cause IE8 to crash if the status box is hidden..
742                     this._status.innerHTML = '<strong>' + parseInt(h, 10) + ' x ' + parseInt(w, 10) + '</strong><em>' + ((diffH > 0) ? '+' : '') + diffH + ' x ' + ((diffW > 0) ? '+' : '') + diffW + '</em>';
743                     D.setXY(this._status, [Event.getPageX(this._resizeEvent) + 12, Event.getPageY(this._resizeEvent) + 12]);
744                 }
745             }
746         },
747         /** 
748         * @method lock
749         * @description Lock the resize so it can't be resized
750         * @param {Boolean} dd If the draggable config is set, lock it too
751         * @return {<a href="YAHOO.util.Resize.html">YAHOO.util.Resize</a>} The Resize instance
752         */
753         lock: function(dd) {
754             this._locked = true;
755             if (dd && this.dd) {
756                 D.removeClass(this._wrap, 'yui-draggable');
757                 this.dd.lock();
758             }
759             return this;
760         },
761         /** 
762         * @method unlock
763         * @description Unlock the resize so it can be resized
764         * @param {Boolean} dd If the draggable config is set, unlock it too
765         * @return {<a href="YAHOO.util.Resize.html">YAHOO.util.Resize</a>} The Resize instance
766         */
767         unlock: function(dd) {
768             this._locked = false;
769             if (dd && this.dd) {
770                 D.addClass(this._wrap, 'yui-draggable');
771                 this.dd.unlock();
772             }
773             return this;
774         },
775         /** 
776         * @method isLocked
777         * @description Check the locked status of the resize instance
778         * @return {Boolean}
779         */
780         isLocked: function() {
781             return this._locked;
782         },
783         /** 
784         * @method reset
785         * @description Resets the element to is start state.
786         * @return {<a href="YAHOO.util.Resize.html">YAHOO.util.Resize</a>} The Resize instance
787         */
788         reset: function() {
789             YAHOO.log('Resetting to cached sizes and position', 'info', 'Resize');
790             this.resize(null, this._cache.start.height, this._cache.start.width, this._cache.start.top, this._cache.start.left, true);
791             return this;
792         },
793         /** 
794         * @private
795         * @method resize
796         * @param {Event} ev The mouse event.
797         * @param {Number} h The new height setting.
798         * @param {Number} w The new width setting.
799         * @param {Number} t The new top setting.
800         * @param {Number} l The new left setting.
801         * @param {Boolean} force Resize the element (used for proxy resize).
802         * @param {Boolean} silent Don't fire the beforeResize Event.
803         * @description Resizes the element, wrapper or proxy based on the data from the handlers.
804         * @return {<a href="YAHOO.util.Resize.html">YAHOO.util.Resize</a>} The Resize instance
805         */
806         resize: function(ev, h, w, t, l, force, silent) {
807             if (this._locked) {
808                 YAHOO.log('Resize Locked', 'info', 'Resize');
809                 return false;
810             }
811             YAHOO.log('Resize: ' + h + ',' + w + ',' + t + ',' + l, 'info', 'Resize');
812             this._resizeEvent = ev;
813             var el = this._wrap, anim = this.get('animate'), set = true;
814             if (this._proxy && !force) {
815                 el = this._proxy;
816                 anim = false;
817             }
818             this._setAutoRatio(ev);
819             if (this._positioned) {
820                 if (this._proxy) {
821                     t = this._cache.top - t;
822                     l = this._cache.left - l;
823                 }
824             }
825             
826             
827             var ratio = this._setRatio(h, w, t, l);
828             h = parseInt(ratio[0], 10);
829             w = parseInt(ratio[1], 10);
830             t = parseInt(ratio[2], 10);
831             l = parseInt(ratio[3], 10);
832             
833             if (t == 0) {
834                 //No Offset, get from cache
835                 t = D.getY(el);
836             }
837             if (l == 0) {
838                 //No Offset, get from cache
839                 l = D.getX(el);
840             }
841
842             
843
844             if (this._positioned) {
845                 if (this._proxy && force) {
846                     if (!anim) {
847                         el.style.top = this._proxy.style.top;
848                         el.style.left = this._proxy.style.left;
849                     } else {
850                         t = this._proxy.style.top;
851                         l = this._proxy.style.left;
852                     }
853                 } else {
854                     if (!this.get('ratio') && !this._proxy) {
855                         t = this._cache.top + -(t);
856                         l = this._cache.left + -(l);
857                     }
858                     if (t) {
859                         if (this.get('minY')) {
860                             if (t < this.get('minY')) {
861                                 t = this.get('minY');
862                             }
863                         }
864                         if (this.get('maxY')) {
865                             if (t > this.get('maxY')) {
866                                 t = this.get('maxY');
867                             }
868                         }
869                     }
870                     if (l) {
871                         if (this.get('minX')) {
872                             if (l < this.get('minX')) {
873                                 l = this.get('minX');
874                             }
875                         }
876                         if (this.get('maxX')) {
877                             if ((l + w) > this.get('maxX')) {
878                                 l = (this.get('maxX') - w);
879                             }
880                         }
881                     }
882                 }
883             }
884             if (!silent) {
885                 YAHOO.log('beforeResize', 'info', 'Resize');
886                 var beforeReturn = this.fireEvent('beforeResize', { ev: 'beforeResize', target: this, height: h, width: w, top: t, left: l });
887                 if (beforeReturn === false) {
888                     YAHOO.log('Resized cancelled because befireResize returned false', 'info', 'Resize');
889                     return false;
890                 }
891             }
892
893             this._updateStatus(h, w, t, l);
894
895
896             if (this._positioned) {
897                 if (this._proxy && force) {
898                     //Do nothing
899                 } else {
900                     if (t) {
901                         D.setY(el, t);
902                         this._cache.top = t;
903                     }
904                     if (l) {
905                         D.setX(el, l);
906                         this._cache.left = l;
907                     }
908                 }
909             }
910             if (h) {
911                 if (!anim) {
912                     set = true;
913                     if (this._proxy && force) {
914                         if (!this.get('setSize')) {
915                             set = false;
916                         }
917                     }
918                     if (set) {
919                         el.style.height = h + 'px';
920                     }
921                     if ((this._proxy && force) || !this._proxy) {
922                         if (this._wrap != this.get('element')) {
923                             this.get('element').style.height = h + 'px';
924                         }
925                     }
926                 }
927                 this._cache.height = h;
928             }
929             if (w) {
930                 this._cache.width = w;
931                 if (!anim) {
932                     set = true;
933                     if (this._proxy && force) {
934                         if (!this.get('setSize')) {
935                             set = false;
936                         }
937                     }
938                     if (set) {
939                         el.style.width = w + 'px';
940                     }
941                     if ((this._proxy && force) || !this._proxy) {
942                         if (this._wrap != this.get('element')) {
943                             this.get('element').style.width = w + 'px';
944                         }
945                     }
946                 }
947             }
948             if (anim) {
949                 if (YAHOO.util.Anim) {
950                     var _anim = new YAHOO.util.Anim(el, {
951                         height: {
952                             to: this._cache.height
953                         },
954                         width: {
955                             to: this._cache.width
956                         }
957                     }, this.get('animateDuration'), this.get('animateEasing'));
958                     if (this._positioned) {
959                         if (t) {
960                             _anim.attributes.top = {
961                                 to: parseInt(t, 10)
962                             };
963                         }
964                         if (l) {
965                             _anim.attributes.left = {
966                                 to: parseInt(l, 10)
967                             };
968                         }
969                     }
970
971                     if (this._wrap != this.get('element')) {
972                         _anim.onTween.subscribe(function() {
973                             this.get('element').style.height = el.style.height;
974                             this.get('element').style.width = el.style.width;
975                         }, this, true);
976                     }
977
978                     _anim.onComplete.subscribe(function() {
979                         YAHOO.log('Animation onComplete fired', 'info', 'Resize');
980                         this.set('height', h);
981                         this.set('width', w);
982                         this.fireEvent('resize', { ev: 'resize', target: this, height: h, width: w, top: t, left: l });
983                     }, this, true);
984                     _anim.animate();
985
986                 }
987             } else {
988                 if (this._proxy && !force) {
989                     YAHOO.log('proxyResize', 'info', 'Resize');
990                     this.fireEvent('proxyResize', { ev: 'proxyresize', target: this, height: h, width: w, top: t, left: l });
991                 } else {
992                     YAHOO.log('resize', 'info', 'Resize');
993                     this.fireEvent('resize', { ev: 'resize', target: this, height: h, width: w, top: t, left: l });
994                 }
995             }
996             return this;
997         },
998         /** 
999         * @private
1000         * @method _handle_for_br
1001         * @param {Object} args The arguments from the CustomEvent.
1002         * @description Handles the sizes for the Bottom Right handle.
1003         */
1004         _handle_for_br: function(args) {
1005             YAHOO.log('Handle BR', 'info', 'Resize');
1006             var newW = this._setWidth(args.e);
1007             var newH = this._setHeight(args.e);
1008             this.resize(args.e, newH, newW, 0, 0);
1009         },
1010         /** 
1011         * @private
1012         * @method _handle_for_bl
1013         * @param {Object} args The arguments from the CustomEvent.
1014         * @description Handles the sizes for the Bottom Left handle.
1015         */
1016         _handle_for_bl: function(args) {
1017             YAHOO.log('Handle BL', 'info', 'Resize');
1018             var newW = this._setWidth(args.e, true);
1019             var newH = this._setHeight(args.e);
1020             var l = (newW - this._cache.width);
1021             this.resize(args.e, newH, newW, 0, l);
1022         },
1023         /** 
1024         * @private
1025         * @method _handle_for_tl
1026         * @param {Object} args The arguments from the CustomEvent.
1027         * @description Handles the sizes for the Top Left handle.
1028         */
1029         _handle_for_tl: function(args) {
1030             YAHOO.log('Handle TL', 'info', 'Resize');
1031             var newW = this._setWidth(args.e, true);
1032             var newH = this._setHeight(args.e, true);
1033             var t = (newH - this._cache.height);
1034             var l = (newW - this._cache.width);
1035             this.resize(args.e, newH, newW, t, l);
1036         },
1037         /** 
1038         * @private
1039         * @method _handle_for_tr
1040         * @param {Object} args The arguments from the CustomEvent.
1041         * @description Handles the sizes for the Top Right handle.
1042         */
1043         _handle_for_tr: function(args) {
1044             YAHOO.log('Handle TR', 'info', 'Resize');
1045             var newW = this._setWidth(args.e);
1046             var newH = this._setHeight(args.e, true);
1047             var t = (newH - this._cache.height);
1048             this.resize(args.e, newH, newW, t, 0);
1049         },
1050         /** 
1051         * @private
1052         * @method _handle_for_r
1053         * @param {Object} args The arguments from the CustomEvent.
1054         * @description Handles the sizes for the Right handle.
1055         */
1056         _handle_for_r: function(args) {
1057             YAHOO.log('Handle R', 'info', 'Resize');
1058             this._dds.r.setYConstraint(0,0);
1059             var newW = this._setWidth(args.e);
1060             this.resize(args.e, 0, newW, 0, 0);
1061         },
1062         /** 
1063         * @private
1064         * @method _handle_for_l
1065         * @param {Object} args The arguments from the CustomEvent.
1066         * @description Handles the sizes for the Left handle.
1067         */
1068         _handle_for_l: function(args) {
1069             YAHOO.log('Handle L', 'info', 'Resize');
1070             this._dds.l.setYConstraint(0,0);
1071             var newW = this._setWidth(args.e, true);
1072             var l = (newW - this._cache.width);
1073             this.resize(args.e, 0, newW, 0, l);
1074         },
1075         /** 
1076         * @private
1077         * @method _handle_for_b
1078         * @param {Object} args The arguments from the CustomEvent.
1079         * @description Handles the sizes for the Bottom handle.
1080         */
1081         _handle_for_b: function(args) {
1082             YAHOO.log('Handle B', 'info', 'Resize');
1083             this._dds.b.setXConstraint(0,0);
1084             var newH = this._setHeight(args.e);
1085             this.resize(args.e, newH, 0, 0, 0);
1086         },
1087         /** 
1088         * @private
1089         * @method _handle_for_t
1090         * @param {Object} args The arguments from the CustomEvent.
1091         * @description Handles the sizes for the Top handle.
1092         */
1093         _handle_for_t: function(args) {
1094             YAHOO.log('Handle T', 'info', 'Resize');
1095             this._dds.t.setXConstraint(0,0);
1096             var newH = this._setHeight(args.e, true);
1097             var t = (newH - this._cache.height);
1098             this.resize(args.e, newH, 0, t, 0);
1099         },
1100         /** 
1101         * @private
1102         * @method _setWidth
1103         * @param {Event} ev The mouse event.
1104         * @param {Boolean} flip Argument to determine the direction of the movement.
1105         * @description Calculates the width based on the mouse event.
1106         * @return {Number} The new value
1107         */
1108         _setWidth: function(ev, flip) {
1109             YAHOO.log('Set width based on Event', 'info', 'Resize');
1110             var xy = this._cache.xy[0],
1111                 w = this._cache.width,
1112                 x = Event.getPageX(ev),
1113                 nw = (x - xy);
1114
1115                 if (flip) {
1116                     nw = (xy - x) + parseInt(this.get('width'), 10);
1117                 }
1118                 
1119                 nw = this._snapTick(nw, this.get('xTicks'));
1120                 nw = this._checkWidth(nw);
1121             return nw;
1122         },
1123         /** 
1124         * @private
1125         * @method _checkWidth
1126         * @param {Number} w The width to check.
1127         * @description Checks the value passed against the maxWidth and minWidth.
1128         * @return {Number} the new value
1129         */
1130         _checkWidth: function(w) {
1131             YAHOO.log('Checking the min/max width', 'info', 'Resize');
1132             if (this.get('minWidth')) {
1133                 if (w <= this.get('minWidth')) {
1134                     YAHOO.log('Using minWidth', 'info', 'Resize');
1135                     w = this.get('minWidth');
1136                 }
1137             }
1138             if (this.get('maxWidth')) {
1139                 if (w >= this.get('maxWidth')) {
1140                     YAHOO.log('Using Max Width', 'info', 'Resize');
1141                     w = this.get('maxWidth');
1142                 }
1143             }
1144             return w;
1145         },
1146         /** 
1147         * @private
1148         * @method _checkHeight
1149         * @param {Number} h The height to check.
1150         * @description Checks the value passed against the maxHeight and minHeight.
1151         * @return {Number} The new value
1152         */
1153         _checkHeight: function(h) {
1154             YAHOO.log('Checking the min/max height', 'info', 'Resize');
1155             if (this.get('minHeight')) {
1156                 if (h <= this.get('minHeight')) {
1157                     YAHOO.log('Using minHeight', 'info', 'Resize');
1158                     h = this.get('minHeight');
1159                 }
1160             }
1161             if (this.get('maxHeight')) {
1162                 if (h >= this.get('maxHeight')) {
1163                     YAHOO.log('using maxHeight', 'info', 'Resize');
1164                     h = this.get('maxHeight');
1165                 }
1166             }
1167             return h;
1168         },
1169         /** 
1170         * @private
1171         * @method _setHeight
1172         * @param {Event} ev The mouse event.
1173         * @param {Boolean} flip Argument to determine the direction of the movement.
1174         * @description Calculated the height based on the mouse event.
1175         * @return {Number} The new value
1176         */
1177         _setHeight: function(ev, flip) {
1178             YAHOO.log('Setting the height based on the Event', 'info', 'Resize');
1179             var xy = this._cache.xy[1],
1180                 h = this._cache.height,
1181                 y = Event.getPageY(ev),
1182                 nh = (y - xy);
1183
1184                 if (flip) {
1185                     nh = (xy - y) + parseInt(this.get('height'), 10);
1186                 }
1187                 nh = this._snapTick(nh, this.get('yTicks'));
1188                 nh = this._checkHeight(nh);
1189                 
1190             return nh;
1191         },
1192         /** 
1193         * @private
1194         * @method _snapTick
1195         * @param {Number} size The size to tick against.
1196         * @param {Number} pix The tick pixels.
1197         * @description Adjusts the number based on the ticks used.
1198         * @return {Number} the new snapped position
1199         */
1200         _snapTick: function(size, pix) {
1201             YAHOO.log('Snapping to ticks', 'info', 'Resize');
1202             if (!size || !pix) {
1203                 return size;
1204             }
1205             var _s = size;
1206             var _x = size % pix;
1207             if (_x > 0) {
1208                 if (_x > (pix / 2)) {
1209                     _s = size + (pix - _x);
1210                 } else {
1211                     _s = size - _x;
1212                 }
1213             }
1214             return _s;
1215         },
1216         /** 
1217         * @private
1218         * @method init
1219         * @description The Resize class's initialization method
1220         */        
1221         init: function(p_oElement, p_oAttributes) {
1222             YAHOO.log('init', 'info', 'Resize');
1223             this._locked = false;
1224             this._cache = {
1225                 xy: [],
1226                 height: 0,
1227                 width: 0,
1228                 top: 0,
1229                 left: 0,
1230                 offsetHeight: 0,
1231                 offsetWidth: 0,
1232                 start: {
1233                     height: 0,
1234                     width: 0,
1235                     top: 0,
1236                     left: 0
1237                 }
1238             };
1239
1240             Resize.superclass.init.call(this, p_oElement, p_oAttributes);
1241
1242             this.set('setSize', this.get('setSize'));
1243
1244             if (p_oAttributes.height) {
1245                 this.set('height', parseInt(p_oAttributes.height, 10));
1246             } else {
1247                 var h = this.getStyle('height');
1248                 if (h == 'auto') {
1249                     this.set('height', parseInt(this.get('element').offsetHeight, 10));
1250                 }
1251             }
1252             if (p_oAttributes.width) {
1253                 this.set('width', parseInt(p_oAttributes.width, 10));
1254             } else {
1255                 var w = this.getStyle('width');
1256                 if (w == 'auto') {
1257                     this.set('width', parseInt(this.get('element').offsetWidth, 10));
1258                 }
1259             }
1260             
1261             var id = p_oElement;
1262             if (!Lang.isString(id)) {
1263                 id = D.generateId(id);
1264             }
1265             Resize._instances[id] = this;
1266
1267             this._active = false;
1268             
1269             this._createWrap();
1270             this._createProxy();
1271             this._createHandles();
1272
1273         },
1274         /**
1275         * @method getProxyEl
1276         * @description Get the HTML reference for the proxy, returns null if no proxy.
1277         * @return {HTMLElement} The proxy element
1278         */      
1279         getProxyEl: function() {
1280             return this._proxy;
1281         },
1282         /**
1283         * @method getWrapEl
1284         * @description Get the HTML reference for the wrap element, returns the current element if not wrapped.
1285         * @return {HTMLElement} The wrap element
1286         */      
1287         getWrapEl: function() {
1288             return this._wrap;
1289         },
1290         /**
1291         * @method getStatusEl
1292         * @description Get the HTML reference for the status element.
1293         * @return {HTMLElement} The status element
1294         */      
1295         getStatusEl: function() {
1296             return this._status;
1297         },
1298         /**
1299         * @method getActiveHandleEl
1300         * @description Get the HTML reference for the currently active resize handle.
1301         * @return {HTMLElement} The handle element that is active
1302         */      
1303         getActiveHandleEl: function() {
1304             return this._handles[this._currentHandle];
1305         },
1306         /**
1307         * @method isActive
1308         * @description Returns true or false if a resize operation is currently active on the element.
1309         * @return {Boolean}
1310         */      
1311         isActive: function() {
1312             return ((this._active) ? true : false);
1313         },
1314         /**
1315         * @private
1316         * @method initAttributes
1317         * @description Initializes all of the configuration attributes used to create a resizable element.
1318         * @param {Object} attr Object literal specifying a set of 
1319         * configuration attributes used to create the utility.
1320         */      
1321         initAttributes: function(attr) {
1322             Resize.superclass.initAttributes.call(this, attr);
1323
1324             /**
1325             * @attribute useShim
1326             * @description This setting will be passed to the DragDrop instances on the resize handles and for the draggable property.
1327             * This property should be used if you want the resize handles to work over iframe and other elements.
1328             * @type Boolean
1329             */
1330             this.setAttributeConfig('useShim', {
1331                 value: ((attr.useShim === true) ? true : false),
1332                 validator: YAHOO.lang.isBoolean,
1333                 method: function(u) {
1334                     for (var i in this._dds) {
1335                         if (Lang.hasOwnProperty(this._dds, i)) {
1336                             this._dds[i].useShim = u;
1337                         }
1338                     }
1339                     if (this.dd) {
1340                         this.dd.useShim = u;
1341                     }
1342                 }
1343             });
1344             /**
1345             * @attribute setSize
1346             * @description Set the size of the resized element, if set to false the element will not be auto resized,
1347             * the resize event will contain the dimensions so the end user can resize it on their own.
1348             * This setting will only work with proxy set to true and animate set to false.
1349             * @type Boolean
1350             */
1351             this.setAttributeConfig('setSize', {
1352                 value: ((attr.setSize === false) ? false : true),
1353                 validator: YAHOO.lang.isBoolean
1354             });
1355
1356             /**
1357             * @attribute wrap
1358             * @description Should we wrap the element
1359             * @type Boolean
1360             */
1361             this.setAttributeConfig('wrap', {
1362                 writeOnce: true,
1363                 validator: YAHOO.lang.isBoolean,
1364                 value: attr.wrap || false
1365             });
1366
1367             /**
1368             * @attribute handles
1369             * @description The handles to use (any combination of): 't', 'b', 'r', 'l', 'bl', 'br', 'tl', 'tr'. Defaults to: ['r', 'b', 'br'].
1370             * Can use a shortcut of All. Note: 8 way resizing should be done on an element that is absolutely positioned.
1371             * @type Array
1372             */
1373             this.setAttributeConfig('handles', {
1374                 writeOnce: true,
1375                 value: attr.handles || ['r', 'b', 'br'],
1376                 validator: function(handles) {
1377                     if (Lang.isString(handles) && handles.toLowerCase() == 'all') {
1378                         handles = ['t', 'b', 'r', 'l', 'bl', 'br', 'tl', 'tr'];
1379                     }
1380                     if (!Lang.isArray(handles)) {
1381                         handles = handles.replace(/, /g, ',');
1382                         handles = handles.split(',');
1383                     }
1384                     this._configs.handles.value = handles;
1385                 }
1386             });
1387
1388             /**
1389             * @attribute width
1390             * @description The width of the element
1391             * @type Number
1392             */
1393             this.setAttributeConfig('width', {
1394                 value: attr.width || parseInt(this.getStyle('width'), 10),
1395                 validator: YAHOO.lang.isNumber,
1396                 method: function(width) {
1397                     width = parseInt(width, 10);
1398                     if (width > 0) {
1399                         if (this.get('setSize')) {
1400                             this.setStyle('width', width + 'px');
1401                         }
1402                         this._cache.width = width;
1403                         this._configs.width.value = width;
1404                     }
1405                 }
1406             });
1407
1408             /**
1409             * @attribute height
1410             * @description The height of the element
1411             * @type Number
1412             */
1413             this.setAttributeConfig('height', {
1414                 value: attr.height || parseInt(this.getStyle('height'), 10),
1415                 validator: YAHOO.lang.isNumber,
1416                 method: function(height) {
1417                     height = parseInt(height, 10);
1418                     if (height > 0) {
1419                         if (this.get('setSize')) {
1420                             this.setStyle('height', height + 'px');
1421                         }
1422                         this._cache.height = height;
1423                         this._configs.height.value = height;
1424                     }
1425                 }
1426             });
1427
1428             /**
1429             * @attribute minWidth
1430             * @description The minimum width of the element
1431             * @type Number
1432             */
1433             this.setAttributeConfig('minWidth', {
1434                 value: attr.minWidth || 15,
1435                 validator: YAHOO.lang.isNumber
1436             });
1437
1438             /**
1439             * @attribute minHeight
1440             * @description The minimum height of the element
1441             * @type Number
1442             */
1443             this.setAttributeConfig('minHeight', {
1444                 value: attr.minHeight || 15,
1445                 validator: YAHOO.lang.isNumber
1446             });
1447
1448             /**
1449             * @attribute maxWidth
1450             * @description The maximum width of the element
1451             * @type Number
1452             */
1453             this.setAttributeConfig('maxWidth', {
1454                 value: attr.maxWidth || 10000,
1455                 validator: YAHOO.lang.isNumber
1456             });
1457
1458             /**
1459             * @attribute maxHeight
1460             * @description The maximum height of the element
1461             * @type Number
1462             */
1463             this.setAttributeConfig('maxHeight', {
1464                 value: attr.maxHeight || 10000,
1465                 validator: YAHOO.lang.isNumber
1466             });
1467
1468             /**
1469             * @attribute minY
1470             * @description The minimum y coord of the element
1471             * @type Number
1472             */
1473             this.setAttributeConfig('minY', {
1474                 value: attr.minY || false
1475             });
1476
1477             /**
1478             * @attribute minX
1479             * @description The minimum x coord of the element
1480             * @type Number
1481             */
1482             this.setAttributeConfig('minX', {
1483                 value: attr.minX || false
1484             });
1485             /**
1486             * @attribute maxY
1487             * @description The max y coord of the element
1488             * @type Number
1489             */
1490             this.setAttributeConfig('maxY', {
1491                 value: attr.maxY || false
1492             });
1493
1494             /**
1495             * @attribute maxX
1496             * @description The max x coord of the element
1497             * @type Number
1498             */
1499             this.setAttributeConfig('maxX', {
1500                 value: attr.maxX || false
1501             });
1502
1503             /**
1504             * @attribute animate
1505             * @description Should be use animation to resize the element (can only be used if we use proxy).
1506             * @type Boolean
1507             */
1508             this.setAttributeConfig('animate', {
1509                 value: attr.animate || false,
1510                 validator: function(value) {
1511                     var ret = true;
1512                     if (!YAHOO.util.Anim) {
1513                         ret = false;
1514                     }
1515                     return ret;
1516                 }               
1517             });
1518
1519             /**
1520             * @attribute animateEasing
1521             * @description The Easing to apply to the animation.
1522             * @type Object
1523             */
1524             this.setAttributeConfig('animateEasing', {
1525                 value: attr.animateEasing || function() {
1526                     var easing = false;
1527                     if (YAHOO.util.Easing && YAHOO.util.Easing.easeOut) {
1528                         easing = YAHOO.util.Easing.easeOut;
1529                     }
1530                     return easing;
1531                 }()
1532             });
1533
1534             /**
1535             * @attribute animateDuration
1536             * @description The Duration to apply to the animation.
1537             * @type Number
1538             */
1539             this.setAttributeConfig('animateDuration', {
1540                 value: attr.animateDuration || 0.5
1541             });
1542
1543             /**
1544             * @attribute proxy
1545             * @description Resize a proxy element instead of the real element.
1546             * @type Boolean
1547             */
1548             this.setAttributeConfig('proxy', {
1549                 value: attr.proxy || false,
1550                 validator: YAHOO.lang.isBoolean
1551             });
1552
1553             /**
1554             * @attribute ratio
1555             * @description Maintain the element's ratio when resizing.
1556             * @type Boolean
1557             */
1558             this.setAttributeConfig('ratio', {
1559                 value: attr.ratio || false,
1560                 validator: YAHOO.lang.isBoolean
1561             });
1562
1563             /**
1564             * @attribute ghost
1565             * @description Apply an opacity filter to the element being resized (only works with proxy).
1566             * @type Boolean
1567             */
1568             this.setAttributeConfig('ghost', {
1569                 value: attr.ghost || false,
1570                 validator: YAHOO.lang.isBoolean
1571             });
1572
1573             /**
1574             * @attribute draggable
1575             * @description A convienence method to make the element draggable
1576             * @type Boolean
1577             */
1578             this.setAttributeConfig('draggable', {
1579                 value: attr.draggable || false,
1580                 validator: YAHOO.lang.isBoolean,
1581                 method: function(dd) {
1582                     if (dd && this._wrap) {
1583                         this._setupDragDrop();
1584                     } else {
1585                         if (this.dd) {
1586                             D.removeClass(this._wrap, this.CSS_DRAG);
1587                             this.dd.unreg();
1588                         }
1589                     }
1590                 }
1591             });
1592
1593             /**
1594             * @attribute hover
1595             * @description Only show the handles when they are being moused over.
1596             * @type Boolean
1597             */
1598             this.setAttributeConfig('hover', {
1599                 value: attr.hover || false,
1600                 validator: YAHOO.lang.isBoolean
1601             });
1602
1603             /**
1604             * @attribute hiddenHandles
1605             * @description Don't show the handles, just use the cursor to the user.
1606             * @type Boolean
1607             */
1608             this.setAttributeConfig('hiddenHandles', {
1609                 value: attr.hiddenHandles || false,
1610                 validator: YAHOO.lang.isBoolean
1611             });
1612
1613             /**
1614             * @attribute knobHandles
1615             * @description Use the smaller handles, instead if the full size handles.
1616             * @type Boolean
1617             */
1618             this.setAttributeConfig('knobHandles', {
1619                 value: attr.knobHandles || false,
1620                 validator: YAHOO.lang.isBoolean
1621             });
1622
1623             /**
1624             * @attribute xTicks
1625             * @description The number of x ticks to span the resize to.
1626             * @type Number or False
1627             */
1628             this.setAttributeConfig('xTicks', {
1629                 value: attr.xTicks || false
1630             });
1631
1632             /**
1633             * @attribute yTicks
1634             * @description The number of y ticks to span the resize to.
1635             * @type Number or False
1636             */
1637             this.setAttributeConfig('yTicks', {
1638                 value: attr.yTicks || false
1639             });
1640
1641             /**
1642             * @attribute status
1643             * @description Show the status (new size) of the resize.
1644             * @type Boolean
1645             */
1646             this.setAttributeConfig('status', {
1647                 value: attr.status || false,
1648                 validator: YAHOO.lang.isBoolean
1649             });
1650
1651             /**
1652             * @attribute autoRatio
1653             * @description Using the shift key during a resize will toggle the ratio config.
1654             * @type Boolean
1655             */
1656             this.setAttributeConfig('autoRatio', {
1657                 value: attr.autoRatio || false,
1658                 validator: YAHOO.lang.isBoolean
1659             });
1660
1661         },
1662         /**
1663         * @method destroy
1664         * @description Destroys the resize object and all of it's elements & listeners.
1665         */        
1666         destroy: function() {
1667             YAHOO.log('Destroying Resize', 'info', 'Resize');
1668             for (var h in this._handles) {
1669                 if (Lang.hasOwnProperty(this._handles, h)) {
1670                     Event.purgeElement(this._handles[h]);
1671                     this._handles[h].parentNode.removeChild(this._handles[h]);
1672                 }
1673             }
1674             if (this._proxy) {
1675                 this._proxy.parentNode.removeChild(this._proxy);
1676             }
1677             if (this._status) {
1678                 this._status.parentNode.removeChild(this._status);
1679             }
1680             if (this.dd) {
1681                 this.dd.unreg();
1682                 D.removeClass(this._wrap, this.CSS_DRAG);
1683             }
1684             if (this._wrap != this.get('element')) {
1685                 this.setStyle('position', '');
1686                 this.setStyle('top', '');
1687                 this.setStyle('left', '');
1688                 this._wrap.parentNode.replaceChild(this.get('element'), this._wrap);
1689             }
1690             this.removeClass(this.CSS_RESIZE);
1691
1692             delete YAHOO.util.Resize._instances[this.get('id')];
1693             //Brutal Object Destroy
1694             for (var i in this) {
1695                 if (Lang.hasOwnProperty(this, i)) {
1696                     this[i] = null;
1697                     delete this[i];
1698                 }
1699             }
1700         },
1701         /**
1702         * @method toString
1703         * @description Returns a string representing the Resize Object.
1704         * @return {String}
1705         */        
1706         toString: function() {
1707             if (this.get) {
1708                 return 'Resize (#' + this.get('id') + ')';
1709             }
1710             return 'Resize Utility';
1711         }
1712     });
1713
1714     YAHOO.util.Resize = Resize;
1715  
1716 /**
1717 * @event dragEvent
1718 * @description Fires when the <a href="YAHOO.util.DragDrop.html">YAHOO.util.DragDrop</a> dragEvent is fired for the config option draggable.
1719 * @type YAHOO.util.CustomEvent
1720 */
1721 /**
1722 * @event startResize
1723 * @description Fires when a resize action is started.
1724 * @type YAHOO.util.CustomEvent
1725 */
1726 /**
1727 * @event endResize
1728 * @description Fires when the mouseUp event from the Drag Instance fires.
1729 * @type YAHOO.util.CustomEvent
1730 */
1731 /**
1732 * @event resize
1733 * @description Fires on every element resize (only fires once when used with proxy config setting).
1734 * @type YAHOO.util.CustomEvent
1735 */
1736 /**
1737 * @event beforeResize
1738 * @description Fires before every element resize after the size calculations, returning false will stop the resize.
1739 * @type YAHOO.util.CustomEvent
1740 */
1741 /**
1742 * @event proxyResize
1743 * @description Fires on every proxy resize (only fires when used with proxy config setting).
1744 * @type YAHOO.util.CustomEvent
1745 */
1746
1747 })();
1748
1749 YAHOO.register("resize", YAHOO.util.Resize, {version: "2.8.0r4", build: "2449"});