YUI 3: Overlay [beta]

Overlay is a positionable and stackable widget, which also provides support for the standard module format layout, with a header, body and footer section. The overlay is built by extending the Widget class and adding the WidgetPosition, WidgetStack, WidgetPositionExt and WidgetStdMod extensions, and doesn't actually need to add any implementation code of its own. The "Creating Custom Widget Classes" example shows how you can use these extensions to build classes which mix and match the above features.

For the current release, Overlay supports basic XY page positioning, alignment and centering relative to a node or the viewport, header, body, footer section support with Progressive Enhancement and zIndex with shimming support. Future versions will introduce support for event triggers to maintain alignment/centering, managed stacking (bring to top) and constrained positioning.

Getting Started

Include Dependencies

The easiest way to include the source files for Overlay 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:

  1. <script src="http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"></script>
<script src="http://yui.yahooapis.com/3.0.0/build/yui/yui-min.js"></script>

The YUI instance will automatically pull down Overlay's source files and any missing dependencies when the overlay 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 Overlay.

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:

  1. // Create new YUI instance, and populate it with the required modules
  2. YUI().use('overlay', function(Y) {
  3.  
  4. // Overlay available, and ready for use.
  5.  
  6. });
// Create new YUI instance, and populate it with the required modules
YUI().use('overlay', function(Y) {
 
    // Overlay available, and ready for use.
 
});

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 overlay 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.

Using the Overlay Widget

This section describes how to use the Overlay Widget in further detail. It contains these subsections:

Instantiating The Overlay

The Overlay widget extends the Widget class, and hence the Overlay constructor follows the same pattern as any Widget constructor, accepting a configuration object to set the initial configuration for the widget.

Instantiating From Markup: Progressive Enhancement

The overlay can be instantiated from markup, by specifying the contentBox which contains the header, body and footer content for the overlay:

  1. <div id="myContent">
  2. <div class="yui-widget-hd">Overlay Header</div>
  3. <div class="yui-widget-bd">Overlay Body</div>
  4. <div class="yui-widget-ft">Overlay Footer</div>
  5. </div>
  6.  
<div id="myContent">
    <div class="yui-widget-hd">Overlay Header</div>
    <div class="yui-widget-bd">Overlay Body</div>
    <div class="yui-widget-ft">Overlay Footer</div>
</div>
 

The header, body and footer sections provided in markup need to be marked with the class name which Overlay (or more accurately, WidgetStdMod) expects for the section ("yui-widget-hd", "yui-widget-bd" and "yui-widget-ft") as shown above. All of these sections are optional. If content is set via the API at a later point the corresponding section will be created dynamically.

When instantiating from markup, a reference to the contentBox is provided in the configuration object. This reference can be a node reference, or a selector string which can be used to identify the node. If the selector string is too broad (returns multiple nodes), the first node found will be used. The following code targets the markup shown above:

  1. YUI({...}).use("overlay", function(Y) {
  2.  
  3. //...
  4. var overlay = new Y.Overlay({
  5. // Specify a reference to a content box,
  6. // which already exists on the page and contains
  7. // header/body/footer content
  8. contentBox:"#myContent",
  9.  
  10. // Also set some of the attributes inherited from
  11. // the base Widget class.
  12. visible:false,
  13. width:"20em"
  14. });
  15. //...
  16.  
  17. });
  18.  
YUI({...}).use("overlay", function(Y) {
 
    //...
    var overlay = new Y.Overlay({
        // Specify a reference to a content box, 
        // which already exists on the page and contains
        // header/body/footer content
        contentBox:"#myContent",
 
        // Also set some of the attributes inherited from
        // the base Widget class.
        visible:false,
        width:"20em"
    });
    //...
 
});
 

Following instantiation, a call to render is required to have the Overlay's state reflected in the DOM, as with all YUI 3 widgets:

  1. var overlay = new Y.Overlay({ ... });
  2. overlay.render();
  3.  
var overlay = new Y.Overlay({ ... });
overlay.render();
 

Note that you could set the state of the Overlay multiple times (modifying content, changing dimensions etc.) before rendering. When the render method is invoked, the state of the Overlay at that point in time will be reflected in the DOM.

When render is invoked, the overlay's content box will be wrapped by the bounding box (another DIV), to provide the nested box structure common to all widgets.

Instantiating From Script

You can also create Overlay instances entirely from script, setting content programmatically, using the headerContent, bodyContent and footerContent attributes.

  1. var overlay = new Y.Overlay({
  2. headerContent:"My Overlay Header",
  3. bodyContent:"My Overlay Body",
  4. footerContent:"My Footer Content",
  5. //...
  6. });
  7. overlay.render("#parentNode");
  8.  
