]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/widget/widget-stdmod.js
Release 6.2.0beta4
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / widget / widget-stdmod.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: 3.0.0
6 build: 1549
7 */
8 YUI.add('widget-stdmod', function(Y) {
9
10 /**
11  * Provides standard module support for Widgets through an extension.
12  * 
13  * @module widget-stdmod
14  */
15     var L = Y.Lang,
16         Node = Y.Node,
17         NodeList = Y.NodeList,
18         UA = Y.UA,
19         Widget = Y.Widget,
20
21         EMPTY = "",
22         HD = "hd",
23         BD = "bd",
24         FT = "ft",
25         HEADER = "header",
26         BODY = "body",
27         FOOTER = "footer",
28         FILL_HEIGHT = "fillHeight",
29         STDMOD = "stdmod",
30
31         PX = "px",
32         NODE_SUFFIX = "Node",
33         CONTENT_SUFFIX = "Content",
34         INNER_HTML = "innerHTML",
35         FIRST_CHILD = "firstChild",
36         CHILD_NODES = "childNodes",
37         CREATE_DOCUMENT_FRAGMENT = "createDocumentFragment",
38         OWNER_DOCUMENT = "ownerDocument",
39
40         CONTENT_BOX = "contentBox",
41         BOUNDING_BOX = "boundingBox",
42
43         HEIGHT = "height",
44         OFFSET_HEIGHT = "offsetHeight",
45         AUTO = "auto",
46
47         HeaderChange = "headerContentChange",
48         BodyChange = "bodyContentChange",
49         FooterChange = "footerContentChange",
50         FillHeightChange = "fillHeightChange",
51         HeightChange = "HeightChange",        
52         ContentUpdate = "contentUpdate",
53
54         RENDERUI = "renderUI",
55         BINDUI = "bindUI",
56         SYNCUI = "syncUI",
57
58         UI = Y.Widget.UI_SRC;
59
60     /**
61      * Widget extension, which can be used to add Standard Module support to the 
62      * base Widget class, through the <a href="Base.html#method_build">Base.build</a> 
63      * method.
64      * <p>
65      * The extension adds header, body and footer sections to the Widget's content box and 
66      * provides the corresponding methods and attributes to modify the contents of these sections.
67      * </p>
68      * @class WidgetStdMod
69      * @param {Object} The user configuration object
70      */
71     function StdMod(config) {
72
73         this._stdModNode = this.get(CONTENT_BOX);
74
75         Y.after(this._renderUIStdMod, this, RENDERUI);
76         Y.after(this._bindUIStdMod, this, BINDUI);
77         Y.after(this._syncUIStdMod, this, SYNCUI);
78     }
79
80     /**
81      * Constant used to refer the the standard module header, in methods which expect a section specifier
82      * 
83      * @property WidgetStdMod.HEADER
84      * @static
85      * @type String
86      */
87     StdMod.HEADER = HEADER;
88     /**
89      * Constant used to refer the the standard module body, in methods which expect a section specifier
90      * 
91      * @property WidgetStdMod.BODY
92      * @static
93      * @type String
94      */
95     StdMod.BODY = BODY;
96     /**
97      * Constant used to refer the the standard module footer, in methods which expect a section specifier
98      * 
99      * @property WidgetStdMod.FOOTER
100      * @static
101      * @type String
102      */
103     StdMod.FOOTER = FOOTER;
104
105     /**
106      * Constant used to specify insertion position, when adding content to sections of the standard module in 
107      * methods which expect a "where" argument.
108      * <p>
109      * Inserts new content <em>before</em> the sections existing content.
110      * </p>
111      * @property WidgetStdMod.AFTER
112      * @static
113      * @type String
114      */
115     StdMod.AFTER = "after";
116
117     /**
118      * Constant used to specify insertion position, when adding content to sections of the standard module in
119      * methods which expect a "where" argument.
120      * <p>
121      * Inserts new content <em>before</em> the sections existing content.
122      * </p>
123      * @property WidgetStdMod.BEFORE
124      * @static
125      * @type String
126      */
127     StdMod.BEFORE = "before";
128     /**
129      * Constant used to specify insertion position, when adding content to sections of the standard module in
130      * methods which expect a "where" argument.
131      * <p>
132      * <em>Replaces</em> the sections existing content, with new content.
133      * </p>
134      * @property WidgetStdMod.REPLACE
135      * @static
136      * @type String
137      */
138     StdMod.REPLACE = "replace";
139
140     var STD_HEADER = StdMod.HEADER,
141         STD_BODY = StdMod.BODY,
142         STD_FOOTER = StdMod.FOOTER,
143         AFTER = StdMod.AFTER,
144         BEFORE = StdMod.BEFORE;
145
146     /**
147      * Static property used to define the default attribute 
148      * configuration introduced by WidgetStdMod.
149      * 
150      * @property WidgetStdMod.ATTRS
151      * @type Object
152      * @static
153      */
154     StdMod.ATTRS = {
155
156         /**
157          * @attribute headerContent
158          * @type {String | Node}
159          * @default undefined
160          * @description The content to be added to the header section. This will replace any existing content
161          * in the header. If you want to append, or insert new content, use the <a href="#method_setStdModContent">setStdModContent</a> method.
162          */
163         headerContent: {
164             value:null
165         },
166
167         /**
168          * @attribute footerContent
169          * @type {String | Node}
170          * @default undefined
171          * @description The content to be added to the footer section. This will replace any existing content
172          * in the footer. If you want to append, or insert new content, use the <a href="#method_setStdModContent">setStdModContent</a> method.
173          */
174         footerContent: {
175             value:null
176         },
177         
178         /**
179          * @attribute bodyContent
180          * @type {String | Node}
181          * @default undefined
182          * @description The content to be added to the body section. This will replace any existing content
183          * in the body. If you want to append, or insert new content, use the <a href="#method_setStdModContent">setStdModContent</a> method.
184          */
185         bodyContent: {
186             value:null
187         },
188         
189         /**
190          * @attribute fillHeight
191          * @type {String}
192          * @default WidgetStdMod.BODY
193          * @description The section (WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER) which should be resized to fill the height of the standard module, when a 
194          * height is set on the Widget. If a height is not set on the widget, then all sections are sized based on 
195          * their content.
196          */
197         fillHeight: {
198             value: StdMod.BODY,
199             validator: function(val) {
200                  return this._validateFillHeight(val);
201             }
202         }
203     };
204
205     /**
206      * The HTML parsing rules for the WidgetStdMod class.
207      * 
208      * @property WidgetStdMod.HTML_PARSER
209      * @static
210      * @type Object
211      */
212     StdMod.HTML_PARSER = {
213         headerContent: function(contentBox) {
214             return this._parseStdModHTML(STD_HEADER);
215         },
216
217         bodyContent: function(contentBox) {
218             return this._parseStdModHTML(STD_BODY);
219         },
220
221         footerContent : function(contentBox) {
222             return this._parseStdModHTML(STD_FOOTER);
223         }
224     };
225
226     /**
227      * Static hash of default class names used for the header,
228      * body and footer sections of the standard module, keyed by
229      * the section identifier (WidgetStdMod.STD_HEADER, WidgetStdMod.STD_BODY, WidgetStdMod.STD_FOOTER)
230      *
231      * @property WidgetStdMod.SECTION_CLASS_NAMES
232      * @static
233      * @type Object
234      */
235     StdMod.SECTION_CLASS_NAMES = {
236         header: Widget.getClassName(HD),
237         body: Widget.getClassName(BD),
238         footer: Widget.getClassName(FT)
239     };
240
241     /**
242      * The template HTML strings for each of the standard module sections. Section entries are keyed by the section constants,
243      * WidgetStdMod.HEADER, WidgetStdMod.BODY, WidgetStdMod.FOOTER, and contain the HTML to be added for each section.
244      * e.g.
245      * <pre>
246      *    {
247      *       header : '&lt;div class="yui-widget-hd"&gt;&lt;/div&gt;',
248      *       body : '&lt;div class="yui-widget-bd"&gt;&lt;/div&gt;',
249      *       footer : '&lt;div class="yui-widget-ft"&gt;&lt;/div&gt;'
250      *    }
251      * </pre>
252      * @property WidgetStdMod.TEMPLATES
253      * @type Object
254      * @static
255      */
256     StdMod.TEMPLATES = {
257         header : '<div class="' + StdMod.SECTION_CLASS_NAMES[STD_HEADER] + '"></div>',
258         body : '<div class="' + StdMod.SECTION_CLASS_NAMES[STD_BODY] + '"></div>',
259         footer : '<div class="' + StdMod.SECTION_CLASS_NAMES[STD_FOOTER] + '"></div>'
260     };
261
262     StdMod.prototype = {
263
264         /**
265          * Synchronizes the UI to match the Widgets standard module state.
266          * <p>
267          * This method is invoked after syncUI is invoked for the Widget class
268          * using YUI's aop infrastructure.
269          * </p>
270          * @method _syncUIStdMod
271          * @protected
272          */
273         _syncUIStdMod : function() {
274             this._uiSetStdMod(STD_HEADER, this.get(STD_HEADER + CONTENT_SUFFIX));
275             this._uiSetStdMod(STD_BODY, this.get(STD_BODY + CONTENT_SUFFIX));
276             this._uiSetStdMod(STD_FOOTER, this.get(STD_FOOTER + CONTENT_SUFFIX));
277             this._uiSetFillHeight(this.get(FILL_HEIGHT));
278         },
279
280         /**
281          * Creates/Initializes the DOM for standard module support.
282          * <p>
283          * This method is invoked after renderUI is invoked for the Widget class
284          * using YUI's aop infrastructure.
285          * </p>
286          * @method _renderUIStdMod
287          * @protected
288          */
289         _renderUIStdMod : function() {
290             this._stdModNode.addClass(Widget.getClassName(STDMOD));
291         },
292
293         /**
294          * Binds event listeners responsible for updating the UI state in response to 
295          * Widget standard module related state changes.
296          * <p>
297          * This method is invoked after bindUI is invoked for the Widget class
298          * using YUI's aop infrastructure.
299          * </p>
300          * @method _bindUIStdMod
301          * @protected
302          */
303         _bindUIStdMod : function() {
304             this.after(HeaderChange, this._afterHeaderChange);
305             this.after(BodyChange, this._afterBodyChange);
306             this.after(FooterChange, this._afterFooterChange);
307
308             this.after(FillHeightChange, this._afterFillHeightChange);
309             this.after(HeightChange, this._fillHeight);            
310             this.after(ContentUpdate, this._fillHeight);
311         },
312
313         /**
314          * Default attribute change listener for the headerContent attribute, responsible
315          * for updating the UI, in response to attribute changes.
316          *
317          * @method _afterHeaderChange
318          * @protected
319          * @param {EventFacade} e The event facade for the attribute change
320          */
321         _afterHeaderChange : function(e) {
322             if (e.src !== UI) {
323                 this._uiSetStdMod(STD_HEADER, e.newVal, e.stdModPosition);
324             }
325         },
326
327         /**
328          * Default attribute change listener for the bodyContent attribute, responsible
329          * for updating the UI, in response to attribute changes.
330          *
331          * @method _afterBodyChange
332          * @protected
333          * @param {EventFacade} e The event facade for the attribute change
334          */
335         _afterBodyChange : function(e) {
336             if (e.src !== UI) {
337                 this._uiSetStdMod(STD_BODY, e.newVal, e.stdModPosition);
338             }
339         },
340
341         /**
342          * Default attribute change listener for the footerContent attribute, responsible
343          * for updating the UI, in response to attribute changes.
344          *
345          * @method _afterFooterChange
346          * @protected
347          * @param {EventFacade} e The event facade for the attribute change
348          */
349         _afterFooterChange : function(e) {
350             if (e.src !== UI) {
351                 this._uiSetStdMod(STD_FOOTER, e.newVal, e.stdModPosition);
352             }
353         },
354
355         /**
356          * Default attribute change listener for the fillHeight attribute, responsible
357          * for updating the UI, in response to attribute changes.
358          * 
359          * @method _afterFillHeightChange
360          * @protected
361          * @param {EventFacade} e The event facade for the attribute change
362          */
363         _afterFillHeightChange: function (e) {
364             this._uiSetFillHeight(e.newVal);
365         },
366
367         /**
368          * Default validator for the fillHeight attribute. Verifies that the 
369          * value set is a valid section specifier - one of WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER,
370          * or a falsey value if fillHeight is to be disabled.
371          *
372          * @method _validateFillHeight
373          * @protected
374          * @param {String} val The section which should be setup to fill height, or false/null to disable fillHeight
375          * @return true if valid, false if not
376          */
377         _validateFillHeight : function(val) {
378             return !val || val == StdMod.BODY || val == StdMod.HEADER || val == StdMod.FOOTER;    
379         },
380
381         /**
382          * Updates the rendered UI, to resize the provided section so that the standard module fills out 
383          * the specified widget height. Note: This method does not check whether or not a height is set 
384          * on the Widget.
385          * 
386          * @method _uiSetFillHeight
387          * @protected
388          * @param {String} fillSection A valid section specifier - one of WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER
389          */
390         _uiSetFillHeight : function(fillSection) {
391             var fillNode = this.getStdModNode(fillSection);
392             var currNode = this._currFillNode;
393
394             if (currNode && fillNode !== currNode){
395                 currNode.setStyle(HEIGHT, EMPTY);
396             }
397
398             if (fillNode) {
399                 this._currFillNode = fillNode;
400             }
401
402             this._fillHeight();
403         },
404
405         /**
406          * Updates the rendered UI, to resize the current section specified by the fillHeight attribute, so
407          * that the standard module fills out the Widget height. If a height has not been set on Widget,
408          * the section is not resized (height is set to "auto").
409          * 
410          * @method _fillHeight
411          * @private
412          */
413         _fillHeight : function() {
414             if (this.get(FILL_HEIGHT)) {
415                 var height = this.get(HEIGHT);
416                 if (height != EMPTY && height != AUTO) {
417                     this.fillHeight(this._currFillNode);    
418                 }
419             }
420         },
421
422         /**
423          * Updates the rendered UI, adding the provided content (either an HTML string, or node reference),
424          * to the specified section. The content is either added before, after or replaces existing content
425          * in the section, based on the value of the <code>where</code> argument.
426          * 
427          * @method _uiSetStdMod
428          * @protected
429          * 
430          * @param {String} section The section to be updated. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER. 
431          * @param {String | Node} content The new content (either as an HTML string, or Node reference) to add to the section
432          * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE.
433          * If not provided, the content will replace existing content in the section.
434          */
435         _uiSetStdMod : function(section, content, where) {
436             if (content) {
437                 var node = this.getStdModNode(section) || this._renderStdMod(section);
438                 if (content instanceof Node || content instanceof NodeList) {
439                     this._addNodeRef(node, content, where);
440                 } else {
441                     this._addNodeHTML(node, content, where);
442                 }
443                 this.set(section + CONTENT_SUFFIX, this._getStdModContent(section), {src:UI});
444                 this.fire(ContentUpdate);
445             }
446         },
447
448         /**
449          * Creates the DOM node for the given section, and inserts it into the correct location in the contentBox.
450          *
451          * @method _renderStdMod
452          * @protected
453          * @param {String} section The section to create/render. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
454          * @return {Node} A reference to the added section node
455          */
456         _renderStdMod : function(section) {
457
458             var contentBox = this.get(CONTENT_BOX),
459                 sectionNode = this._findStdModSection(section);
460
461             if (!sectionNode) {
462                 sectionNode = this._getStdModTemplate(section);
463             }
464
465             this._insertStdModSection(contentBox, section, sectionNode);
466
467             this[section + NODE_SUFFIX] = sectionNode;
468             return this[section + NODE_SUFFIX];
469         },
470
471         /**
472          * Helper method to insert the Node for the given section into the correct location in the contentBox.
473          *
474          * @method _insertStdModSection
475          * @private
476          * @param {Node} contentBox A reference to the Widgets content box.
477          * @param {String} section The section to create/render. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
478          * @param {Node} sectionNode The Node for the section.
479          */
480         _insertStdModSection : function(contentBox, section, sectionNode) {
481             var fc = contentBox.get(FIRST_CHILD);
482
483             if (section === STD_FOOTER || !fc) {
484                 contentBox.appendChild(sectionNode);
485             } else {
486                 if (section === STD_HEADER) {
487                     contentBox.insertBefore(sectionNode, fc);
488                 } else {
489                     // BODY
490                     var footer = this[STD_FOOTER + NODE_SUFFIX];
491                     if (footer) {
492                         contentBox.insertBefore(sectionNode, footer);
493                     } else {
494                         contentBox.appendChild(sectionNode);
495                     }
496                 }
497             }
498         },
499
500         /**
501          * Gets a new Node reference for the given standard module section, by cloning
502          * the stored template node.
503          *
504          * @method _getStdModTemplate
505          * @protected
506          * @param {String} section The section to create a new node for. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
507          * @return {Node} The new Node instance for the section
508          */
509         _getStdModTemplate : function(section) {
510             return Node.create(StdMod.TEMPLATES[section], this._stdModNode.get(OWNER_DOCUMENT));
511         },
512
513         /**
514          * Helper method to add the given HTML string to the node reference provided.
515          * The HTML is added either before, after or replaces the existing node content 
516          * based on the value of the <code>where</code> argument.
517          *
518          * @method _addNodeHTML
519          * @private
520          * 
521          * @param {Node} node The section Node to be updated.
522          * @param {String} html The new content HTML string to be added to the section Node.
523          * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE.
524          * If not provided, the content will replace Nodes existing content.
525          */
526         _addNodeHTML : function(node, html, where) {
527             if (where == AFTER) {
528                 node.set(INNER_HTML, node.get(INNER_HTML) + html);
529             } else if (where == BEFORE) {
530                 node.set(INNER_HTML, html + node.get(INNER_HTML));
531             } else {
532                 node.set(INNER_HTML, html);
533             }
534         },
535
536         /**
537          * Helper method to add nodes, to another node.
538          * The child node(s) are added either before, after or replaces the existing node content 
539          * based on the value of the <code>where</code> argument.
540          * 
541          * @method _addNodeRef
542          * @private
543          * 
544          * @param {Node} node The section Node to be updated.
545          * @param {Node|NodeList} children The new content Node, or NodeList to be added to section Node provided.
546          * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE.
547          * If not provided, the content will replace existing content in the Node.
548          */
549         _addNodeRef : function(node, children, where) {
550             var append = true, 
551                 i, s;
552             
553             if (where == BEFORE) {
554                 var n = node.get(FIRST_CHILD);
555                 if (n) {
556                     if (children instanceof NodeList) {
557                         for (i = children.size() - 1; i >=0; --i) {
558                             node.insertBefore(children.item(i), n);
559                         }
560                     } else {
561                         node.insertBefore(children, n);
562                     }
563                     append = false;
564                 }
565             } else if (where != AFTER) { // replace
566                 node.set(INNER_HTML, EMPTY);
567             }
568
569             if (append) {
570                 if (children instanceof NodeList) {
571                     for (i = 0, s = children.size(); i < s; ++i) {
572                         node.appendChild(children.item(i));
573                     }
574                 } else {
575                     node.appendChild(children);
576                 }
577             }
578         },
579
580         /**
581          * Helper method to obtain the precise height of the node provided, including padding and border.
582          * The height could be a sub-pixel value for certain browsers, such as Firefox 3.
583          *
584          * @method _getPreciseHeight
585          * @private
586          * @param {Node} node The node for which the precise height is required.
587          * @return {Number} The height of the Node including borders and padding, possibly a float.
588          */
589         _getPreciseHeight : function(node) {
590             var height = (node) ? node.get(OFFSET_HEIGHT) : 0,
591                 getBCR = "getBoundingClientRect";
592
593             if (node && node.hasMethod(getBCR)) {
594                 var preciseRegion = node.invoke(getBCR);
595                 if (preciseRegion) {
596                     height = preciseRegion.bottom - preciseRegion.top;
597                 }
598             }
599
600             return height;
601         },
602
603         /**
604          * Helper method to query the rendered contents of the contentBox to find the
605          * node for the given section if it exists.
606          * 
607          * @method _findStdModSection
608          * @private
609          * @param {String} section The section for which the render Node is to be found. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
610          * @return {Node} The rendered node for the given section, or null if not found.
611          */
612         _findStdModSection: function(section) {
613             return this.get(CONTENT_BOX).query("> ." + StdMod.SECTION_CLASS_NAMES[section]);
614         },
615
616         /**
617          * Utility method, used by WidgetStdMods HTML_PARSER implementation
618          * to extract data for each section from markup.
619          *
620          * @method _parseStdModHTML
621          * @private
622          * @param {String} section
623          * @return {String} Inner HTML string with the contents of the section
624          */
625         _parseStdModHTML : function(section) {
626             var node = this._findStdModSection(section),
627                 docFrag, children;
628
629             if (node) {
630                 docFrag = node.get(OWNER_DOCUMENT).invoke(CREATE_DOCUMENT_FRAGMENT);
631                 children = node.get(CHILD_NODES);
632
633                 for (var i = children.size() - 1; i >= 0; i--) {
634                     var fc = docFrag.get(FIRST_CHILD);
635                     if (fc) {
636                         docFrag.insertBefore(children.item(i), fc);
637                     } else {
638                         docFrag.appendChild(children.item(i));
639                     }
640                 }
641
642                 return docFrag;
643             }
644
645             return null;
646         },
647
648         /**
649          * Retrieves the child nodes (content) of a standard module section
650          * 
651          * @method _getStdModContent
652          * @private
653          * @param {String} section The standard module section whose child nodes are to be retrieved. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
654          * @return {Node} The child node collection of the standard module section.
655          */
656         _getStdModContent : function(section) {
657             return (this[section + NODE_SUFFIX]) ? this[section + NODE_SUFFIX].get(CHILD_NODES) : null;
658         },
659
660         /**
661          * Updates the body section of the standard module with the content provided (either an HTML string, or node reference).
662          * <p>
663          * This method can be used instead of the corresponding section content attribute if you'd like to retain the current content of the section,
664          * and insert content before or after it, by specifying the <code>where</code> argument.
665          * </p>
666          * @method setStdModContent
667          * @param {String} section The standard module section whose content is to be updated. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
668          * @param {String | Node} content The content to be added, either an HTML string or a Node reference.
669          * @param {String} where Optional. Either WidgetStdMod.AFTER, WidgetStdMod.BEFORE or WidgetStdMod.REPLACE.
670          * If not provided, the content will replace existing content in the section.
671          */
672         setStdModContent : function(section, content, where) {
673             this.set(section + CONTENT_SUFFIX, content, {stdModPosition:where});
674         },
675
676         /**
677          * Returns the node reference for the given section. Note: The DOM is not queried for the node reference. The reference
678          * stored by the widget instance is returned if set.
679          * 
680          * @method getStdModNode
681          * @param {String} section The section whose node reference is required. Either WidgetStdMod.HEADER, WidgetStdMod.BODY or WidgetStdMod.FOOTER.
682          * @return {Node} The node reference for the section, or null if not set.
683          */
684         getStdModNode : function(section) {
685             return this[section + NODE_SUFFIX] || null;
686         },
687
688         /**
689          * Sets the height on the provided header, body or footer element to 
690          * fill out the height of the Widget. It determines the height of the 
691          * widgets bounding box, based on it's configured height value, and 
692          * sets the height of the provided section to fill out any 
693          * space remaining after the other standard module section heights 
694          * have been accounted for.
695          * 
696          * <p><strong>NOTE:</strong> This method is not designed to work if an explicit 
697          * height has not been set on the Widget, since for an "auto" height Widget, 
698          * the heights of the header/body/footer will drive the height of the Widget.</p>
699          *
700          * @method fillHeight
701          * @param {Node} node The node which should be resized to fill out the height
702          * of the Widget bounding box. Should be a standard module section node which belongs
703          * to the widget.
704          */
705         fillHeight : function(node) {
706             if (node) {
707                 var boundingBox = this.get(BOUNDING_BOX),
708                     stdModNodes = [this.headerNode, this.bodyNode, this.footerNode],
709                     stdModNode,
710                     total = 0,
711                     filled = 0,
712                     remaining = 0,
713                     validNode = false;
714
715                 for (var i = 0, l = stdModNodes.length; i < l; i++) {
716                     stdModNode = stdModNodes[i];
717                     if (stdModNode) {
718                         if (stdModNode !== node) {
719                             filled += this._getPreciseHeight(stdModNode);
720                         } else {
721                             validNode = true;
722                         }
723                     }
724                 }
725
726                 if (validNode) {
727                     if (UA.ie || UA.opera) {
728                         // Need to set height to 0, to allow height to be reduced
729                         node.setStyle(HEIGHT, 0 + PX);
730                     }
731
732                     total = parseInt(boundingBox.getComputedStyle(HEIGHT), 10);
733                     if (L.isNumber(total)) {
734                         remaining = total - filled;
735
736                         if (remaining >= 0) {
737                             node.setStyle(HEIGHT, remaining + PX);
738                         }
739
740                         // Re-adjust height if required, to account for el padding and border
741                         var offsetHeight = this.get(CONTENT_BOX).get(OFFSET_HEIGHT); 
742                         if (offsetHeight != total) {
743                             remaining = remaining - (offsetHeight - total);
744                             node.setStyle(HEIGHT, remaining + PX);
745                         }
746                     }
747                 }
748             }
749         }
750     };
751
752     Y.WidgetStdMod = StdMod;
753
754
755 }, '3.0.0' ,{requires:['widget']});