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