YUI 3: Widget [beta]
Widget is the foundation class from which all YUI 3 widgets are derived. It provides the following pieces of core functionality on top of what Base already provides:
- The
renderlifecycle method, in addition to theinitanddestroylifecycle methods provided by Base - Abstract rendering methods to support a consistent MVC structure across widgets
- A common set of base widget attributes
- Consistent class-name generation support
More Information
- Examples: Widget Utility in action.
- API Documentation: View the full API documentation for the Widget Utility.
- Download: Widget Utility as part of the full YUI Library.
- Free Hosting on our fast edge servers with combo-loading.
- License: BSD.
Getting Started
Include Dependencies
The easiest way to include the source files for Widget and its dependencies is to add the YUI seed file to your page, using the following script tag, and allow the YUI instance to download any additional files which may be required:
The YUI instance will automatically pull down Widget's source files and any missing dependencies when the widget module is used. This helps you avoid having to manually manage the list of files needed on your page to support multiple components while also optimizing your initial page weight by loading files only when they are required.
If you do want to include file dependencies manually on your page, the YUI Dependency Configurator can be used to determine the list of files you need to include in order to use Widget.
The YUI Instance
Once you have the YUI seed file on your page (yui-min.js), you can
create a new YUI instance for your application to use and populate it
with the modules you need, specified as the first set of arguments to the
use method:
The last argument passed to use is a callback function. The callback function will be invoked as soon as the YUI instance is done downloading any required files missing from your page. Once those files are loaded, your local YUI instance will be supplemented with the classes which make up the widget module and any modules it depends on. A reference to the populated YUI instance (Y) is passed back to your callback function. Within your callback, then, you can start writing your application code based on your own custom instance of YUI.
For more information on creating instances of YUI and the
use method, see the
YUI Global object documentation.
Working With Widget Utility
This section describes the functionality Widget Utility provides in further detail. It contains these subsections:
- Class Structure And Responsibilities
- Basic Attributes
- Rendering Methods
- Progressive Enhancement
- Markup Structure
- Class Names and CSS
- Extending Widget
Class Structure And Responsibilities
Widget provides the foundation class on which all YUI 3 widgets will be built.
Although instantiable and usable by itself, it is designed to be extended, to create widgets which address
specific user interaction patterns.
The Widget class extends Base. Therefore it provides
the same Attribute, Event.Provider and Plugin.Host support as Base.
It adds the following core functionality:
- Basic Attributes
- It introduces the base set of attributes that will be available on any widget.
For example,
boundingBox,contentBox,width,height,visible,focusedanddisabled. - Render Lifecycle Phase
- It adds the
renderlifecycle method (and event) to theinitanddestroylifecycle methods provided byBase. - Abstract Rendering Methods
- It establishes abstract methods
renderUI,bindUIandsyncUIto provide consistent entry points for rendering across all widgets. - Standard Progressive Enhancement
- It establishes a common entry point for Progressive Enhancement during widget initialization.
- String Localization
- Through the
stringsandlocaleattributes, provides client side string localization support. init(inherited fromBase):-
The
initmethod loops through the class hierarchy, top down (Base first, subclass last) and:- Configures attributes for each class, based on the class'
ATTRSstatic property. - Then, invokes the
initializermethod for the class.
The
initmethod fires aninitevent, which can be prevented to stop initialization from proceeding. - Configures attributes for each class, based on the class'
destroy(inherited fromBase):-
Invokes the
destructormethod for all classes in the widget hierarchy, bottom up (subclass first, Base last).The
destroymethod fires adestroyevent, which can be prevented to stop destruction from proceeding. render:-
Invokes the
renderermethod for the Widget instance. Unlike theinitializeranddestructor, this method is not chained automatically for the widget class hierarchy.The
rendermethod accepts a node argument, which can be used to define where in the document the widget should be appended. If the widget's contentBox or boundingBox don't already exist in the document, and this argument is not provided, the widget is rendered to the document's body element.The render method fires a
renderevent, which can be prevented to stop rendering from proceeding. renderUI- This method is responsible for creating and adding the nodes which the widget needs to the document (or modifying existing nodes, in the case of progressive enhancement). It is usually the point at which the DOM is first modified by the Widget.
bindUI- This method is responsible for attaching event listeners which bind the UI to the widget state. These listeners are generally attribute change listeners — used to update the state of the UI in response to changes in the attribute's value. It also attaches DOM event listeners to the nodes making up the UI to map user interactions to the Widget's API.
syncUI- This method is responsible for setting the initial state of the UI based on the current state of the widget at the time of rendering.
A class name identifying the widget type is added to the bounding box.
The default format for the class name is "yui-[widgetname]". For example, for Slider, the "yui-slider" class name is added to the bounding box.
Additionally, class names for all widget classes in the class hierarchy are also used to tag the bounding box.
For example, for a MultiThumbSlider, which may extend Slider, the bounding box is marked with the classes "yui-widget", "yui-slider" and "yui-multithumbslider" (this is the only place where we mark an element with class names for all widget classes in the hierarchy).
-
Class names used for state management by the widget instance are also applied to the bounding box.
The general format is "yui-[widgetname]-[state]". For example "yui-slider-hidden", "yui-slider-disabled".
-
The widget's width and height values are applied to the bounding box if set, as are top/left (xy) positioning values, for positioned widgets.
-
The bounding box is not expected to have any visual properties (e.g. borders, padding etc.) applied to it.
However it will have CSS defining how the widget impacts the document flow. For example, the bounding box type ("display:inline", "display:inline-block", "display:block") and the positioning scheme ("position:absolute", "position:relative")
-
The content box also has an identifying class name applied to it.
The default format is "yui-[widgetname]-content". For example "yui-slider-content".
Visual treatment for the widget is applied to the content box (e.g. borders, padding, background-color etc.).
-
For progressively enhanced solutions, generally the user will only provide what will be the content box on the page and pass it into the constructor as the
contentBox(rather than the bounding box).The bounding box will be added dynamically when the widget is instantiated. This maintains semantic value (the content box ends up containing existing content), and avoids unnecessary markup on the page up front.
- The nested structure allows the bounding box to act as a container for any additional decorator elements which need to be added for the widget. For example, elements to support rounded corners, shadows, or shimming. These can live as siblings of the content box, and can be positioned, and sized more efficiently since they have a common parent container.
- Additionally, due to the consistent structure across all widgets, generic plugins can be written to provide the above decorator support, which are re-usable across all widgets.
- Having a box without border and padding applied (the bounding box) allows for consistent width and height application across browser box model differences.
getClassName(arg1, arg2, arg3 ...)method (instance)-
This method can be used to create class names which begin with the configured prefix for application ("yui-") by default and the name of the widget (the
NAMEproperty, lowercase) For example:Note: The static
ClassNameManager.getClassName(arg1, arg2, arg3 ...)method can be used as a replacement for the above method, when class names need to be generated in a static context, by passing in the widget'sNAMEproperty as the first argument. For example: Widget.getClassName(arg1, arg2, arg3 ....)method (static)-
This static version of method (invoked directly on the widget class, as opposed the "this") can be used to create class names which begin with a constant widget prefix ("yui-widget"). This maybe useful for plugins, which need to ship with CSS which targets a fixed class name, regardless of the widget instance to which they are applied. For example:
Basic Attributes
Widget establishes the basic set of attributes which will be available in all YUI 3 widgets. The key attributes are discussed below:
| Attribute | Description |
|---|---|
boundingBox | The outermost node for the Widget, used for sizing and positioning of a Widget; this element can also serve as a containing element for any decorator elements used for skinning. |
contentBox | A node that is a direct descendent of a Widget's bounding box that houses its content. This node will generally be the node that establishes the look/feel for the widget and it will usually be set during construction for widgets built from markup. |
tabIndex | The tabIndex, applied to the bounding box. |
focused | Flag, indicating if the Widget currently has focus. Widget marks the bounding box with a "focused" class, but other than that the focus implementation is left to the specific widget class. |
disabled | Flag, indicating if the Widget is disabled. Widget marks the bounding box with a "disabled" class, but other than that the disabled implementation is left to the specific widget class. |
visible | Flag, indicating whether or not the Widget is visible. Widget marks the bounding box with a "hidden" class. The hidden implementation is left to the CSS delivered by the specific widget class (viz. whether or not the widget uses visibility, display or off screen positioning to actually hide the widget). |
height | String with units, or a number, representing the height of the Widget. If a number is provided, the default unit, defined by Widget's DEF_UNIT, property is used. The height is applied to the bounding box. |
width | String with units, or a number, representing the width of the Widget. If a number is provided, the default unit, defined by Widget's DEF_UNIT, property is used. The width is applied to the bounding box. |
strings | Localizable collection of strings used to label elements of the Widget's UI. |
locale | The current locale in which strings should be displayed. NOTE: Using get/set on the "strings" attribute will return/set strings for this locale. |
Rendering Methods
Widget adds the render method/lifecycle phase to the
init and destroy phases established by Base.
The render method establishes the point at which the Widget lays down its UI by adding elements to (or modifying existing elements in) the DOM and
setting up listeners to activate that UI. Having a distinct rendering phase promotes Widget classes that separate state and corresponding logic
from the way the Widget UI is displayed. This separation tends to allow the Widget's state to be safely modified and queried before it is displayed or rendered to the DOM.
Additionally, this separation of concerns leads to code being split into methods that manipulate the widget's state or handle core "app" logic versus methods which work with the DOM. Following this practice makes it easier to customize (and test) one area or the other.
The Lifecycle Methods: init, destroy, render
As with init and destroy, the render method on Widget is final and delegates to the
widget's renderer method to perform the actual rendering work:
Widget's renderer Method
Widget provides a renderer method implementation, which for most simple widgets will not need to be over-ridden.
This renderer method is shown below:
The renderUI, bindUI and syncUI are abstract (empty) methods in the Widget class which attempt to establish a common pattern for widget development.
The intended role of each of these methods is described below, and most widgets will simply implement these methods based on their expected roles:
Progressive Enhancement
The Widget class establishes a standard entry point for widgets that need to provide support for Progressive Enhancement; this entry point is provided in the form of an HTML_PARSER property on each class.
HTML_PARSER is a static property, used to define an object (used as an associative array) of selectors or functions that are responsible for (a) parsing content for the widget from existing DOM elements and (b) extracting attribute configuration values for use during initialization.
The HTML_PARSER property is evaluated when the Widget class' initializer method is invoked (so Widget sub-classes receive the configuration
object passed in to the constructor). The object is iterated, to create a filled out configuration object for the Widget, based on the content found on the page. For example
the parser definition above, may lead to the following object literal when evaluated:
{
titleNode: NodeRef,
itemNodes: NodeRef (multiple nodes),
label: "My Widget",
xValue: "10",
yValue: "20"
}
This object is merged with the user configuration object passed into the constructor (markup can be thought of as alternate source/format for configuration data), with the configuration object passed to the widget constructor taking precedence if a value for an attribute is found in both place.
Rendered Markup
The Widget class establishes a common markup format for all widgets, through its boundingBox and
contentBox attributes.
All widgets will have a bounding box wrapping a content box. They are both DIVs by default but can be customized for a widget by overriding the BOUNDING_TEMPLATE and CONTENT_TEMPLATE prototype properties. References
to existing nodes in the document (or a selector string which can be used to obtain them) can be passed to the constructor using the contentBox and boundingBox attributes, as can references to newly created nodes not currently in the document.
The widget will create either of the nodes if they are not provided in the constructor, and add them to the document when the widget's render method is called.
As mentioned previously, if the render method is passed a node reference(#parentNode in the snippet above), the widget's bounding box is appended to that node if it is not already a child.
The Bounding Box
The bounding box is the outermost element owned by the widget and is used for functional, rather than visual, purposes.
The Content Box
The content box is a child of the bounding box. The widget will add the elements which make up its core UI inside the content box.
Widget Markup Diagram
The following illustration demonstrates how the markup and class names for a widget's bounding box and content box come together.
Why Two Nested Boxes?
Providing nested boxes for all widgets provides benefits for CSS application, decorative element support and bounding box dimension handling. These are detailed below:
Class Names and CSS
In order to provide consistent class names for use across all widgets, the Widget class provides two methods which are simple wrappers for the ClassNameManager utility, and leverage the NAME property defined for widget classes.
The ClassNameManager API documentation has details about how to configure the application prefix ("yui") and the default separator ("-") if required.
CSS Implications
Class names generated to reflect state will generally use the widget's name as a prefix. Widget does that for the classes it adds to the bounding box:
| Attribute/State | CSS Class Applied |
|---|---|
| visible | yui-[widgetname]-hidden |
| disabled | yui-[widgetname]-disabled |
| focused | yui-[widgetname]-focused |
In the above definitions, "[widgetname]" is the name of the widget instance (e.g. "menu", "overlay", "slider").
The widget name is combined with the state identifier so that different widgets can customize the way they handle visibility differently, and still work with IE6,
where multiple class name rules, like .yui-menu.yui-hidden are not well supported. For example:
However, providing an IE6-compatible format requires each widget to ship with the CSS rules defined for each of its states. Of the state-based rules above, all widgets will definitely end up providing a "yui-[widgetname]-hidden" implementation to control visibility. Whether or not the other two are provided is usually a function of whether or not the widget needs special UI handled for the "disabled" and "focused" states.
Extending Widget
The "Extending The Widget Class" example uses a concrete Spinner widget to cover the above concepts with functional code. It walks the developer through the step-by-step process involved in creating widget classes using a working Spinner as an example. This example provides the jumping off point for developing your own widgets.
Support & Community
Forums & Blog
YUI 3 discussion forums are hosted on YUILibrary.com.
In addition, please visit the YUIBlog for updates and articles about the YUI Library written by the library's developers.
Filing Bugs & Feature Requests
The YUI Library's public bug tracking and feature request repositories are located on the YUILibrary.com site. Before filing new feature requests or bug reports, please review our reporting guidelines.