var overlay = new Y.Overlay({
    headerContent:"My Overlay Header",
    bodyContent:"My Overlay Body",
    footerContent:"My Footer Content",
    //...
});
overlay.render("#parentNode");
 

Content can be strings containing markup (innerHTML will be used to set the content), or Node references, in which case they will be appended to the section (header, body or footer) node.

The render method can be passed a node reference (or a selector string) as shown above, to specify the node under which the overlay's bounding box should be added to the DOM. When rendering an overlay instance which has not been created from markup (so it does not have a position in the DOM) if this argument is not provided the overlay will be added to the document's body element (inserted as the first child to avoid the potential for "operation aborted" errors in IE6).

Attributes

Overlay adds the following key attributes (through the extensions mentioned above), in addition to the attributes provided by the base Widget class:

AttributeDescription
x, y and xyPositioning attributes, to set the XY position in page co-ordinates on the Overlay's bounding box. Set to [0,0] by default
zIndexSets the z-index on the Overlay's bounding box. Set to 0 by default.
shimBoolean, indicating whether or not an iframe shim should be added to the Overlay to protect against select box bleed through. It is only enabled by default for IE6.
alignUsed to align a specific point on the Overlay's bounding box to a specific point on another node, or the viewport. Set to null by default.
centeredUsed to center the Overlay inside another node, or inside the viewport. Set to false by default.
headerContentUsed to set the content of the Overlay's header section. No default value set.
bodyContentUsed to set the content of the Overlay's body section. No default value set.
footerContentUsed to set the content of the Overlay's footer section. No default value set.
fillHeightSpecifies which of the 3 sections - header, body or footer, should be automatically sized to fill out the height of the Overlay, if a fixed height has been set. Set to WidgetStdMod.BODY by default. Can be disabled by setting to null.

Positioning

Basic XY Positioning

Overlay provides basic XY positioning support through its x, y and xy attributes as well as a convenience move method which wraps the xy attribute.

The xy position of the overlay can be set in the constructor, as with any attribute value:

  1. var overlay = new Y.Overlay({
  2. contentBox:"myContent",
  3. xy: [200,100]
  4. });
  5. overlay.render();
  6.  
  7. // or
  8.  
  9. var overlay = new Y.Overlay({
  10. contentBox:"myContent",
  11. x: 200,
  12. y: 100
  13. });
  14. overlay.render();
  15.  
  16. // or
  17.  
  18. var overlay = new Y.Overlay({
  19. contentBox:"myContent",
  20. x: 200 // y defaults to 0
  21. });
  22. overlay.render();
  23.  
var overlay = new Y.Overlay({
    contentBox:"myContent",
    xy: [200,100]
});
overlay.render();
 
// or
 
var overlay = new Y.Overlay({
    contentBox:"myContent",
    x: 200,
    y: 100
});
overlay.render();
 
// or
 
var overlay = new Y.Overlay({
    contentBox:"myContent",
    x: 200 // y defaults to 0
});
overlay.render();
 

The overlay's default position, if xy values are not provided, will be 0,0. Note that xy are page co-ordinates, not relative co-ordinates.

Changes in the overlay's position (when set programmatically through the API) can be monitored by listening for the attribute xyChange event. Listeners to this event will receive an event facade, which contains previous and new xy values:

  1. // Listen to the "on" moment, if you're interested in
  2. // preventing the change in position from occurring.
  3. overlay.on("xyChange", function(e) {
  4.  
  5. var currPosition = e.prevVal;
  6. var newPosition = e.newVal;
  7.  
  8. if (newPosition[0] > MAX_X || newPosition[1] > MAX_Y) {
  9. // Stop move from occurring.
  10. e.preventDefault();
  11. }
  12. });
  13.  
  14. // Listen to the "after" moment, if you're just interested
  15. // in being notified when the position has been changed.
  16. overlay.after("xyChange", function(e) {
  17. var position = e.newVal;
  18. console.log("Overlay has been moved to: " + position[0] + "," position[1]);
  19. });
  20.  
// Listen to the "on" moment, if you're interested in
// preventing the change in position from occurring.
overlay.on("xyChange", function(e) {
 
    var currPosition = e.prevVal;
    var newPosition = e.newVal;
 
    if (newPosition[0] > MAX_X || newPosition[1] > MAX_Y) {
        // Stop move from occurring. 
        e.preventDefault();
    }
});
 
// Listen to the "after" moment, if you're just interested 
// in being notified when the position has been changed.
overlay.after("xyChange", function(e) {
    var position = e.newVal;
    console.log("Overlay has been moved to: " + position[0] + "," position[1]);
});
 

