]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blob - wradmin_/wradmin/public/yui/layout/layout-debug.js
Intermediate rename to restructure package.
[philipp/winterrodeln/wradmin.git] / wradmin_ / wradmin / public / yui / layout / layout-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.7.0
6 */
7 /**
8  * @description <p>Provides a fixed layout containing, top, bottom, left, right and center layout units. It can be applied to either the body or an element.</p>
9  * @namespace YAHOO.widget
10  * @requires yahoo, dom, element, event
11  * @module layout
12  */
13 (function() {
14     var Dom = YAHOO.util.Dom,
15         Event = YAHOO.util.Event,
16         Lang = YAHOO.lang;
17
18     /**
19      * @constructor
20      * @class Layout
21      * @extends YAHOO.util.Element
22      * @description <p>Provides a fixed layout containing, top, bottom, left, right and center layout units. It can be applied to either the body or an element.</p>
23      * @param {String/HTMLElement} el The element to make contain a layout.
24      * @param {Object} attrs Object liternal containing configuration parameters.
25     */
26
27     var Layout = function(el, config) {
28         YAHOO.log('Creating the Layout Object', 'info', 'Layout');
29         if (Lang.isObject(el) && !el.tagName) {
30             config = el;
31             el = null;
32         }
33         if (Lang.isString(el)) {
34             if (Dom.get(el)) {
35                 el = Dom.get(el);
36             }
37         }
38         if (!el) {
39             el = document.body;
40         }
41
42         var oConfig = {
43             element: el,
44             attributes: config || {}
45         };
46
47         Layout.superclass.constructor.call(this, oConfig.element, oConfig.attributes);    
48     };
49
50     /**
51     * @private
52     * @static
53     * @property _instances
54     * @description Internal hash table for all layout instances
55     * @type Object
56     */ 
57     Layout._instances = {};
58     /**
59     * @static
60     * @method getLayoutById 
61     * @description Get's a layout object by the HTML id of the element associated with the Layout object.
62     * @return {Object} The Layout Object
63     */ 
64     Layout.getLayoutById = function(id) {
65         if (Layout._instances[id]) {
66             return Layout._instances[id];
67         }
68         return false;
69     };
70
71     YAHOO.extend(Layout, YAHOO.util.Element, {
72         /**
73         * @property browser
74         * @description A modified version of the YAHOO.env.ua object
75         * @type Object
76         */
77         browser: function() {
78             var b = YAHOO.env.ua;
79             b.standardsMode = false;
80             b.secure = false;
81             return b;
82         }(),
83         /**
84         * @private
85         * @property _units
86         * @description An object literal that contains a list of units in the layout
87         * @type Object
88         */
89         _units: null,
90         /**
91         * @private
92         * @property _rendered
93         * @description Set to true when the layout is rendered
94         * @type Boolean
95         */
96         _rendered: null,
97         /**
98         * @private
99         * @property _zIndex
100         * @description The zIndex to set all LayoutUnits to
101         * @type Number
102         */
103         _zIndex: null,
104         /**
105         * @private
106         * @property _sizes
107         * @description A collection of the current sizes of all usable LayoutUnits to be used for calculations
108         * @type Object
109         */
110         _sizes: null,
111         /**
112         * @private
113         * @method _setBodySize
114         * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
115         * @description Used to set the body size of the layout, sets the height and width of the parent container
116         */
117         _setBodySize: function(set) {
118             var h = 0, w = 0;
119             set = ((set === false) ? false : true);
120
121             if (this._isBody) {
122                 h = Dom.getClientHeight();
123                 w = Dom.getClientWidth();
124             } else {
125                 h = parseInt(this.getStyle('height'), 10);
126                 w = parseInt(this.getStyle('width'), 10);
127                 if (isNaN(w)) {
128                     w = this.get('element').clientWidth;
129                 }
130                 if (isNaN(h)) {
131                     h = this.get('element').clientHeight;
132                 }
133             }
134             if (this.get('minWidth')) {
135                 if (w < this.get('minWidth')) {
136                     w = this.get('minWidth');
137                 }
138             }
139             if (this.get('minHeight')) {
140                 if (h < this.get('minHeight')) {
141                     h = this.get('minHeight');
142                 }
143             }
144             if (set) {
145                 Dom.setStyle(this._doc, 'height', h + 'px');
146                 Dom.setStyle(this._doc, 'width', w + 'px');
147             }
148             this._sizes.doc = { h: h, w: w };
149             YAHOO.log('Setting Body height and width: (' + h + ',' + w + ')', 'info', 'Layout');
150             this._setSides(set);
151         },
152         /**
153         * @private
154         * @method _setSides
155         * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
156         * @description Used to set the size and position of the left, right, top and bottom units
157         */
158         _setSides: function(set) {
159             YAHOO.log('Setting side units', 'info', 'Layout');
160             var h1 = ((this._units.top) ? this._units.top.get('height') : 0),
161                 h2 = ((this._units.bottom) ? this._units.bottom.get('height') : 0),
162                 h = this._sizes.doc.h,
163                 w = this._sizes.doc.w;
164             set = ((set === false) ? false : true);
165
166             this._sizes.top = {
167                 h: h1, w: ((this._units.top) ? w : 0),
168                 t: 0
169             };
170             this._sizes.bottom = {
171                 h: h2, w: ((this._units.bottom) ? w : 0)
172             };
173             
174             var newH = (h - (h1 + h2));
175
176             this._sizes.left = {
177                 h: newH, w: ((this._units.left) ? this._units.left.get('width') : 0)
178             };
179             this._sizes.right = {
180                 h: newH, w: ((this._units.right) ? this._units.right.get('width') : 0),
181                 l: ((this._units.right) ? (w - this._units.right.get('width')) : 0),
182                 t: ((this._units.top) ? this._sizes.top.h : 0)
183             };
184             
185             if (this._units.right && set) {
186                 this._units.right.set('top', this._sizes.right.t);
187                 if (!this._units.right._collapsing) { 
188                     this._units.right.set('left', this._sizes.right.l);
189                 }
190                 this._units.right.set('height', this._sizes.right.h, true);
191             }
192             if (this._units.left) {
193                 this._sizes.left.l = 0;
194                 if (this._units.top) {
195                     this._sizes.left.t = this._sizes.top.h;
196                 } else {
197                     this._sizes.left.t = 0;
198                 }
199                 if (set) {
200                     this._units.left.set('top', this._sizes.left.t);
201                     this._units.left.set('height', this._sizes.left.h, true);
202                     this._units.left.set('left', 0);
203                 }
204             }
205             if (this._units.bottom) {
206                 this._sizes.bottom.t = this._sizes.top.h + this._sizes.left.h;
207                 if (set) {
208                     this._units.bottom.set('top', this._sizes.bottom.t);
209                     this._units.bottom.set('width', this._sizes.bottom.w, true);
210                 }
211             }
212             if (this._units.top) {
213                 if (set) {
214                     this._units.top.set('width', this._sizes.top.w, true);
215                 }
216             }
217             YAHOO.log('Setting sizes: (' + Lang.dump(this._sizes) + ')', 'info', 'Layout');
218             this._setCenter(set);
219         },
220         /**
221         * @private
222         * @method _setCenter
223         * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
224         * @description Used to set the size and position of the center unit
225         */
226         _setCenter: function(set) {
227             set = ((set === false) ? false : true);
228             var h = this._sizes.left.h;
229             var w = (this._sizes.doc.w - (this._sizes.left.w + this._sizes.right.w));
230             if (set) {
231                 this._units.center.set('height', h, true);
232                 this._units.center.set('width', w, true);
233                 this._units.center.set('top', this._sizes.top.h);
234                 this._units.center.set('left', this._sizes.left.w);
235             }
236             this._sizes.center = { h: h, w: w, t: this._sizes.top.h, l: this._sizes.left.w };
237             YAHOO.log('Setting Center size to: (' + h + ', ' + w + ')', 'info', 'Layout');
238         },
239         /**
240         * @method getSizes
241         * @description Get a reference to the internal Layout Unit sizes object used to build the layout wireframe
242         * @return {Object} An object of the layout unit sizes
243         */
244         getSizes: function() {
245             return this._sizes;
246         },
247         /**
248         * @method getUnitById
249         * @param {String} id The HTML element id of the unit
250         * @description Get the LayoutUnit by it's HTML id
251         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
252         */
253         getUnitById: function(id) {
254             return YAHOO.widget.LayoutUnit.getLayoutUnitById(id);
255         },
256         /**
257         * @method getUnitByPosition
258         * @param {String} pos The position of the unit in this layout
259         * @description Get the LayoutUnit by it's position in this layout
260         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
261         */
262         getUnitByPosition: function(pos) {
263             if (pos) {
264                 pos = pos.toLowerCase();
265                 if (this._units[pos]) {
266                     return this._units[pos];
267                 }
268                 return false;
269             }
270             return false;
271         },
272         /**
273         * @method removeUnit
274         * @param {Object} unit The LayoutUnit that you want to remove
275         * @description Remove the unit from this layout and resize the layout.
276         */
277         removeUnit: function(unit) {
278             delete this._units[unit.get('position')];
279             this.resize();
280         },
281         /**
282         * @method addUnit
283         * @param {Object} cfg The config for the LayoutUnit that you want to add
284         * @description Add a unit to this layout and if the layout is rendered, resize the layout. 
285         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
286         */
287         addUnit: function(cfg) {
288             if (!cfg.position) {
289                 YAHOO.log('No position property passed', 'error', 'Layout');
290                 return false;
291             }
292             if (this._units[cfg.position]) {
293                 YAHOO.log('Position already exists', 'error', 'Layout');
294                 return false;
295             }
296             YAHOO.log('Adding Unit at position: ' + cfg.position, 'info', 'Layout');
297             var element = null,
298                 el = null;
299
300             if (cfg.id) {
301                 if (Dom.get(cfg.id)) {
302                     element = Dom.get(cfg.id);
303                     delete cfg.id;
304
305                 }
306             }
307             if (cfg.element) {
308                 element = cfg.element;
309             }
310
311             if (!el) {
312                 el = document.createElement('div');
313                 var id = Dom.generateId();
314                 el.id = id;
315             }
316
317             if (!element) {
318                 element = document.createElement('div');
319             }
320             Dom.addClass(element, 'yui-layout-wrap');
321             if (this.browser.ie && !this.browser.standardsMode) {
322                 el.style.zoom = 1;
323                 element.style.zoom = 1;
324             }
325
326             if (el.firstChild) {
327                 el.insertBefore(element, el.firstChild);
328             } else {
329                 el.appendChild(element);
330             }
331             this._doc.appendChild(el);
332
333             var h = false, w = false;
334
335             if (cfg.height) {
336                 h = parseInt(cfg.height, 10);
337             }
338             if (cfg.width) {
339                 w = parseInt(cfg.width, 10);
340             }
341             var unitConfig = {};
342             YAHOO.lang.augmentObject(unitConfig, cfg); // break obj ref
343
344             unitConfig.parent = this;
345             unitConfig.wrap = element;
346             unitConfig.height = h;
347             unitConfig.width = w;
348
349             var unit = new YAHOO.widget.LayoutUnit(el, unitConfig);
350
351             unit.on('heightChange', this.resize, this, true);
352             unit.on('widthChange', this.resize, this, true);
353             unit.on('gutterChange', this.resize, this, true);
354             this._units[cfg.position] = unit;
355
356             if (this._rendered) {
357                 this.resize();
358             }
359
360             return unit;
361         },
362         /**
363         * @private
364         * @method _createUnits
365         * @description Private method to create units from the config that was passed in.
366         */
367         _createUnits: function() {
368             var units = this.get('units');
369             for (var i in units) {
370                 if (Lang.hasOwnProperty(units, i)) {
371                     this.addUnit(units[i]);
372                 }
373             }
374         },
375         /**
376         * @method resize
377         * @param {Boolean} set If set to false, it will NOT set the size, just perform the calculations (used for collapsing units)
378         * @description Starts the chain of resize routines that will resize all the units.
379         * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The Layout instance
380         */
381         resize: function(set) {
382             set = ((set === false) ? false : true);
383             if (set) {
384                 var retVal = this.fireEvent('beforeResize');
385                 if (retVal === false) {
386                     set = false;
387                 }
388                 if (this.browser.ie) {
389                     if (this._isBody) {
390                         Dom.removeClass(document.documentElement, 'yui-layout');
391                         Dom.addClass(document.documentElement, 'yui-layout');
392                     } else {
393                         this.removeClass('yui-layout');
394                         this.addClass('yui-layout');
395                     }
396                 }
397             }
398             this._setBodySize(set);
399             if (set) {
400                 this.fireEvent('resize', { target: this, sizes: this._sizes });
401             }
402             return this;
403         },
404         /**
405         * @private
406         * @method _setupBodyElements
407         * @description Sets up the main doc element when using the body as the main element.
408         */
409         _setupBodyElements: function() {
410             this._doc = Dom.get('layout-doc');
411             if (!this._doc) {
412                 this._doc = document.createElement('div');
413                 this._doc.id = 'layout-doc';
414                 if (document.body.firstChild) {
415                     document.body.insertBefore(this._doc, document.body.firstChild);
416                 } else {
417                     document.body.appendChild(this._doc);
418                 }
419             }
420             this._createUnits();
421             this._setBodySize();
422             Event.on(window, 'resize', this.resize, this, true);
423             Dom.addClass(this._doc, 'yui-layout-doc');
424         },
425         /**
426         * @private
427         * @method _setupElements
428         * @description Sets up the main doc element when not using the body as the main element.
429         */
430         _setupElements: function() {
431             this._doc = this.getElementsByClassName('yui-layout-doc')[0];
432             if (!this._doc) {
433                 this._doc = document.createElement('div');
434                 this.get('element').appendChild(this._doc);
435             }
436             this._createUnits();
437             this._setBodySize();
438             Dom.addClass(this._doc, 'yui-layout-doc');
439         },
440         /**
441         * @private
442         * @property _isBody
443         * @description Flag to determine if we are using the body as the root element.
444         * @type Boolean
445         */
446         _isBody: null,
447         /**
448         * @private
449         * @property _doc
450         * @description Reference to the root element
451         * @type HTMLElement
452         */
453         _doc: null,
454         /**
455         * @private
456         * @method init
457         * @description The Layout class' initialization method
458         */        
459         init: function(p_oElement, p_oAttributes) {
460             YAHOO.log('init', 'info', 'Layout');
461
462             this._zIndex = 0;
463
464             Layout.superclass.init.call(this, p_oElement, p_oAttributes);
465             
466             if (this.get('parent')) {
467                 this._zIndex = this.get('parent')._zIndex + 10;
468             }
469
470             this._sizes = {};
471             this._units = {};
472
473             var id = p_oElement;
474             if (!Lang.isString(id)) {
475                 id = Dom.generateId(id);
476             }
477             Layout._instances[id] = this;
478         },
479         /**
480         * @method render
481         * @description This method starts the render process, applying classnames and creating elements
482         * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The Layout instance
483         */        
484         render: function() {
485             YAHOO.log('Render', 'info', 'Layout');
486             this._stamp();
487             var el = this.get('element');
488             if (el && el.tagName && (el.tagName.toLowerCase() == 'body')) {
489                 this._isBody = true;
490                 Dom.addClass(document.body, 'yui-layout');
491                 if (Dom.hasClass(document.body, 'yui-skin-sam')) {
492                     //Move the class up so we can have a css chain
493                     Dom.addClass(document.documentElement, 'yui-skin-sam');
494                     Dom.removeClass(document.body, 'yui-skin-sam');
495                 }
496                 this._setupBodyElements();
497             } else {
498                 this._isBody = false;
499                 this.addClass('yui-layout');
500                 this._setupElements();
501             }
502             this.resize();
503             this._rendered = true;
504             this.fireEvent('render');
505
506             return this;
507         },
508         /**
509         * @private
510         * @method _stamp
511         * @description Stamps the root node with a secure classname for ease of use. Also sets the this.browser.standardsMode variable.
512         */        
513         _stamp: function() {
514             if (document.compatMode == 'CSS1Compat') {
515                 this.browser.standardsMode = true;
516             }
517             if (window.location.href.toLowerCase().indexOf("https") === 0) {
518                 Dom.addClass(document.documentElement, 'secure');
519                 this.browser.secure = true;
520             }
521         },
522         /**
523         * @private
524         * @method initAttributes
525         * @description Processes the config
526         */        
527         initAttributes: function(attr) {
528             Layout.superclass.initAttributes.call(this, attr);
529             /**
530             * @attribute units
531             * @description An array of config definitions for the LayoutUnits to add to this layout
532             * @type Array
533             */
534             this.setAttributeConfig('units', {
535                 writeOnce: true,
536                 validator: YAHOO.lang.isArray,
537                 value: attr.units || []
538             });
539
540             /**
541             * @attribute minHeight
542             * @description The minimum height in pixels
543             * @type Number
544             */
545             this.setAttributeConfig('minHeight', {
546                 value: attr.minHeight || false,
547                 validator: YAHOO.lang.isNumber
548             });
549
550             /**
551             * @attribute minWidth
552             * @description The minimum width in pixels
553             * @type Number
554             */
555             this.setAttributeConfig('minWidth', {
556                 value: attr.minWidth || false,
557                 validator: YAHOO.lang.isNumber
558             });
559
560             /**
561             * @attribute height
562             * @description The height in pixels
563             * @type Number
564             */
565             this.setAttributeConfig('height', {
566                 value: attr.height || false,
567                 validator: YAHOO.lang.isNumber,
568                 method: function(h) {
569                     this.setStyle('height', h + 'px');
570                 }
571             });
572
573             /**
574             * @attribute width
575             * @description The width in pixels
576             * @type Number
577             */
578             this.setAttributeConfig('width', {
579                 value: attr.width || false,
580                 validator: YAHOO.lang.isNumber,
581                 method: function(w) {
582                     this.setStyle('width', w + 'px');
583                 }
584             });
585
586             /**
587             * @attribute parent
588             * @description If this layout is to be used as a child of another Layout instance, this config will bind the resize events together.
589             * @type Object YAHOO.widget.Layout
590             */
591             this.setAttributeConfig('parent', {
592                 writeOnce: true,
593                 value: attr.parent || false,
594                 method: function(p) {
595                     if (p) {
596                         p.on('resize', this.resize, this, true);
597                     }
598                 }
599             });
600         },
601         /**
602         * @method destroy
603         * @description Removes this layout from the page and destroys all units that it contains. This will destroy all data inside the layout and it's children.
604         */
605         destroy: function() {
606             var par = this.get('parent');
607             if (par) {
608                 par.removeListener('resize', this.resize, this, true);
609             }
610             Event.removeListener(window, 'resize', this.resize, this, true);
611
612             this.unsubscribeAll();
613             for (var u in this._units) {
614                 if (Lang.hasOwnProperty(this._units, u)) {
615                     if (this._units[u]) {
616                         this._units[u].destroy(true);
617                     }
618                 }
619             }
620
621             Event.purgeElement(this.get('element'));
622             this.get('parentNode').removeChild(this.get('element'));
623             
624             delete YAHOO.widget.Layout._instances[this.get('id')];
625             //Brutal Object Destroy
626             for (var i in this) {
627                 if (Lang.hasOwnProperty(this, i)) {
628                     this[i] = null;
629                     delete this[i];
630                 }
631             }
632             
633             if (par) {
634                 par.resize();
635             }
636         },
637         /**
638         * @method toString
639         * @description Returns a string representing the Layout.
640         * @return {String}
641         */        
642         toString: function() {
643             if (this.get) {
644                 return 'Layout #' + this.get('id');
645             }
646             return 'Layout';
647         }
648     });
649     /**
650     * @event resize
651     * @description Fired when this.resize is called
652     * @type YAHOO.util.CustomEvent
653     */
654     /**
655     * @event startResize
656     * @description Fired when the Resize Utility for a Unit fires it's startResize Event.
657     * @type YAHOO.util.CustomEvent
658     */
659     /**
660     * @event beforeResize
661     * @description Fires at the beginning of the resize method. If you return false, the resize is cancelled.
662     * @type YAHOO.util.CustomEvent
663     */
664     /**
665     * @event render
666     * @description Fired after the render method completes.
667     * @type YAHOO.util.CustomEvent
668     */
669
670     YAHOO.widget.Layout = Layout;
671 })();
672 /**
673  * @description <p>Provides a fixed position unit containing a header, body and footer for use with a YAHOO.widget.Layout instance.</p>
674  * @namespace YAHOO.widget
675  * @requires yahoo, dom, element, event, layout
676  * @optional animation, dragdrop, selector
677  */
678 (function() {
679     var Dom = YAHOO.util.Dom,
680         Sel = YAHOO.util.Selector,
681         Event = YAHOO.util.Event,
682         Lang = YAHOO.lang;
683
684     /**
685      * @constructor
686      * @class LayoutUnit
687      * @extends YAHOO.util.Element
688      * @description <p>Provides a fixed position unit containing a header, body and footer for use with a YAHOO.widget.Layout instance.</p>
689      * @param {String/HTMLElement} el The element to make a unit.
690      * @param {Object} attrs Object liternal containing configuration parameters.
691     */
692
693     var LayoutUnit = function(el, config) {
694         
695         var oConfig = {
696             element: el,
697             attributes: config || {}
698         };
699
700         LayoutUnit.superclass.constructor.call(this, oConfig.element, oConfig.attributes);    
701     };
702
703     /**
704     * @private
705     * @static
706     * @property _instances
707     * @description Internal hash table for all layout unit instances
708     * @type Object
709     */ 
710     LayoutUnit._instances = {};
711     /**
712     * @static
713     * @method getLayoutUnitById 
714     * @description Get's a layout unit object by the HTML id of the element associated with the Layout Unit object.
715     * @return {Object} The Layout Object
716     */ 
717     LayoutUnit.getLayoutUnitById = function(id) {
718         if (LayoutUnit._instances[id]) {
719             return LayoutUnit._instances[id];
720         }
721         return false;
722     };
723
724     YAHOO.extend(LayoutUnit, YAHOO.util.Element, {
725         /**
726         * @property STR_CLOSE
727         * @description String used for close button title
728         * @type {String}
729         */
730         STR_CLOSE: 'Click to close this pane.',
731         /**
732         * @property STR_COLLAPSE
733         * @description String used for collapse button title
734         * @type {String}
735         */
736         STR_COLLAPSE: 'Click to collapse this pane.',
737         /**
738         * @property STR_EXPAND
739         * @description String used for expand button title
740         * @type {String}
741         */
742         STR_EXPAND: 'Click to expand this pane.',
743         /**
744             * The class name applied to dynamic tabs while loading.
745             * @property LOADING_CLASSNAME
746             * @type String
747             * @default "disabled"
748             */
749             LOADING_CLASSNAME: 'loading',
750         /**
751         * @property browser
752         * @description A modified version of the YAHOO.env.ua object
753         * @type Object
754         */
755         browser: null,
756         /**
757         * @private
758         * @property _sizes
759         * @description A collection of the current sizes of the contents of this Layout Unit
760         * @type Object
761         */
762         _sizes: null,
763         /**
764         * @private
765         * @property _anim
766         * @description A reference to the Animation instance used by this LayouUnit
767         * @type YAHOO.util.Anim
768         */
769         _anim: null,
770         /**
771         * @private
772         * @property _resize
773         * @description A reference to the Resize instance used by this LayoutUnit
774         * @type YAHOO.util.Resize
775         */
776         _resize: null,
777         /**
778         * @private
779         * @property _clip
780         * @description A reference to the clip element used when collapsing the unit
781         * @type HTMLElement
782         */
783         _clip: null,
784         /**
785         * @private
786         * @property _gutter
787         * @description A simple hash table used to store the gutter to apply to the Unit
788         * @type Object
789         */
790         _gutter: null,
791         /**
792         * @property header
793         * @description A reference to the HTML element used for the Header
794         * @type HTMLELement
795         */
796         header: null,
797         /**
798         * @property body
799         * @description A reference to the HTML element used for the body
800         * @type HTMLElement
801         */
802         body: null,
803         /**
804         * @property footer
805         * @description A reference to the HTML element used for the footer
806         * @type HTMLElement
807         */
808         footer: null,
809         /**
810         * @private
811         * @property _collapsed
812         * @description Flag to determine if the unit is collapsed or not.
813         * @type Boolean
814         */
815         _collapsed: null,
816         /**
817         * @private
818         * @property _collapsing
819         * @description A flag set while the unit is being collapsed, used so we don't fire events while animating the size
820         * @type Boolean
821         */
822         _collapsing: null,
823         /**
824         * @private
825         * @property _lastWidth
826         * @description A holder for the last known width of the unit
827         * @type Number
828         */
829         _lastWidth: null,
830         /**
831         * @private
832         * @property _lastHeight
833         * @description A holder for the last known height of the unit
834         * @type Number
835         */
836         _lastHeight: null,
837         /**
838         * @private
839         * @property _lastTop
840         * @description A holder for the last known top of the unit
841         * @type Number
842         */
843         _lastTop: null,
844         /**
845         * @private
846         * @property _lastLeft
847         * @description A holder for the last known left of the unit
848         * @type Number
849         */
850         _lastLeft: null,
851         /**
852         * @private
853         * @property _lastScroll
854         * @description A holder for the last known scroll state of the unit
855         * @type Boolean
856         */
857         _lastScroll: null,
858         /**
859         * @private
860         * @property _lastCenetrScroll
861         * @description A holder for the last known scroll state of the center unit
862         * @type Boolean
863         */
864         _lastCenterScroll: null,
865         /**
866         * @private
867         * @property _lastScrollTop
868         * @description A holder for the last known scrollTop state of the unit
869         * @type Number
870         */
871         _lastScrollTop: null,
872         /**
873         * @method resize
874         * @description Resize either the unit or it's clipped state, also updating the box inside
875         * @param {Boolean} force This will force full calculations even when the unit is collapsed
876         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
877         */
878         resize: function(force) {
879             YAHOO.log('Resize', 'info', 'LayoutUnit');
880             var retVal = this.fireEvent('beforeResize');
881             if (retVal === false) {
882                 return this;
883             }
884             if (!this._collapsing || (force === true)) {
885                 var scroll = this.get('scroll');
886                 this.set('scroll', false);
887
888
889                 var hd = this._getBoxSize(this.header),
890                     ft = this._getBoxSize(this.footer),
891                     box = [this.get('height'), this.get('width')];
892
893                 var nh = (box[0] - hd[0] - ft[0]) - (this._gutter.top + this._gutter.bottom),
894                     nw = box[1] - (this._gutter.left + this._gutter.right);
895
896                 var wrapH = (nh + (hd[0] + ft[0])),
897                     wrapW = nw;
898
899                 if (this._collapsed && !this._collapsing) {
900                     this._setHeight(this._clip, wrapH);
901                     this._setWidth(this._clip, wrapW);
902                     Dom.setStyle(this._clip, 'top', this.get('top') + this._gutter.top + 'px');
903                     Dom.setStyle(this._clip, 'left', this.get('left') + this._gutter.left + 'px');
904                 } else if (!this._collapsed || (this._collapsed && this._collapsing)) {
905                     wrapH = this._setHeight(this.get('wrap'), wrapH);
906                     wrapW = this._setWidth(this.get('wrap'), wrapW);
907                     this._sizes.wrap.h = wrapH;
908                     this._sizes.wrap.w = wrapW;
909
910                     Dom.setStyle(this.get('wrap'), 'top', this._gutter.top + 'px');
911                     Dom.setStyle(this.get('wrap'), 'left', this._gutter.left + 'px');
912
913                     this._sizes.header.w = this._setWidth(this.header, wrapW);
914                     this._sizes.header.h = hd[0];
915
916                     this._sizes.footer.w = this._setWidth(this.footer, wrapW);
917                     this._sizes.footer.h = ft[0];
918
919                     Dom.setStyle(this.footer, 'bottom', '0px');
920
921                     this._sizes.body.h = this._setHeight(this.body, (wrapH - (hd[0] + ft[0])));
922                     this._sizes.body.w =this._setWidth(this.body, wrapW);
923                     Dom.setStyle(this.body, 'top', hd[0] + 'px');
924
925                     this.set('scroll', scroll);
926                     this.fireEvent('resize');
927                 }
928             }
929             return this;
930         },
931         /**
932         * @private
933         * @method _setWidth
934         * @description Sets the width of the element based on the border size of the element.
935         * @param {HTMLElement} el The HTMLElement to have it's width set
936         * @param {Number} w The width that you want it the element set to
937         * @return {Number} The new width, fixed for borders and IE QuirksMode
938         */
939         _setWidth: function(el, w) {
940             if (el) {
941                 var b = this._getBorderSizes(el);
942                 w = (w - (b[1] + b[3]));
943                 w = this._fixQuirks(el, w, 'w');
944                 if (w < 0) {
945                     w = 0;
946                 }
947                 Dom.setStyle(el, 'width', w + 'px');
948             }
949             return w;
950         },
951         /**
952         * @private
953         * @method _setHeight
954         * @description Sets the height of the element based on the border size of the element.
955         * @param {HTMLElement} el The HTMLElement to have it's height set
956         * @param {Number} h The height that you want it the element set to
957         * @return {Number} The new height, fixed for borders and IE QuirksMode
958         */
959         _setHeight: function(el, h) {
960             if (el) {
961                 var b = this._getBorderSizes(el);
962                 h = (h - (b[0] + b[2]));
963                 h = this._fixQuirks(el, h, 'h');
964                 if (h < 0) {
965                     h = 0;
966                 }
967                 Dom.setStyle(el, 'height', h + 'px');
968             }
969             return h;
970         },
971         /**
972         * @private
973         * @method _fixQuirks
974         * @description Fixes the box calculations for IE in QuirksMode
975         * @param {HTMLElement} el The HTMLElement to set the dimension on
976         * @param {Number} dim The number of the dimension to fix
977         * @param {String} side The dimension (h or w) to fix. Defaults to h
978         * @return {Number} The fixed dimension
979         */
980         _fixQuirks: function(el, dim, side) {
981             var i1 = 0, i2 = 2;
982             if (side == 'w') {
983                 i1 = 1;
984                 i2 = 3;
985             }
986             if (this.browser.ie && !this.browser.standardsMode) {
987                 //Internet Explorer - Quirks Mode
988                 var b = this._getBorderSizes(el),
989                     bp = this._getBorderSizes(el.parentNode);
990                 if ((b[i1] === 0) && (b[i2] === 0)) { //No Borders, check parent
991                     if ((bp[i1] !== 0) && (bp[i2] !== 0)) { //Parent has Borders
992                         dim = (dim - (bp[i1] + bp[i2]));
993                     }
994                 } else {
995                     if ((bp[i1] === 0) && (bp[i2] === 0)) {
996                         dim = (dim + (b[i1] + b[i2]));
997                     }
998                 }
999             }
1000             return dim;
1001         },
1002         /**
1003         * @private
1004         * @method _getBoxSize
1005         * @description Get's the elements clientHeight and clientWidth plus the size of the borders
1006         * @param {HTMLElement} el The HTMLElement to get the size of
1007         * @return {Array} An array of height and width
1008         */
1009         _getBoxSize: function(el) {
1010             var size = [0, 0];
1011             if (el) {
1012                 if (this.browser.ie && !this.browser.standardsMode) {
1013                     el.style.zoom = 1;
1014                 }
1015                 var b = this._getBorderSizes(el);
1016                 size[0] = el.clientHeight + (b[0] + b[2]);
1017                 size[1] = el.clientWidth + (b[1] + b[3]);
1018             }
1019             return size;
1020         },
1021         /**
1022         * @private
1023         * @method _getBorderSizes
1024         * @description Get the CSS border size of the element passed.
1025         * @param {HTMLElement} el The element to get the border size of
1026         * @return {Array} An array of the top, right, bottom, left borders.
1027         */
1028         _getBorderSizes: function(el) {
1029             var s = [];
1030             el = el || this.get('element');
1031             if (this.browser.ie && !this.browser.standardsMode) {
1032                 el.style.zoom = 1;
1033             }
1034             s[0] = parseInt(Dom.getStyle(el, 'borderTopWidth'), 10);
1035             s[1] = parseInt(Dom.getStyle(el, 'borderRightWidth'), 10);
1036             s[2] = parseInt(Dom.getStyle(el, 'borderBottomWidth'), 10);
1037             s[3] = parseInt(Dom.getStyle(el, 'borderLeftWidth'), 10);
1038             
1039             //IE will return NaN on these if they are set to auto, we'll set them to 0
1040             for (var i = 0; i < s.length; i++) {
1041                 if (isNaN(s[i])) {
1042                     s[i] = 0;
1043                 }
1044             }
1045             return s;
1046         },
1047         /**
1048         * @private
1049         * @method _createClip
1050         * @description Create the clip element used when the Unit is collapsed
1051         */
1052         _createClip: function() {
1053             if (!this._clip) {
1054                 this._clip = document.createElement('div');
1055                 this._clip.className = 'yui-layout-clip yui-layout-clip-' + this.get('position');
1056                 this._clip.innerHTML = '<div class="collapse"></div>';
1057                 var c = this._clip.firstChild;
1058                 c.title = this.STR_EXPAND;
1059                 Event.on(c, 'click', this.expand, this, true);
1060                 this.get('element').parentNode.appendChild(this._clip);
1061             }
1062         },
1063         /**
1064         * @private
1065         * @method _toggleClip
1066         * @description Toggle th current state of the Clip element and set it's height, width and position
1067         */
1068         _toggleClip: function() {
1069             if (!this._collapsed) {
1070                 //show
1071                 var hd = this._getBoxSize(this.header),
1072                     ft = this._getBoxSize(this.footer),
1073                     box = [this.get('height'), this.get('width')];
1074
1075
1076                 var nh = (box[0] - hd[0] - ft[0]) - (this._gutter.top + this._gutter.bottom),
1077                     nw = box[1] - (this._gutter.left + this._gutter.right),
1078                     wrapH = (nh + (hd[0] + ft[0]));
1079
1080                 switch (this.get('position')) {
1081                     case 'top':
1082                     case 'bottom':
1083                         this._setWidth(this._clip, nw);
1084                         this._setHeight(this._clip, this.get('collapseSize'));
1085                         Dom.setStyle(this._clip, 'left', (this._lastLeft + this._gutter.left) + 'px');
1086                         if (this.get('position') == 'bottom') {
1087                             Dom.setStyle(this._clip, 'top', ((this._lastTop + this._lastHeight) - (this.get('collapseSize') - this._gutter.top)) + 'px');
1088                         } else {
1089                             Dom.setStyle(this._clip, 'top', this.get('top') + this._gutter.top + 'px');
1090                         }
1091                         break;
1092                     case 'left':
1093                     case 'right':
1094                         this._setWidth(this._clip, this.get('collapseSize'));
1095                         this._setHeight(this._clip, wrapH);
1096                         Dom.setStyle(this._clip, 'top', (this.get('top') + this._gutter.top) + 'px');
1097                         if (this.get('position') == 'right') {
1098                             Dom.setStyle(this._clip, 'left', (((this._lastLeft + this._lastWidth) - this.get('collapseSize')) - this._gutter.left) + 'px');
1099                         } else {
1100                             Dom.setStyle(this._clip, 'left', (this.get('left') + this._gutter.left) + 'px');
1101                         }
1102                         break;
1103                 }
1104
1105                 Dom.setStyle(this._clip, 'display', 'block');
1106                 this.setStyle('display', 'none');
1107             } else {
1108                 //Hide
1109                 Dom.setStyle(this._clip, 'display', 'none');
1110             }
1111         },
1112         /**
1113         * @method getSizes
1114         * @description Get a reference to the internal sizes object for this unit
1115         * @return {Object} An object of the sizes used for calculations
1116         */
1117         getSizes: function() {
1118             return this._sizes;
1119         },
1120         /**
1121         * @method toggle
1122         * @description Toggles the Unit, replacing it with a clipped version.
1123         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
1124         */
1125         toggle: function() {
1126             if (this._collapsed) {
1127                 this.expand();
1128             } else {
1129                 this.collapse();
1130             }
1131             return this;
1132         },
1133         /**
1134         * @method expand
1135         * @description Expand the Unit if it is collapsed.
1136         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
1137         */
1138         expand: function() {
1139             if (!this._collapsed) {
1140                 return this;
1141             }
1142             var retVal = this.fireEvent('beforeExpand');
1143             if (retVal === false) {
1144                 return this;
1145             }
1146
1147             this._collapsing = true;
1148             this.setStyle('zIndex', this.get('parent')._zIndex + 1);
1149
1150             if (this._anim) {
1151                 this.setStyle('display', 'none');
1152                 var attr = {}, s;
1153
1154                 switch (this.get('position')) {
1155                     case 'left':
1156                     case 'right':
1157                         this.set('width', this._lastWidth, true);
1158                         this.setStyle('width', this._lastWidth + 'px');
1159                         this.get('parent').resize(false);
1160                         s = this.get('parent').getSizes()[this.get('position')];
1161                         this.set('height', s.h, true);
1162                         var left = s.l;
1163                         attr = {
1164                             left: {
1165                                 to: left
1166                             }
1167                         };
1168                         if (this.get('position') == 'left') {
1169                             attr.left.from = (left - s.w);
1170                             this.setStyle('left', (left - s.w) + 'px');
1171                         }
1172                         break;
1173                     case 'top':
1174                     case 'bottom':
1175                         this.set('height', this._lastHeight, true);
1176                         this.setStyle('height', this._lastHeight + 'px');
1177                         this.get('parent').resize(false);
1178                         s = this.get('parent').getSizes()[this.get('position')];
1179                         this.set('width', s.w, true);
1180                         var top = s.t;
1181                         attr = {
1182                             top: {
1183                                 to: top
1184                             }
1185                         };
1186                         if (this.get('position') == 'top') {
1187                             this.setStyle('top',  (top - s.h) + 'px');
1188                             attr.top.from = (top - s.h);
1189                         }
1190                         break;
1191                 }
1192
1193                 this._anim.attributes = attr;
1194                 var exStart = function() {
1195                     this.setStyle('display', 'block');
1196                     this.resize(true);
1197                     this._anim.onStart.unsubscribe(exStart, this, true);
1198                 };
1199                 var expand = function() {
1200                     this._collapsing = false;
1201                     this.setStyle('zIndex', this.get('parent')._zIndex);
1202                     this.set('width', this._lastWidth);
1203                     this.set('height', this._lastHeight);
1204                     this._collapsed = false;
1205                     this.resize();
1206                     this.set('scroll', this._lastScroll);
1207                     if (this._lastScrollTop > 0) {
1208                         this.body.scrollTop = this._lastScrollTop;
1209                     }
1210                     this._anim.onComplete.unsubscribe(expand, this, true);
1211                     this.fireEvent('expand');
1212                 };
1213                 this._anim.onStart.subscribe(exStart, this, true);
1214                 this._anim.onComplete.subscribe(expand, this, true);
1215                 this._anim.animate();
1216                 this._toggleClip();
1217             } else {
1218                 this._collapsing = false;
1219                 this._toggleClip();
1220                 this._collapsed = false;
1221                 this.setStyle('zIndex', this.get('parent')._zIndex);
1222                 this.setStyle('display', 'block');
1223                 this.set('width', this._lastWidth);
1224                 this.set('height', this._lastHeight);
1225                 this.resize();
1226                 this.set('scroll', this._lastScroll);
1227                 if (this._lastScrollTop > 0) {
1228                     this.body.scrollTop = this._lastScrollTop;
1229                 }
1230                 this.fireEvent('expand');
1231             }
1232             return this;
1233         },
1234         /**
1235         * @method collapse
1236         * @description Collapse the Unit if it is not collapsed.
1237         * @return {<a href="YAHOO.widget.LayoutUnit.html">YAHOO.widget.LayoutUnit</a>} The LayoutUnit instance
1238         */
1239         collapse: function() {
1240             if (this._collapsed) {
1241                 return this;
1242             }
1243             var retValue = this.fireEvent('beforeCollapse');
1244             if (retValue === false) {
1245                 return this;
1246             }
1247             if (!this._clip) {
1248                 this._createClip();
1249             }
1250             this._collapsing = true;
1251             var w = this.get('width'),
1252                 h = this.get('height'),
1253                 attr = {};
1254             this._lastWidth = w;
1255             this._lastHeight = h;
1256             this._lastScroll = this.get('scroll');
1257             this._lastScrollTop = this.body.scrollTop;            
1258             this.set('scroll', false, true);
1259             this._lastLeft = parseInt(this.get('element').style.left, 10);
1260             this._lastTop = parseInt(this.get('element').style.top, 10);
1261             if (isNaN(this._lastTop)) {
1262                 this._lastTop = 0;
1263                 this.set('top', 0);
1264             }
1265             if (isNaN(this._lastLeft)) {
1266                 this._lastLeft = 0;
1267                 this.set('left', 0);
1268             }
1269             this.setStyle('zIndex', this.get('parent')._zIndex + 1);
1270             var pos = this.get('position');
1271
1272             switch (pos) {
1273                 case 'top':
1274                 case 'bottom':
1275                     this.set('height', (this.get('collapseSize') + (this._gutter.top + this._gutter.bottom)));
1276                     attr = {
1277                         top: {
1278                             to: (this.get('top') - h)
1279                         }
1280                     };
1281                     if (pos == 'bottom') {
1282                         attr.top.to = (this.get('top') + h);
1283                     }
1284                     break;
1285                 case 'left':
1286                 case 'right':
1287                     this.set('width', (this.get('collapseSize') + (this._gutter.left + this._gutter.right)));
1288                     attr = {
1289                         left: {
1290                             to: -(this._lastWidth)
1291                         }
1292                     };
1293                     if (pos == 'right') {
1294                         attr.left = {
1295                             to: (this.get('left') + w)
1296                         };
1297                     }
1298                     break;
1299             }
1300             if (this._anim) {
1301                 this._anim.attributes = attr;
1302                 var collapse = function() {
1303                     this._collapsing = false;
1304                     this._toggleClip();
1305                     this.setStyle('zIndex', this.get('parent')._zIndex);
1306                     this._collapsed = true;
1307                     this.get('parent').resize();
1308                     this._anim.onComplete.unsubscribe(collapse, this, true);
1309                     this.fireEvent('collapse');
1310                 };
1311                 this._anim.onComplete.subscribe(collapse, this, true);
1312                 this._anim.animate();
1313             } else {
1314                 this._collapsing = false;
1315                 this.setStyle('display', 'none');
1316                 this._toggleClip();
1317                 this.setStyle('zIndex', this.get('parent')._zIndex);
1318                 this.get('parent').resize();
1319                 this._collapsed = true;
1320                 this.fireEvent('collapse');
1321             }
1322             return this;
1323         },
1324         /**
1325         * @method close
1326         * @description Close the unit, removing it from the parent Layout.
1327         * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The parent Layout instance
1328         */
1329         close: function() {
1330             this.setStyle('display', 'none');
1331             this.get('parent').removeUnit(this);
1332             this.fireEvent('close');
1333             if (this._clip) {
1334                 this._clip.parentNode.removeChild(this._clip);
1335                 this._clip = null;
1336             }
1337             return this.get('parent');
1338         },
1339                 /**
1340         * @property loadHandler
1341         * @description Callback method for the YUI Connection Manager used for load the body using AJAX
1342         * @type Object
1343         */
1344                 loadHandler: {
1345             success: function(o) {
1346                                 this.body.innerHTML = o.responseText;
1347                                 this.resize (true);
1348             },
1349             failure: function(o) {
1350             }
1351         },
1352                 /**
1353         * @property dataConnection
1354         * @description YUI Connection Manager handler
1355         * @type Object
1356         */
1357                 dataConnection: null,
1358                 /**
1359         * @private
1360         * @property _loading
1361         * @description During the loading process this variable will be true
1362         * @type Number
1363         */
1364         _loading: false,
1365                 /**
1366         * @method loadContent
1367         * @description Loading the content of the unit using the connection manager
1368         * @return {object} YUI Connection Manager handler
1369         */
1370         loadContent: function() {
1371                         // load dynamic content unless already loading or loaded and caching
1372                         if (YAHOO.util.Connect && this.get('dataSrc') && !this._loading && !this.get('dataLoaded')) {
1373                         this._loading = true; 
1374                         Dom.addClass(this.body, this.LOADING_CLASSNAME);
1375                                 this.dataConnection = YAHOO.util.Connect.asyncRequest(
1376                             this.get('loadMethod'),
1377                             this.get('dataSrc'), 
1378                             {
1379                                 success: function(o) {
1380                                     this.loadHandler.success.call(this, o);
1381                                     this.set('dataLoaded', true);
1382                                     this.dataConnection = null;
1383                                     Dom.removeClass(this.body, this.LOADING_CLASSNAME);
1384                                                         this._loading = false;
1385                                                         this.fireEvent('load');
1386                                 },
1387                                 failure: function(o) {
1388                                     this.loadHandler.failure.call(this, o);
1389                                     this.dataConnection = null;
1390                                     Dom.removeClass(this.body, this.LOADING_CLASSNAME);
1391                                     this._loading = false;
1392                                                         this.fireEvent('loadError', { error: o });
1393                                 },
1394                                 scope: this,
1395                                 timeout: this.get('dataTimeout')
1396                             }
1397                         );
1398                                 return this.dataConnection;
1399                 }
1400                         return false;
1401         },
1402         /**
1403         * @private
1404         * @method init
1405         * @description The initalization method inherited from Element.
1406         */
1407         init: function(p_oElement, p_oAttributes) {
1408             YAHOO.log('init', 'info', 'LayoutUnit');
1409             this._gutter = {
1410                 left: 0,
1411                 right: 0,
1412                 top: 0,
1413                 bottom: 0
1414             };
1415             this._sizes = {
1416                 wrap: {
1417                     h: 0,
1418                     w: 0
1419                 },
1420                 header: {
1421                     h: 0,
1422                     w: 0
1423                 },
1424                 body: {
1425                     h: 0,
1426                     w: 0
1427                 },
1428                 footer: {
1429                     h: 0,
1430                     w: 0
1431                 }
1432             };
1433             
1434             LayoutUnit.superclass.init.call(this, p_oElement, p_oAttributes);
1435
1436             this.browser = this.get('parent').browser;
1437             
1438             var id = p_oElement;
1439             if (!Lang.isString(id)) {
1440                 id = Dom.generateId(id);
1441             }
1442             LayoutUnit._instances[id] = this;
1443
1444             this.setStyle('position', 'absolute');
1445
1446             this.addClass('yui-layout-unit');
1447             this.addClass('yui-layout-unit-' + this.get('position'));
1448
1449
1450             var header = this.getElementsByClassName('yui-layout-hd', 'div')[0];
1451             if (header) {
1452                 this.header = header;
1453             }
1454             var body = this.getElementsByClassName('yui-layout-bd', 'div')[0];
1455             if (body) {
1456                 this.body = body;
1457             }
1458             var footer = this.getElementsByClassName('yui-layout-ft', 'div')[0];
1459             if (footer) {
1460                 this.footer = footer;
1461             }
1462
1463             this.on('contentChange', this.resize, this, true);
1464             this._lastScrollTop = 0;
1465
1466             this.set('animate', this.get('animate'));
1467         },
1468         /**
1469         * @private
1470         * @method initAttributes
1471         * @description Processes the config
1472         */        
1473         initAttributes: function(attr) {
1474             LayoutUnit.superclass.initAttributes.call(this, attr);
1475
1476             /**
1477             * @private
1478             * @attribute wrap
1479             * @description A reference to the wrap element
1480             * @type HTMLElement
1481             */
1482             this.setAttributeConfig('wrap', {
1483                 value: attr.wrap || null,
1484                 method: function(w) {
1485                     if (w) {
1486                         var id = Dom.generateId(w);
1487                         LayoutUnit._instances[id] = this;
1488                     }
1489                 }
1490             });
1491             /**
1492             * @attribute grids
1493             * @description Set this option to true if you want the LayoutUnit to fix the first layer of YUI CSS Grids (margins)
1494             * @type Boolean
1495             */
1496             this.setAttributeConfig('grids', {
1497                 value: attr.grids || false
1498             });
1499             /**
1500             * @private
1501             * @attribute top
1502             * @description The current top positioning of the Unit
1503             * @type Number
1504             */
1505             this.setAttributeConfig('top', {
1506                 value: attr.top || 0,
1507                 validator: Lang.isNumber,
1508                 method: function(t) {
1509                     if (!this._collapsing) {
1510                         this.setStyle('top', t + 'px');
1511                     }
1512                 }
1513             });
1514             /**
1515             * @private
1516             * @attribute left
1517             * @description The current left position of the Unit
1518             * @type Number
1519             */
1520             this.setAttributeConfig('left', {
1521                 value: attr.left || 0,
1522                 validator: Lang.isNumber,
1523                 method: function(l) {
1524                     if (!this._collapsing) {
1525                         this.setStyle('left', l + 'px');
1526                     }
1527                 }
1528             });
1529
1530             /**
1531             * @attribute minWidth
1532             * @description The minWidth parameter passed to the Resize Utility
1533             * @type Number
1534             */
1535             this.setAttributeConfig('minWidth', {
1536                 value: attr.minWidth || false,
1537                 validator: YAHOO.lang.isNumber
1538             });
1539
1540             /**
1541             * @attribute maxWidth
1542             * @description The maxWidth parameter passed to the Resize Utility
1543             * @type Number
1544             */
1545             this.setAttributeConfig('maxWidth', {
1546                 value: attr.maxWidth || false,
1547                 validator: YAHOO.lang.isNumber
1548             });
1549
1550             /**
1551             * @attribute minHeight
1552             * @description The minHeight parameter passed to the Resize Utility
1553             * @type Number
1554             */
1555             this.setAttributeConfig('minHeight', {
1556                 value: attr.minHeight || false,
1557                 validator: YAHOO.lang.isNumber
1558             });
1559
1560             /**
1561             * @attribute maxHeight
1562             * @description The maxHeight parameter passed to the Resize Utility
1563             * @type Number
1564             */
1565             this.setAttributeConfig('maxHeight', {
1566                 value: attr.maxHeight || false,
1567                 validator: YAHOO.lang.isNumber
1568             });
1569
1570             /**
1571             * @attribute height
1572             * @description The height of the Unit
1573             * @type Number
1574             */
1575             this.setAttributeConfig('height', {
1576                 value: attr.height,
1577                 validator: Lang.isNumber,
1578                 method: function(h) {
1579                     if (!this._collapsing) {
1580                         if (h < 0) {
1581                             h = 0;
1582                         }
1583                         this.setStyle('height', h + 'px');
1584                     }
1585                 }
1586             });
1587
1588             /**
1589             * @attribute width
1590             * @description The width of the Unit
1591             * @type Number
1592             */
1593             this.setAttributeConfig('width', {
1594                 value: attr.width,
1595                 validator: Lang.isNumber,
1596                 method: function(w) {
1597                     if (!this._collapsing) {
1598                         if (w < 0) {
1599                             w = 0;
1600                         }
1601                         this.setStyle('width', w + 'px');
1602                     }
1603                 }
1604             });
1605             /**
1606             * @attribute zIndex
1607             * @description The CSS zIndex to give to the unit, so you can have overlapping elements such as menus in a unit.
1608             * @type {Number}
1609             */
1610             this.setAttributeConfig('zIndex', {
1611                 value: attr.zIndex || false,
1612                 method: function(z) {
1613                     this.setStyle('zIndex', z);
1614                 }
1615             });
1616             /**
1617             * @attribute position
1618             * @description The position (top, right, bottom, left or center) of the Unit in the Layout
1619             * @type {String}
1620             */
1621             this.setAttributeConfig('position', {
1622                 value: attr.position
1623             });
1624             /**
1625             * @attribute gutter
1626             * @description The gutter that we should apply to the parent Layout around this Unit. Supports standard CSS markup: (2 4 0 5) or (2) or (2 5)
1627             * @type String
1628             */
1629             this.setAttributeConfig('gutter', {
1630                 value: attr.gutter || 0,
1631                 validator: YAHOO.lang.isString,
1632                 method: function(gutter) {
1633                     var p = gutter.split(' ');
1634                     if (p.length) {
1635                         this._gutter.top = parseInt(p[0], 10);
1636                         if (p[1]) {
1637                             this._gutter.right = parseInt(p[1], 10);
1638                         } else {
1639                             this._gutter.right = this._gutter.top;
1640                         }
1641                         if (p[2]) {
1642                             this._gutter.bottom = parseInt(p[2], 10);
1643                         } else {
1644                             this._gutter.bottom = this._gutter.top;
1645                         }
1646                         if (p[3]) {
1647                             this._gutter.left = parseInt(p[3], 10);
1648                         } else if (p[1]) {
1649                             this._gutter.left = this._gutter.right;
1650                         } else {
1651                             this._gutter.left = this._gutter.top;
1652                         }
1653                     }
1654                 }
1655             });
1656             /**
1657             * @attribute parent
1658             * @description The parent Layout that we are assigned to
1659             * @type {Object} YAHOO.widget.Layout
1660             */
1661             this.setAttributeConfig('parent', {
1662                 writeOnce: true,
1663                 value: attr.parent || false,
1664                 method: function(p) {
1665                     if (p) {
1666                         p.on('resize', this.resize, this, true);
1667                     }
1668
1669                 }
1670             });
1671             /**
1672             * @attribute collapseSize
1673             * @description The pixel size of the Clip that we will collapse to
1674             * @type Number
1675             */
1676             this.setAttributeConfig('collapseSize', {
1677                 value: attr.collapseSize || 25,
1678                 validator: YAHOO.lang.isNumber
1679             });
1680             /**
1681             * @attribute duration
1682             * @description The duration to give the Animation Utility when animating the opening and closing of Units
1683             */
1684             this.setAttributeConfig('duration', {
1685                 value: attr.duration || 0.5
1686             });
1687             /**
1688             * @attribute easing
1689             * @description The Animation Easing to apply to the Animation instance for this unit.
1690             */
1691             this.setAttributeConfig('easing', {
1692                 value: attr.easing || ((YAHOO.util && YAHOO.util.Easing) ? YAHOO.util.Easing.BounceIn : 'false')
1693             });
1694             /**
1695             * @attribute animate
1696             * @description Use animation to collapse/expand the unit
1697             * @type Boolean
1698             */
1699             this.setAttributeConfig('animate', {
1700                 value: ((attr.animate === false) ? false : true),
1701                 validator: function() {
1702                     var anim = false;
1703                     if (YAHOO.util.Anim) {
1704                         anim = true;
1705                     }
1706                     return anim;
1707                 },
1708                 method: function(anim) {
1709                     if (anim) {
1710                         this._anim = new YAHOO.util.Anim(this.get('element'), {}, this.get('duration'), this.get('easing'));
1711                     } else {
1712                         this._anim = false;
1713                     }
1714                 }
1715             });
1716             /**
1717             * @attribute header
1718             * @description The text to use as the Header of the Unit
1719             */
1720             this.setAttributeConfig('header', {
1721                 value: attr.header || false,
1722                 method: function(txt) {
1723                     if (txt === false) {
1724                         //Remove the footer
1725                         if (this.header) {
1726                             Dom.addClass(this.body, 'yui-layout-bd-nohd');
1727                             this.header.parentNode.removeChild(this.header);
1728                             this.header = null;
1729                         }
1730                     } else {
1731                         if (!this.header) {
1732                             var header = this.getElementsByClassName('yui-layout-hd', 'div')[0];
1733                             if (!header) {
1734                                 header = this._createHeader();
1735                             }
1736                             this.header = header;
1737                         }
1738                         var h = this.header.getElementsByTagName('h2')[0];
1739                         if (!h) {
1740                             h = document.createElement('h2');
1741                             this.header.appendChild(h);
1742                         }
1743                         h.innerHTML = txt;
1744                         if (this.body) {
1745                             Dom.removeClass(this.body, 'yui-layout-bd-nohd');
1746                         }
1747                     }
1748                     this.fireEvent('contentChange', { target: 'header' });
1749                 }
1750             });
1751             /**
1752             * @attribute proxy
1753             * @description Use the proxy config setting for the Resize Utility
1754             * @type Boolean
1755             */
1756             this.setAttributeConfig('proxy', {
1757                 writeOnce: true,
1758                 value: ((attr.proxy === false) ? false : true)
1759             });
1760             /**
1761             * @attribute body
1762             * @description The content for the body. If we find an element in the page with an id that matches the passed option we will move that element into the body of this unit.
1763             */
1764             this.setAttributeConfig('body', {
1765                 value: attr.body || false,
1766                 method: function(content) {
1767                     if (!this.body) {
1768                         var body = this.getElementsByClassName('yui-layout-bd', 'div')[0];
1769                         if (body) {
1770                             this.body = body;
1771                         } else {
1772                             body = document.createElement('div');
1773                             body.className = 'yui-layout-bd';
1774                             this.body = body;
1775                             this.get('wrap').appendChild(body);
1776                         }
1777                     }
1778                     if (!this.header) {
1779                         Dom.addClass(this.body, 'yui-layout-bd-nohd');
1780                     }
1781                     Dom.addClass(this.body, 'yui-layout-bd-noft');
1782
1783
1784                     var el = null;
1785                     if (Lang.isString(content)) {
1786                         el = Dom.get(content);
1787                     } else if (content && content.tagName) {
1788                         el = content;
1789                     }
1790                     if (el) {
1791                         var id = Dom.generateId(el);
1792                         LayoutUnit._instances[id] = this;
1793                         this.body.appendChild(el);
1794                     } else {
1795                         this.body.innerHTML = content;
1796                     }
1797
1798                     this._cleanGrids();
1799
1800                     this.fireEvent('contentChange', { target: 'body' });
1801                 }
1802             });
1803
1804             /**
1805             * @attribute footer
1806             * @description The content for the footer. If we find an element in the page with an id that matches the passed option we will move that element into the footer of this unit.
1807             */
1808             this.setAttributeConfig('footer', {
1809                 value: attr.footer || false,
1810                 method: function(content) {
1811                     if (content === false) {
1812                         //Remove the footer
1813                         if (this.footer) {
1814                             Dom.addClass(this.body, 'yui-layout-bd-noft');
1815                             this.footer.parentNode.removeChild(this.footer);
1816                             this.footer = null;
1817                         }
1818                     } else {
1819                         if (!this.footer) {
1820                             var ft = this.getElementsByClassName('yui-layout-ft', 'div')[0];
1821                             if (!ft) {
1822                                 ft = document.createElement('div');
1823                                 ft.className = 'yui-layout-ft';
1824                                 this.footer = ft;
1825                                 this.get('wrap').appendChild(ft);
1826                             } else {
1827                                 this.footer = ft;
1828                             }
1829                         }
1830                         var el = null;
1831                         if (Lang.isString(content)) {
1832                             el = Dom.get(content);
1833                         } else if (content && content.tagName) {
1834                             el = content;
1835                         }
1836                         if (el) {
1837                             this.footer.appendChild(el);
1838                         } else {
1839                             this.footer.innerHTML = content;
1840                         }
1841                         Dom.removeClass(this.body, 'yui-layout-bd-noft');
1842                     }
1843                     this.fireEvent('contentChange', { target: 'footer' });
1844                 }
1845             });
1846             /**
1847             * @attribute close
1848             * @description Adds a close icon to the unit
1849             */
1850             this.setAttributeConfig('close', {
1851                 value: attr.close || false,
1852                 method: function(close) {
1853                     //Position Center doesn't get this
1854                     if (this.get('position') == 'center') {
1855                         YAHOO.log('Position center unit cannot have close', 'error', 'LayoutUnit');
1856                         return false;
1857                     }
1858                     if (!this.header) {
1859                         this._createHeader();
1860                     }
1861                     var c = Dom.getElementsByClassName('close', 'div', this.header)[0];
1862                     if (close) {
1863                         //Force some header text if there isn't any
1864                         if (!this.get('header')) {
1865                             this.set('header', '&nbsp;');
1866                         }
1867                         if (!c) {
1868                             c = document.createElement('div');
1869                             c.className = 'close';
1870                             this.header.appendChild(c);
1871                             Event.on(c, 'click', this.close, this, true);
1872                         }
1873                         c.title = this.STR_CLOSE;
1874                     } else if (c) {
1875                         Event.purgeElement(c);
1876                         c.parentNode.removeChild(c);
1877                     }
1878                     this._configs.close.value = close;
1879                     this.set('collapse', this.get('collapse')); //Reset so we get the right classnames
1880                 }
1881             });
1882
1883             /**
1884             * @attribute collapse
1885             * @description Adds a collapse icon to the unit
1886             */
1887             this.setAttributeConfig('collapse', {
1888                 value: attr.collapse || false,
1889                 method: function(collapse) {
1890                     //Position Center doesn't get this
1891                     if (this.get('position') == 'center') {
1892                         YAHOO.log('Position center unit cannot have collapse', 'error', 'LayoutUnit');
1893                         return false;
1894                     }
1895                     if (!this.header) {
1896                         this._createHeader();
1897                     }
1898                     var c = Dom.getElementsByClassName('collapse', 'div', this.header)[0];
1899                     if (collapse) {
1900                         //Force some header text if there isn't any
1901                         if (!this.get('header')) {
1902                             this.set('header', '&nbsp;');
1903                         }
1904                         if (!c) {
1905                             c = document.createElement('div');
1906                             this.header.appendChild(c);
1907                             Event.on(c, 'click', this.collapse, this, true);
1908                         }
1909                         c.title = this.STR_COLLAPSE;
1910                         c.className = 'collapse' + ((this.get('close')) ? ' collapse-close' : '');
1911                     } else if (c) {
1912                         Event.purgeElement(c);
1913                         c.parentNode.removeChild(c);
1914                     }
1915                 }
1916             });
1917             /**
1918             * @attribute scroll
1919             * @description Adds a class to the unit to allow for overflow: auto (yui-layout-scroll), default is overflow: hidden (yui-layout-noscroll). If true scroll bars will be placed on the element when the content exceeds the given area, false will put overflow hidden to hide the content. Passing null will render the content as usual overflow.
1920             * @type Boolean/Null
1921             */
1922
1923             this.setAttributeConfig('scroll', {
1924                 value: (((attr.scroll === true) || (attr.scroll === false) || (attr.scroll === null)) ? attr.scroll : false),
1925                 method: function(scroll) {
1926                     if ((scroll === false) && !this._collapsed) { //Removing scroll bar
1927                         if (this.body) {
1928                             if (this.body.scrollTop > 0) {
1929                                 this._lastScrollTop = this.body.scrollTop;
1930                             }
1931                         }
1932                     }
1933                     
1934                     if (scroll === true) {
1935                         this.addClass('yui-layout-scroll');
1936                         this.removeClass('yui-layout-noscroll');
1937                         if (this._lastScrollTop > 0) {
1938                             if (this.body) {
1939                                 this.body.scrollTop = this._lastScrollTop;
1940                             }
1941                         }
1942                     } else if (scroll === false) {
1943                         this.removeClass('yui-layout-scroll');
1944                         this.addClass('yui-layout-noscroll');
1945                     } else if (scroll === null) {
1946                         this.removeClass('yui-layout-scroll');
1947                         this.removeClass('yui-layout-noscroll');
1948                     }
1949                 }
1950             });
1951             /**
1952             * @attribute hover
1953             * @description Config option to pass to the Resize Utility
1954             */
1955             this.setAttributeConfig('hover', {
1956                 writeOnce: true,
1957                 value: attr.hover || false,
1958                 validator: YAHOO.lang.isBoolean
1959             });
1960             /**
1961             * @attribute useShim
1962             * @description Config option to pass to the Resize Utility
1963             */
1964             this.setAttributeConfig('useShim', {
1965                 value: attr.useShim || false,
1966                 validator: YAHOO.lang.isBoolean,
1967                 method: function(u) {
1968                     if (this._resize) {
1969                         this._resize.set('useShim', u);
1970                     }
1971                 }
1972             });
1973             /**
1974             * @attribute resize
1975             * @description Should a Resize instance be added to this unit
1976             */
1977
1978             this.setAttributeConfig('resize', {
1979                 value: attr.resize || false,
1980                 validator: function(r) {
1981                     if (YAHOO.util && YAHOO.util.Resize) {
1982                         return true;
1983                     }
1984                     return false;
1985                 },
1986                 method: function(resize) {
1987                     if (resize && !this._resize) {
1988                         //Position Center doesn't get this
1989                         if (this.get('position') == 'center') {
1990                             YAHOO.log('Position center unit cannot have resize', 'error', 'LayoutUnit');
1991                             return false;
1992                         }
1993                         var handle = false; //To catch center
1994                         switch (this.get('position')) {
1995                             case 'top':
1996                                 handle = 'b';
1997                                 break;
1998                             case 'bottom':
1999                                 handle = 't';
2000                                 break;
2001                             case 'right':
2002                                 handle = 'l';
2003                                 break;
2004                             case 'left':
2005                                 handle = 'r';
2006                                 break;
2007                         }
2008
2009                         this.setStyle('position', 'absolute'); //Make sure Resize get's a position
2010                         
2011                         if (handle) {
2012                             this._resize = new YAHOO.util.Resize(this.get('element'), {
2013                                 proxy: this.get('proxy'),
2014                                 hover: this.get('hover'),
2015                                 status: false,
2016                                 autoRatio: false,
2017                                 handles: [handle],
2018                                 minWidth: this.get('minWidth'),
2019                                 maxWidth: this.get('maxWidth'),
2020                                 minHeight: this.get('minHeight'),
2021                                 maxHeight: this.get('maxHeight'),
2022                                 height: this.get('height'),
2023                                 width: this.get('width'),
2024                                 setSize: false,
2025                                 useShim: this.get('useShim'),
2026                                 wrap: false
2027                             });
2028                             
2029                             this._resize._handles[handle].innerHTML = '<div class="yui-layout-resize-knob"></div>';
2030
2031                             if (this.get('proxy')) {
2032                                 var proxy = this._resize.getProxyEl();
2033                                 proxy.innerHTML = '<div class="yui-layout-handle-' + handle + '"></div>';
2034                             }
2035                             this._resize.on('startResize', function(ev) {
2036                                 this._lastScroll = this.get('scroll');
2037                                 this.set('scroll', false);
2038                                 if (this.get('parent')) {
2039                                     this.get('parent').fireEvent('startResize');
2040                                     var c = this.get('parent').getUnitByPosition('center');
2041                                     this._lastCenterScroll = c.get('scroll');
2042                                     c.addClass(this._resize.CSS_RESIZING);
2043                                     c.set('scroll', false);
2044                                 }
2045                                 this.fireEvent('startResize');
2046                             }, this, true);
2047                             this._resize.on('resize', function(ev) {
2048                                 this.set('height', ev.height);
2049                                 this.set('width', ev.width);
2050                             }, this, true);
2051                             this._resize.on('endResize', function(ev) {
2052                                 this.set('scroll', this._lastScroll);
2053                                 if (this.get('parent')) {
2054                                     var c = this.get('parent').getUnitByPosition('center');
2055                                     c.set('scroll', this._lastCenterScroll);
2056                                     c.removeClass(this._resize.CSS_RESIZING);
2057                                 }
2058                                 this.resize();
2059                                 this.fireEvent('endResize');
2060                             }, this, true);
2061                         }
2062                     } else {
2063                         if (this._resize) {
2064                             this._resize.destroy();
2065                         }
2066                     }
2067                 }
2068             });
2069                         /**
2070                  * The unit data source, used for loading content dynamically.
2071                  * @attribute dataSrc
2072                  * @type String
2073                  */
2074                 this.setAttributeConfig('dataSrc', {
2075                     value: attr.dataSrc
2076                 });
2077                 /**
2078                  * The method to use for the data request.
2079                  * @attribute loadMethod
2080                  * @type String
2081                  * @default "GET"
2082                  */
2083                 this.setAttributeConfig('loadMethod', {
2084                     value: attr.loadMethod || 'GET',
2085                     validator: YAHOO.lang.isString
2086                 });     
2087                 /**
2088                  * Whether or not any data has been loaded from the server.
2089                  * @attribute dataLoaded
2090                  * @type Boolean
2091                  */        
2092                 this.setAttributeConfig('dataLoaded', {
2093                     value: false,
2094                     validator: YAHOO.lang.isBoolean,
2095                     writeOnce: true
2096                 });
2097                 /**
2098                  * Number if milliseconds before aborting and calling failure handler.
2099                  * @attribute dataTimeout
2100                  * @type Number
2101                  * @default null
2102                  */
2103                 this.setAttributeConfig('dataTimeout', {
2104                     value: attr.dataTimeout || null,
2105                     validator: YAHOO.lang.isNumber
2106                 });
2107         },
2108         /**
2109         * @private
2110         * @method _cleanGrids
2111         * @description This method attempts to clean up the first level of the YUI CSS Grids, YAHOO.util.Selector is required for this operation.
2112         */
2113         _cleanGrids: function() {
2114             if (this.get('grids')) {
2115                 var b = Sel.query('div.yui-b', this.body, true);
2116                 if (b) {
2117                     Dom.removeClass(b, 'yui-b');
2118                 }
2119                 Event.onAvailable('yui-main', function() {
2120                     Dom.setStyle(Sel.query('#yui-main'), 'margin-left', '0');
2121                     Dom.setStyle(Sel.query('#yui-main'), 'margin-right', '0');
2122                 });
2123             }
2124         },
2125         /**
2126         * @private
2127         * @method _createHeader
2128         * @description Creates the HTMLElement for the header
2129         * @return {HTMLElement} The new HTMLElement
2130         */
2131         _createHeader: function() {
2132             var header = document.createElement('div');
2133             header.className = 'yui-layout-hd';
2134             if (this.get('firstChild')) {
2135                 this.get('wrap').insertBefore(header, this.get('wrap').firstChild);
2136             } else {
2137                 this.get('wrap').appendChild(header);
2138             }
2139             this.header = header;
2140             return header;
2141         },
2142         /**
2143         * @method destroy
2144         * @param {Boolean} force Don't report to the parent, because we are being called from the parent.
2145         * @description Removes this unit from the parent and cleans up after itself.
2146         * @return {<a href="YAHOO.widget.Layout.html">YAHOO.widget.Layout</a>} The parent Layout instance
2147         */
2148         destroy: function(force) {
2149             if (this._resize) {
2150                 this._resize.destroy();
2151             }
2152             var par = this.get('parent');
2153
2154             this.setStyle('display', 'none');
2155             if (this._clip) {
2156                 this._clip.parentNode.removeChild(this._clip);
2157                 this._clip = null;
2158             }
2159
2160             if (!force) {
2161                 par.removeUnit(this);
2162             }
2163             
2164             if (par) {
2165                 par.removeListener('resize', this.resize, this, true);
2166             }
2167             this.unsubscribeAll();
2168             Event.purgeElement(this.get('element'));
2169             this.get('parentNode').removeChild(this.get('element'));
2170
2171             delete YAHOO.widget.LayoutUnit._instances[this.get('id')];
2172             //Brutal Object Destroy
2173             for (var i in this) {
2174                 if (Lang.hasOwnProperty(this, i)) {
2175                     this[i] = null;
2176                     delete this[i];
2177                 }
2178             }
2179         
2180             return par;
2181         },
2182         /**
2183         * @method toString
2184         * @description Returns a string representing the LayoutUnit.
2185         * @return {String}
2186         */        
2187         toString: function() {
2188             if (this.get) {
2189                 return 'LayoutUnit #' + this.get('id') + ' (' + this.get('position') + ')';
2190             }
2191             return 'LayoutUnit';
2192         }
2193     /**
2194     * @event resize
2195     * @description Fired when this.resize is called
2196     * @type YAHOO.util.CustomEvent
2197     */
2198     /**
2199     * @event startResize
2200     * @description Fired when the Resize Utility fires it's startResize Event.
2201     * @type YAHOO.util.CustomEvent
2202     */
2203     /**
2204     * @event endResize
2205     * @description Fired when the Resize Utility fires it's endResize Event.
2206     * @type YAHOO.util.CustomEvent
2207     */
2208     /**
2209     * @event beforeResize
2210     * @description Fired at the beginning of the resize method. If you return false, the resize is cancelled.
2211     * @type YAHOO.util.CustomEvent
2212     */
2213     /**
2214     * @event contentChange
2215     * @description Fired when the content in the header, body or footer is changed via the API
2216     * @type YAHOO.util.CustomEvent
2217     */
2218     /**
2219     * @event close
2220     * @description Fired when the unit is closed
2221     * @type YAHOO.util.CustomEvent
2222     */
2223     /**
2224     * @event beforeCollapse
2225     * @description Fired before the unit is collapsed. If you return false, the collapse is cancelled.
2226     * @type YAHOO.util.CustomEvent
2227     */
2228     /**
2229     * @event collapse
2230     * @description Fired when the unit is collapsed
2231     * @type YAHOO.util.CustomEvent
2232     */
2233     /**
2234     * @event expand
2235     * @description Fired when the unit is exanded
2236     * @type YAHOO.util.CustomEvent
2237     */
2238     /**
2239     * @event beforeExpand
2240     * @description Fired before the unit is exanded. If you return false, the collapse is cancelled.
2241     * @type YAHOO.util.CustomEvent
2242     */
2243     /**
2244     * @event load
2245     * @description Fired when data is loaded via the dataSrc config.
2246     * @type YAHOO.util.CustomEvent
2247     */
2248     /**
2249     * @event loadError
2250     * @description Fired when an error occurs loading data via the dataSrc config. Error message is passed as argument to this event.
2251     * @type YAHOO.util.CustomEvent
2252     */
2253     });
2254
2255     YAHOO.widget.LayoutUnit = LayoutUnit;
2256 })();
2257 YAHOO.register("layout", YAHOO.widget.Layout, {version: "2.7.0", build: "1799"});