e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<style type="text/css" scoped>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Standard Module Widget CSS */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule-hidden {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai display:none;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai margin:10px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule-content {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai padding:3px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai border:1px solid #666;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule-content .yui3-widget-hd {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai padding:5px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai border:2px solid #aa0000;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai background-color:#fff;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai overflow:auto;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule-content .yui3-widget-bd {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai padding:5px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai border:2px solid #0000aa;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai background-color:#fff;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai overflow:auto;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule-content .yui3-widget-ft {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai padding:5px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai border:2px solid #00aa00;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai background-color:#fff;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai overflow:auto;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Positionable Widget CSS */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-positionable {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai position:absolute;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-positionable-content {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai text-align:center;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai border:1px solid #000;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai background-color:#999966;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai color:#fff;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai padding:10px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-positionable-hidden {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai visibility:hidden;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Alignable Widget CSS */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-alignable {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai position:absolute;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-alignable-content {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai text-align:center;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai border:1px solid #000000;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai background-color:#004C6D;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai color:#fff;
e1aced3d7f8ff426bc0a9474125b04d9a3137eedSatyen Desai padding:1px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-alignable-hidden {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai visibility:hidden;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Example Layout CSS */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.widget-build-example {
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai border:1px solid #ccc;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai padding:5px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.widget-build-example button, .widget-build-example label, .widget-build-example select, .widget-build-example input {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai margin-right:5px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.widget-build-example button.fail {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai color:#cc0000;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai margin-left:10px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.widget-build-example .filler {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai color:#999;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai#x, #y {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai width:3em;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai#widget-build-examples dd {
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai margin-left:0;
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai}
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai#widget-build-examples dt {
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai margin-bottom:1em;
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai margin-top:1em;
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai}
f3433d94fc91602084922f6106e13e91bebdf6f6Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai#widget2-example, #widget3-example {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai height:15em;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai#widget2-example select, #widget3-example select {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai width:100%;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai#alignment p {
e1aced3d7f8ff426bc0a9474125b04d9a3137eedSatyen Desai margin:0;
e1aced3d7f8ff426bc0a9474125b04d9a3137eedSatyen Desai padding:2px;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai color:#dddd00;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai</style>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<div class="intro">
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai <p>This example shows how you can mix and match the `WidgetPosition`, `WidgetPositionAlign`, `WidgetStack` and `WidgetStdMod` extensions to build custom versions of the `Widget` class, using `Base.create`.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai</div>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<div class="example">
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai {{>widget-build-source}}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai</div>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h2>Creating Custom Widget Classes</h2>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>The `Base` class provides a `create` method which can be used to create custom versions of classes which derive from `Base` by adding extension classes to them.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Widget currently ships with four such extensions: `WidgetPosition`, `WidgetStack`, `WidgetPositionAlign` and `WidgetStdMod`.
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiThese extensions are used to create the basic `Overlay` widget, but can also be used individually, to create custom versions of the base `Widget` class.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h2>Widget with WidgetStdMod support</h2>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Adding the `WidgetStdMod` extension to Widget, creates a statically positioned Widget, with support for standard module format sections - header, body and footer, which maybe useful in portal type use cases, where the positioning/stacking capabilities which come bundled with Overlay are not required.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>To create a custom class, we use <a href="{{apiDocs}}/Base.html#method_Base.create">`Base.create`</a>, which is described in detail on the documention page for <a href="../base/index.html#extensions">Base</a>.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>We pass in `Widget` as the main class we want to add extensions to, and `WidgetStdMod` as the extension we'd like added to the main class:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar StandardModule = Y.Base.create("standardModule", Y.Widget, [Y.WidgetStdMod]);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Render from Markup
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar stdmod = new StandardModule({
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai contentBox: "#widget1",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai width:"12em",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai height:"12em"
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaistdmod.render();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>`Base.create` will:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<ol>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai <li>Create a new class which extends `Widget`</li>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai <li>Aggregate known `Base` and `Widget` fields, such as `ATTRS` and `HTML_PARSER` from `WidgetStdMod` on the new class</li>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai <li>Augment prototype methods from `WidgetStdMod` onto the new class prototype</li>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai</ol>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>The first argument to create is the `NAME` of the new class we are creating, just like the `NAME` we define when extending the Widget class directly.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Note that the `Widget` class is unchanged, allowing you to still create `Widget` instances without any standard module support, along with `StandardModule` instances which have standard module support.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h3>Testing It Out</h3>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>The example attempts to set content on an instance of the newly created `StandardModule` class, using the `setStdModContent` method which is added by the extension (which would otherwise not exist on the Widget instance).</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar contentInput = Y.one("#content");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar sectionInput = Y.one("#section");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// This should work, since the StandardModule widget has settable
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// header/body/footer sections
2c40caf14e175744abe5a7365b2404da0d871328Satyen DesaiY.on("submit", function(e) {
2c40caf14e175744abe5a7365b2404da0d871328Satyen Desai e.preventDefault();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var content = Y.Escape.html(contentInput.get("value"));
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var section = sectionInput.get("value");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai stdmod.setStdModContent(section, content);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
2c40caf14e175744abe5a7365b2404da0d871328Satyen Desai}, "#widget1-example");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>To verify that no unrequested features are added, we also attempt to move the instance using the `move` method, which is not part of the base Widget class, and would be added by the `WidgetPosition` extension. This verifies that the other example classes we'll create, which do create new classes which use `WidgetPosition`, have not modified the base Widget class.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// This shoud fail, since the StandardModule widget is not positionable
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiY.on("click", function(e) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai try {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai stdmod.move([0,0]);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } catch (e) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai alert("move() is " + typeof stdmod.move + ", stdmod.hasImpl(Y.WidgetPosition) : "
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai + stdmod.hasImpl(Y.WidgetPosition));
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}, "#tryMove");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Note that `Base.create` adds a `hasImpl` method to the built class, which allows you to query whether or not it has a particular extension applied.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h3>CSS Considerations</h3>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>We need to define the CSS which goes with this new `StandardModule` class we have created. The only rule really required out of the box is the rule which handles visibility (`yui-standardmodule-hidden`). The "standardmodule" used in the class name comes from the `NAME` property we set up for the new class, and is used to prefix all state related classes added to the widgets bounding box.
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiSince the `StandardModule` class is not positionable, we use `display:none` to define the `hidden` state.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Visibility - How to handle visibility for this new widget */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-standardmodule-hidden {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai display:none;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>The other "yui-standardmodule" rules are only used to create the required look/feel for this particular example, and do not impact the StandardModule widget's functionality.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h2>Widget with WidgetPosition and WidgetStack support</h2>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>As with `StandardModule`, we use `Base.create` to create the new `Positionable` widget class. This time we add `WidgetPosition` and `WidgetStack` support to the base `Widget` class to create a basic XY positionable widget, with shimming and z-index support.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar Positionable = Y.Base.create("positionable", Y.Widget,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai [Y.WidgetPosition, Y.WidgetStack]);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Render from markup
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar positionable = new Positionable({
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai contentBox: "#widget2",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai width:"10em",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai height:"10em",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai zIndex:1
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaipositionable.render("#widget2-example");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar xy = Y.one("#widget2-example > p").getXY();
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaipositionable.move(xy[0], xy[1]);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>We <strong>don't</strong> add `WidgetPositionAlign` or `WidgetStdMod` support, so the widget doesn't have extended positioning support (align, center) or standard module support. Hence we position it manually using the `move` method which the `WidgetPosition` extension provides.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h3>Testing It Out</h3>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>We should now be able to invoke the `move` method on an instance of the newly created `Positionable` class:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// This should work, since Positionable has basic XY Positioning support
2c40caf14e175744abe5a7365b2404da0d871328Satyen DesaiY.on("submit", function(e) {
2c40caf14e175744abe5a7365b2404da0d871328Satyen Desai e.preventDefault();
2c40caf14e175744abe5a7365b2404da0d871328Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var x = parseInt(xInput.get("value"));
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai var y = parseInt(yInput.get("value"));
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai positionable.move(x,y);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
2c40caf14e175744abe5a7365b2404da0d871328Satyen Desai}, "#widget2-example");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>And, as with the `StandardModule` class, we should not be allowed to invoke any methods from an extension which we didn't request:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// This should fail, since Positionable does not have Standard Module sections
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen DesaiY.on("click", function(e) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai try {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai positionable.setStdModContent("header", "new content");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai } catch (e) {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai alert("setStdModContent() is " + typeof positionable.setStdModContent +
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai ", positionable.hasImpl(Y.WidgetStdMod) : " + positionable.hasImpl(Y.WidgetStdMod));
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}, "#tryContent");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h3>CSS Considerations</h3>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Since now we have a positionable widget, with z-index support, we set the widget to be absolutely positioned by default, and control it's hidden state using `visibility` as opposed to `display`</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Define absolute positioning as the default for positionable widgets */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-positionable {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai position:absolute;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/*
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai In order to be able to position the widget when hidden, we define hidden
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai to use visibility, as opposed to display
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai*/
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-positionable-hidden {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai visibility:hidden;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h2>Widget with WidgetPosition, WidgetStack and WidgetPositionAlign support</h2>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Lastly, we'll attempt to create a new widget class, which, in addition to basic positioning and stacking support, also has extended positioning support, allowing us to align it with other elements on the page.</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>Again, we use `Base.create` to create our new `Alignable` widget class, by combining `WidgetPosition`, `WidgetStack` and `WidgetPositionAlign` with the base widget class:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar Alignable = Y.Base.create("alignable", Y.Widget,
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai [Y.WidgetPosition, Y.WidgetPositionAlign, Y.WidgetStack]);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaivar alignable = new Alignable({
e1aced3d7f8ff426bc0a9474125b04d9a3137eedSatyen Desai width:"14em",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai align : {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai node: "#widget3-example",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai points: ["cc", "cc"]
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai },
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai zIndex:1
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.get("contentBox").set("innerHTML",
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai '<strong>Alignable Widget</strong><div id="alignment"><p>#widget3-example</p> \
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai <p>[center, center]</p></div>');
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.render("#widget3-example");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h3>Testing It Out</h3>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>We'll attempt to align an instance of the `Alignable` class, using some of the additional attributes which `WidgetPositionAlign` adds to the base `Widget` class: `align` and `centered`:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Align left-center egde of widget to
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// right-center edge of the node with id "widget3-example"
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.set("align", {node:"#widget3-example", points:["lc", "rc"]});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Align top-right corner of widget to
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// bottom-right corner of the node with id "widget3-example"
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.set("align", {node:"#widget3-example", points:["tr", "br"]});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Center the widget in the node with id "widget3-example"
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.set("centered", "widget3-example");
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Align the right-center edge of the widget to
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// the right center edge of the viewport (since a node is not provided to 'align')
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.set("align", {points:["rc", "rc"]});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Center the widget in the viewport (wince a node is not provided to 'centered')
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.set("centered", true);
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// Return the node to it's original alignment
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// (centered in the node with id "widget3-example")
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai// NOTE: centered is a shortcut for align : { points:["cc", "cc"] }
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desaialignable.set("align", {node:"#widget3-example", points:["cc", "cc"]});
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h3>CSS Considerations</h3>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<p>The `Alignable` widget class, has the same core CSS rules as the `Positionable` class, to define how it is positioned and how it is hidden:</p>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/* Define absolute positioning as the default for alignable widgets */
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-alignable {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai position:absolute;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai/*
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai In order to be able to position the widget when hidden, we define hidden
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai to use visibility, as opposed to display
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai*/
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai.yui3-alignable-hidden {
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai visibility:hidden;
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai<h2>Complete Example Source</h2>
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai{{>widget-build-source}}
e808b8824ca1091c8efb5669db9129e68e5e1c14Satyen Desai```