Note that changing just the x or y attribute value, individually, will still fire the xy change event. The x and y attribute values are simply convenience wrappers which end up setting the xy attribute.

XY position can also be set after construction, as with any attribute, using set to change the attribute value directly, or using the move method:

  1. overlay.set("x", 100);
  2.  
  3. overlay.set("y", 200);
  4.  
  5. overlay.set("xy", [100,200]);
  6.  
  7. overlay.move(100,200);
  8.  
  9. overlay.move([100,200]);
  10.  
overlay.set("x", 100);
 
overlay.set("y", 200);
 
overlay.set("xy", [100,200]);
 
overlay.move(100,200);
 
overlay.move([100,200]);
 

The Basic XY Positioning example shows basic positioning in action.

Extended XY Positioning

Overlay also provides support to help position it relative to another node on the page, or the viewport, through the align and centered attributes, as well as the corresponding align() and centered() convenience methods, through the application of the WidgetPositionExt extension.

The align attribute accepts as a value an object literal with the following properties:

node
The node to which the Widget is to be aligned. If set to null, or not provided, the Overlay is aligned to the viewport
points

A two element array, defining the two points on the Overlay and node which are to be aligned. The first element is the point on the Overlay, and the second element is the point on the node (or viewport). Supported alignment points are defined as static properties on WidgetPositionExt.

e.g. [Y.WidgetPositionExt.TR, Y.WidgetPositionExt.TL] aligns the Top-Right corner of the Overlay with the Top-Left corner of the node/viewport, and [Y.WidgetPositionExt.CC, Y.WidgetPositionExt.TC] aligns the Center of the Overlay with the Top-Center edge of the node/viewport.

  1. // Align the:
  2. // top-left corner of the overlay, with the
  3. // top-right corner of the node with id = "okBtn"
  4. overlay.set("align", {
  5. node:"#okBtn",
  6. points:[Y.WidgetPositionExt.TL, Y.WidgetPositionExt.TR]
  7. });
  8.  
  9. // Align the:
  10. // right-center edge of the overlay, with the
  11. // right-center edge of the viewport (no node specified)
  12. overlay.set("align", {
  13. points:[Y.WidgetPositionExt.RC, Y.WidgetPositionExt.RC]
  14. });
  15.  
  16. // Align the:
  17. // center of the overlay, with the
  18. // top-left corner of the node with id = "okBtn"
  19. overlay.align("#okBtn", [Y.WidgetPostionExt.CC, Y.WidgetPositionExt.TL]);
  20.  
// Align the:
// top-left corner of the overlay, with the 
// top-right corner of the node with id = "okBtn"
overlay.set("align", {
    node:"#okBtn",
    points:[Y.WidgetPositionExt.TL, Y.WidgetPositionExt.TR]
});
 
// Align the:
// right-center edge of the overlay, with the 
// right-center edge of the viewport (no node specified)
overlay.set("align", {
    points:[Y.WidgetPositionExt.RC, Y.WidgetPositionExt.RC]
});
 
// Align the:
// center of the overlay, with the 
// top-left corner of the node with id = "okBtn"
overlay.align("#okBtn", [Y.WidgetPostionExt.CC, Y.WidgetPositionExt.TL]);
 

The centered property can either by set to true to center the Overlay in the viewport, or set to a selector string or node reference to center the Overlay in a particular node.

  1. // Center the overlay in the node with id = "module"
  2. overlay.set("centered", "#module");
  3.  
  4. // Center the overlay in the viewport
  5. overlay.set("centered", true);
  6.  
// Center the overlay in the node with id = "module"
overlay.set("centered", "#module");
 
// Center the overlay in the viewport
overlay.set("centered", true);
 

The "Extended XY Positioning" example shows extended positioning in action.

Note that currently alignment/centering is not maintained when the viewport is scrolled, window resized etc. Support to re-align the overlay on a default and custom set of trigger events will be provided in a future release.

Stacking

The Overlay provides basic stacking support in the form of a zIndex attribute and a shim attribute. The shimming support protects against <select> box bleed through on IE6 (It is enabled by default for IE6) by adding an iframe shim to the overlay's bounding box (positioned underneath the content box). The default value of the zIndex attribute is 0.

Using the zIndex and shim attributes is the same as any other attribute, with the ability to set values in the constructor, or at a later point in time:

  1. // Disable shim for all browsers, set zIndex to 10
  2. var overlay = new Y.Overlay({
  3. shim:false, // Disable for all browsers, including IE6
  4. zIndex:10
  5. });
  6.  
  7. // Set zIndex to 10. Shim is enabled for IE6 but disabled for all
  8. // other browsers (default value)
  9. var overlay = new Y.Overlay({
  10. zIndex:10
  11. });
  12.  
