This example shows how you can work with the zIndex
attribute which the Overlay supports, to implement a simple bringToTop
function. The example code also listens for changes in the zIndex
attribute, which it uses to update the content of the overlay, when it is brought to the top of the stack.
Click on an Overlay to switch it's zIndex with the highest zIndex in the stack, bringing it to the top of the stack
As with the "Basic XY Positioning" example, to create an instance of an Overlay on your page, the only module you need to request is the overlay
module. The overlay
module will pull in the widget
, widget-stack
, widget-position
, widget-position-align
, widget-position-constrain
and widget-stdmod
extensions it uses.
YUI({...}).use("overlay", function(Y) { // We'll write example code here, where we have a Y.Overlay class available. });
Using the overlay
module will also pull down the default CSS required for overlay, on top of which we only need to add our required look/feel CSS for the example.
Note: be sure to add the yui3-skin-sam
classname to the
page's <body>
element or to a parent element of the widget in order to apply
the default CSS skin. See Understanding Skinning.
<body class="yui3-skin-sam"> <!-- You need this skin class -->
For this example we'll instantiate Overlays from script, as we did for the "Alignment Support" example. We'll create 6 Overlay instances and give them increasing zIndex and xy attribute values:
function getOverlayXY(xy, i) { return [xy[0] + i * 60, xy[1] + i * 40]; } for (var i = 0; i < n; ++i) { ovrXY = getOverlayXY(xy, i); ovrZIndex = i+1; // Setup n Overlays, with increasing zIndex values and xy positions overlay = new Y.Overlay({ zIndex:ovrZIndex, xy:ovrXY, width:"8em", height:"8em", headerContent: 'Overlay <span class="yui3-ovr-number">' + i + '</span>', bodyContent: "z-index = " + ovrZIndex }); overlay.render("#overlay-stack"); ... }
We store the Overlay instances in an overlays
array, which we'll later use to sort the Overlays by their zIndex values. We also setup a listener for the zIndex
attribute change event, which will update the body section of the Overlay to display its new zIndex value.
overlays.push(overlay); // Update body whenever zIndex changes overlay.after("zIndexChange", function(e) { this.set("bodyContent", "z-index = " + e.newVal); });
The Widget
class has a static getByNode
method which can be used to retrieve Widget instances based on a node reference. The method will return the closest Widget which contains the given node.
We'll use this method in a click listener bound to the container of the example ("#overlay-stack"). Target nodes of click events bubbled up to this example container, will be passed to the Widget.getByNode
method, to see if an Overlay was clicked on.
function onStackMouseDown(e) { var widget = Y.Widget.getByNode(e.target); // If user clicked on an Overlay, bring it to the top of the stack if (widget && widget instanceof Y.Overlay) { bringToTop(widget); } } Y.on("mousedown", onStackMouseDown, "#overlay-stack");
If an Overlay was clicked on, we invoke the simple bringToTop method which will set the zIndex of the clicked Overlay to the highest current Overlay zIndex value.
bringToTop
ImplementationWe use a basic comparator function to sort the array of Overlays we have. The comparator makes sure the array element we're dealing with has a WidgetStack
implementation (which Overlays do) and if so, sorts them in descending zIndex
attribute value order:
// zIndex comparator function byZIndexDesc(a, b) { if (!a || !b || !a.hasImpl(Y.WidgetStack) || !b.hasImpl(Y.WidgetStack)) { return 0; } else { var aZ = a.get("zIndex"); var bZ = b.get("zIndex"); if (aZ > bZ) { return -1; } else if (aZ < bZ) { return 1; } else { return 0; } } }
Once sorted, for the purposes of the example, we simply switch the zIndex
of the "highest" Overlay, with the Overlay which was clicked on, giving the selected Overlay the highest zIndex value:
function bringToTop(overlay) { // Sort overlays by their numerical zIndex values overlays.sort(byZIndexDesc); // Get the highest one var highest = overlays[0]; // If the overlay is not the highest one, switch zIndices if (highest !== overlay) { var highestZ = highest.get("zIndex"); var overlayZ = overlay.get("zIndex"); overlay.set("zIndex", highestZ); highest.set("zIndex", overlayZ); } }
As mentioned in the "Basic XY Positioning" example, the overlay.css Sam Skin file (build/overlay/assets/skins/sam/overlay.css) provides the default functional CSS for the overlay. Namely the CSS rules to hide the overlay, and position it absolutely. However there's no default out-of-the-box look/feel applied to the Overlay widget.
The example provides it's own look and feel for the Overlay, by defining rules for the content box, header and body sections:
/* Overlay Look/Feel */ .yui3-overlay-content { background-color: #ECEFFB; border: 1px solid #9EA8C6; border-radius: 3px; box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.25); } .yui3-overlay-content .yui3-widget-hd { background-color: #B6BFDA; color: #30418C; font-size: 120%; font-weight: bold; padding: 0.2em 0.5em 0.3em; border-radius: 2px 2px 0 0; } .yui3-overlay-content .yui3-widget-bd { padding: 0.4em 0.6em 0.5em; } .yui3-overlay-content .yui3-widget-ft { background-color:#DFE3F5; padding: 0.4em 0.6em 0.5em; border-radius: 0 0 2px 2px; } .yui3-overlay-content .yui3-widget-bd .yui3-ovr-z-i{ line-height: 3.5em; font-size:190%; }
<p><strong>Click on an Overlay to switch it's zIndex with the highest zIndex in the stack, bringing it to the top of the stack</strong></p> <div class="overlay-example" id="overlay-stack"> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc pretium quam eu mi varius pulvinar. Duis orci arcu, ullamcorper sit amet, luctus ut, interdum ac, quam. Pellentesque euismod. Nam tincidunt, purus in ultrices congue, urna neque posuere arcu, aliquam tristique purus sapien id nulla. Etiam rhoncus nulla at leo. Cras scelerisque nisl in nibh. Sed eget odio. Morbi elit elit, porta a, convallis sit amet, rhoncus non, felis. Mauris nulla pede, pretium eleifend, porttitor at, rutrum id, orci. Quisque non urna. Nulla aliquam rhoncus est.</p> <p> <select class="needs-shim"> <option>Prevent IE6 Bleedthrough</option> </select> </p> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc pretium quam eu mi varius pulvinar. Duis orci arcu, ullamcorper sit amet, luctus ut, interdum ac, quam. Pellentesque euismod. Nam tincidunt, purus in ultrices congue, urna neque posuere arcu, aliquam tristique purus sapien id nulla. Etiam rhoncus nulla at leo. Cras scelerisque nisl in nibh. Sed eget odio. Morbi elit elit, porta a, convallis sit amet, rhoncus non, felis. Mauris nulla pede, pretium eleifend, porttitor at, rutrum id, orci. Quisque non urna. Nulla aliquam rhoncus est.</p> </div> <script type="text/javascript"> YUI().use("overlay", function(Y) { var overlays = [], overlay, n = 6, xy = Y.one("#overlay-stack").getXY(); function getOverlayXY(xy, i) { return [xy[0] + i * 60, xy[1] + i * 40]; } for (var i = 0; i < n; ++i) { ovrXY = getOverlayXY(xy, i); ovrZIndex = i+1; // Setup n Overlays, with increasing zIndex values overlay = new Y.Overlay({ zIndex:ovrZIndex, xy:ovrXY, width:"8em", height:"8em", headerContent: 'Overlay <span class="yui3-ovr-number">' + i + '</span>', bodyContent: '<div class="yui3-ovr-z-i"><em>' + ovrZIndex + '</em> = z-index</div>' }); overlay.render("#overlay-stack"); overlays.push(overlay); // Update body whenever zIndex changes overlay.after("zIndexChange", function(e) { this.set("bodyContent", '<div class="yui3-ovr-z-i"><em>' + e.newVal + '</em> = z-index</div>'); }); } function onStackMouseDown(e) { var widget = Y.Widget.getByNode(e.target); // If user clicked on an Overlay, bring it to the top of the stack if (widget && widget instanceof Y.Overlay) { bringToTop(widget); } } // zIndex comparator function byZIndexDesc(a, b) { if (!a || !b || !a.hasImpl(Y.WidgetStack) || !b.hasImpl(Y.WidgetStack)) { return 0; } else { var aZ = a.get("zIndex"); var bZ = b.get("zIndex"); if (aZ > bZ) { return -1; } else if (aZ < bZ) { return 1; } else { return 0; } } } function bringToTop(overlay) { // Sort overlays by their numerical zIndex values overlays.sort(byZIndexDesc); // Get the highest one var highest = overlays[0]; // If the overlay is not the highest one, switch zIndices if (highest !== overlay) { var highestZ = highest.get("zIndex"); var overlayZ = overlay.get("zIndex"); overlay.set("zIndex", highestZ); highest.set("zIndex", overlayZ); } } Y.on("mousedown", onStackMouseDown, "#overlay-stack"); }); </script>