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