// Disable shim for all browsers, set zIndex to 10
var overlay = new Y.Overlay({
    shim:false, // Disable for all browsers, including IE6
    zIndex:10
});
 
// Set zIndex to 10. Shim is enabled for IE6 but disabled for all
// other browsers (default value)
var overlay = new Y.Overlay({
    zIndex:10
});
 

The "Stack Support" example creates a simple "bringToTop" implementation based on the zIndex attribute. This support will be provided as part of Overlay itself (or more precisely, as part of WidgetStack) in a future release.

Setting Section Content

Overlay uses the standard module format for its rendering. It provides a header, body and footer section as described above (through the WidgetStdMod extension).

Replacing Content

The content for each of these sections is settable either through the headerContent, bodyContent and footerContent attributes. Setting the content through these properties will replace any existing content in the section. The content can either be specified as a string, in which case innerHTML will be used to set the new content, or specified as a Node instance, in which case the content will be added to the respective section using appendChild after clearing existing content.

  1. var overlay = new Y.Overlay({
  2. headerContent: '<span class="title">My Header Content</span>',
  3. bodyContent: '<div class="mod">My Body Content</div>'
  4. // Don't want a footer
  5. });
  6.  
  7. // or
  8.  
  9. overlay.set("headerContent", '<span class="title">My Header Content</span>');
  10.  
  11. // or
  12.  
  13. var headerContent = Y.Node.create("<span></span>");
  14. headerContent.set("innerHTML", "My Header Content");
  15. headerContent.addClass("title");
  16.  
  17. overlay.set("headerContent", headerContent);
  18.  
var overlay = new Y.Overlay({
    headerContent: '<span class="title">My Header Content</span>',
    bodyContent: '<div class="mod">My Body Content</div>'
    // Don't want a footer
});
 
// or 
 
overlay.set("headerContent", '<span class="title">My Header Content</span>');
 
// or 
 
var headerContent = Y.Node.create("<span></span>");
headerContent.set("innerHTML", "My Header Content");
headerContent.addClass("title"); 
 
overlay.set("headerContent", headerContent);
 

Overlay will not create the section if there has been no content set for it. (So, for example, the overlay above will not have a footer section). Also, if the section doesn't exist it will be created, the first time content is set for it.

As with any attribute change, you can listen for (and prevent) changes in content by listening for the corresponding attribute change event:

  1. overlay.on("bodyContentChange", function(e) {
  2. if (someCondition) {
  3. // Don't allow body content to be updated
  4. e.preventDefault():
  5. }
  6. });
  7.  
  8. overlay.after("bodyContentChange", function(e) {
  9. // body section has been modified
  10. });
  11.  
overlay.on("bodyContentChange", function(e) {
    if (someCondition) {
        // Don't allow body content to be updated
        e.preventDefault():
    }
});
 
overlay.after("bodyContentChange", function(e) {
    // body section has been modified
});
 

Setting content in any of the sections will fire Widget's contentUpdate event, which can be monitored if you want to be notified of changes to any section, however this event is purely a catch-all notification event. It cannot be prevented to stop the content change from occurring:

  1. overlay.after("contentUpdate", function(e) {
  2. // Content has been updated in one of the standard module sections.
  3. });
  4.  
overlay.after("contentUpdate", function(e) {
    // Content has been updated in one of the standard module sections.
});
 
Inserting/Appending Content

Setting content using the attributes mentioned above always results in content being replaced. If you need to insert content before, or append content after, existing content in the section, you can use the setStdModContent(section, content, where) method Overlay provides:

  1. overlay.setStdModContent(
  2. Y.WidgetStdMod.HEADER, // Section
  3. "New Content To Insert", // Content
  4. Y.WidgetStdMod.BEFORE // Where
  5. );
  6.  
  7. overlay.setStdModContent(
  8. Y.WidgetStdMod.FOOTER, // Section
  9. "New Content To Append", // Content
  10. Y.WidgetStdMod.AFTER // Where
  11. );
  12.  
overlay.setStdModContent(
    Y.WidgetStdMod.HEADER,       // Section
    "New Content To Insert",   // Content
    Y.WidgetStdMod.BEFORE        // Where
);
 
overlay.setStdModContent(
    Y.WidgetStdMod.FOOTER,      // Section
    "New Content To Append",  // Content
    Y.WidgetStdMod.AFTER        // Where
);
 
  • The section argument specifies which section is to be updated. The constants WidgetStdMod.HEADER, WidgetStdMod.BODY and WidgetStdMod.FOOTER define valid values.
  • The content argument specifies the new content to be added, which, as with the attributes can be a string HTML value or a node reference.
  • The where argument specifies whether the content should be added before, after or replace existing content. The constants WidgetStdMod.BEFORE, WidgetStdMod.AFTER and WidgetStdMod.REPLACE

    define valid values.

Note, the above WidgetStdMod constants define the set of valid values wherever the API expects a "section" or "where" argument.

The content change events mentioned above, will be fired when content is set through the setStdModContent method just as they would when setting the content using the attribute.

The Standard Module example provides a way to exercise the above content attributes and methods.

Markup Structure

The final rendered Overlay has the markup structure shown below:

  1. <div class="yui-widget yui-overlay yui-widget-positioned yui-widget-stacked">
  2. <!--Bounding Box-->
  3. <div class="yui-overlay-content yui-widget-stdmod">
  4. <!--Content Box-->
  5. <div class="yui-widget-hd">Overlay Header Content</div>
  6. <!--Header Section-->
  7. <div class="yui-widget-bd">Overlay Body Content</div>
  8. <!--Body Section-->
  9. <div class="yui-widget-ft">Overlay Footer Content</div>
  10. <!--Footer Section-->
  11. </div>
  12.  
  13. <iframe class="yui-widget-shim"></iframe>
  14. <!-- Stacking shim, if enabled-->
  15.  
  16. </div>
  17.  
<div class="yui-widget yui-overlay yui-widget-positioned yui-widget-stacked">
    <!--Bounding Box-->
    <div class="yui-overlay-content yui-widget-stdmod">
    <!--Content Box-->
        <div class="yui-widget-hd">Overlay Header Content</div>
            <!--Header Section-->
        <div class="yui-widget-bd">Overlay Body Content</div>
            <!--Body Section-->
        <div class="yui-widget-ft">Overlay Footer Content</div>
            <!--Footer Section-->
    </div>
 
    <iframe class="yui-widget-shim"></iframe>
        <!-- Stacking shim, if enabled-->
 
</div>
 

The bounding box is absolutely positioned by default, and top/left positioning and z-index values are applied to it. The nested bounding box/content box structure is discussed in detail on the Widget markup discussion.

In addition to the default classes applied to the bounding box and content box for all widgets ("yui-overlay", "yui-overlay-content", "yui-widget"), the WidgetStdMod, WidgetPositioned and WidgetStack extensions also mark the appropriate boxes with "yui-widget-stdmod", "yui-widget-positioned" and "yui-widget-stacked" classes as shown above.

The iframe shim, added if shim is enabled, is added to the bounding box, as sibling to the content box and stacked underneath it (using a -ve z-index).

CSS

Overlay is a generic, foundation widget and doesn't ship with a default look/feel out of the box. Its Sam Skin (build/overlay/assets/skins/sam/overlay.css) implementation consists only of core functional rules, to control how it is positioned and how it is hidden:

  1. .yui-overlay {
  2. position:absolute;
  3. }
  4.  
  5. .yui-overlay-hidden {
  6. visibility:hidden
  7. }
  8.  
.yui-overlay {
    position:absolute;
}
 
.yui-overlay-hidden {
    visibility:hidden
}
 

Since it includes the WidgetStack extension, the following functional CSS is also provided (through build/widget/assets/skins/sam/widget-stack.css) to handle the shim element, (along with the Gecko/Mac scroll bar support CSS mentioned above)

  1. .yui-widget-stacked .yui-widget-shim {
  2. opacity: 0;
  3. filter: alpha(opacity=0);
  4. position: absolute;
  5. border: none;
  6. top: 0px;
  7. left: 0px;
  8. padding: 0;
  9. margin: 0;
  10. z-index: -1;
  11. width: 100%;
  12. height: 100%;
  13. /*
  14.   We'll be setting these programmatically for IE6,
  15.   to account for cases where height is not set
  16.   */
  17. _width: 0;
  18. _height: 0;
  19. }
  20.  
.yui-widget-stacked .yui-widget-shim {
    opacity: 0;
    filter: alpha(opacity=0);
    position: absolute;
    border: none;
    top: 0px;
    left: 0px;
    padding: 0;
    margin: 0;
    z-index: -1;
    width: 100%;
    height: 100%;
    /* 
       We'll be setting these programmatically for IE6, 
       to account for cases where height is not set 
    */
    _width: 0;
    _height: 0;
}
 

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.

Copyright © 2010 Yahoo! Inc. All rights reserved. Copyright | Privacy Policy | Terms of Use | Job Openings