2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
8 YUI.add('widget-position-align', function(Y) {
11 * Provides extended/advanced XY positioning support for Widgets, through an extension.
13 * It builds on top of the widget-position module, to provide alignmentment and centering support.
14 * Future releases aim to add constrained and fixed positioning support.
16 * @module widget-position-align
24 OFFSET_WIDTH = "offsetWidth",
25 OFFSET_HEIGHT = "offsetHeight",
26 VIEWPORT_REGION = "viewportRegion",
29 AlignChange = "alignChange";
32 * Widget extension, which can be used to add extended XY positioning support to the base Widget class,
33 * through the <a href="Base.html#method_build">Base.build</a> method. This extension requires that
34 * the WidgetPosition extension be added to the Widget (before WidgetPositionAlign, if part of the same
35 * extension list passed to Base.build).
37 * @class WidgetPositionAlign
38 * @param {Object} User configuration object
40 function PositionAlign(config) {
42 Y.error("WidgetPosition needs to be added to the Widget, before WidgetPositionAlign is added");
44 Y.after(this._syncUIPosAlign, this, SYNCUI);
45 Y.after(this._bindUIPosAlign, this, BINDUI);
49 * Static property used to define the default attribute
50 * configuration introduced by WidgetPositionAlign.
52 * @property WidgetPositionAlign.ATTRS
56 PositionAlign.ATTRS = {
62 * @desciption The align attribute is used to align a reference point on the widget, with the refernce point on another node, or the viewport.
63 * The object which align expects has the following properties:
67 * The node to which the Widget is to be aligned. If set to null, or not provided, the Widget is aligned to the viewport
72 * A two element array, defining the two points on the Widget and node/viewport which are to be aligned. The first element is the point on the Widget, and the second element is the point on the node/viewport.
73 * Supported alignment points are defined as static properties on <code>WidgetPositionAlign</code>.
76 * e.g. <code>[WidgetPositionAlign.TR, WidgetPositionAlign.TL]</code> aligns the Top-Right corner of the Widget with the
77 * Top-Left corner of the node/viewport, and <code>[WidgetPositionAlign.CC, WidgetPositionAlign.TC]</code> aligns the Center of the
78 * Widget with the Top-Center edge of the node/viewport.
89 * @type {boolean | node}
91 * @description A convenience attribute, which can be used as a shortcut for the align attribute.
92 * If set to true, the Widget is centered in the viewport. If set to a node reference or valid selector string,
93 * the Widget will be centered within the node. If set the false, no center positioning is applied.
96 setter: "_setAlignCenter",
103 * Constant used to specify the top-left corner for alignment
105 * @property WidgetPositionAlign.TL
110 PositionAlign.TL = "tl";
112 * Constant used to specify the top-right corner for alignment
114 * @property WidgetPositionAlign.TR
119 PositionAlign.TR = "tr";
121 * Constant used to specify the bottom-left corner for alignment
123 * @property WidgetPositionAlign.BL
128 PositionAlign.BL = "bl";
130 * Constant used to specify the bottom-right corner for alignment
132 * @property WidgetPositionAlign.BR
137 PositionAlign.BR = "br";
139 * Constant used to specify the top edge-center point for alignment
141 * @property WidgetPositionAlign.TC
146 PositionAlign.TC = "tc";
148 * Constant used to specify the right edge, center point for alignment
150 * @property WidgetPositionAlign.RC
155 PositionAlign.RC = "rc";
157 * Constant used to specify the bottom edge, center point for alignment
159 * @property WidgetPositionAlign.BC
164 PositionAlign.BC = "bc";
166 * Constant used to specify the left edge, center point for alignment
168 * @property WidgetPositionAlign.LC
173 PositionAlign.LC = "lc";
175 * Constant used to specify the center of widget/node/viewport for alignment
177 * @property WidgetPositionAlign.CC
182 PositionAlign.CC = "cc";
184 PositionAlign.prototype = {
187 * Synchronizes the UI to match the Widgets align configuration.
189 * This method in invoked after syncUI is invoked for the Widget class
190 * using YUI's aop infrastructure.
192 * @method _syncUIPosAlign
195 _syncUIPosAlign : function() {
196 var align = this.get(ALIGN);
198 this._uiSetAlign(align.node, align.points);
203 * Binds event listeners responsible for updating the UI state in response to
204 * Widget extended positioning related state changes.
206 * This method is invoked after bindUI is invoked for the Widget class
207 * using YUI's aop infrastructure.
209 * @method _bindUIStack
212 _bindUIPosAlign : function() {
213 this.after(AlignChange, this._afterAlignChange);
217 * Default setter for center attribute changes. Sets up the appropriate value, and passes
218 * it through the to the align attribute.
220 * @method _setAlignCenter
222 * @param {boolean | node} The attribute value being set.
223 * @return {Number} The attribute value being set.
225 _setAlignCenter : function(val) {
228 node: val === true ? null : val,
229 points: [PositionAlign.CC, PositionAlign.CC]
236 * Default attribute change listener for the align attribute, responsible
237 * for updating the UI, in response to attribute changes.
239 * @method _afterAlignChange
241 * @param {EventFacade} e The event facade for the attribute change
243 _afterAlignChange : function(e) {
245 this._uiSetAlign(e.newVal.node, e.newVal.points);
250 * Updates the UI to reflect the align value passed in (see the align attribute documentation, for the object stucture expected)
251 * @method _uiSetAlign
253 * @param {Node | null} The node to align to, or null to indicate the viewport
255 _uiSetAlign: function (node, points) {
257 if (!L.isArray(points) || points.length != 2) {
258 Y.error("align: Invalid Points Arguments");
262 var nodeRegion = this._getRegion(node),
269 widgetPoint = points[0];
270 nodePoint = points[1];
272 // TODO: Optimize KWeight - Would lookup table help?
274 case PositionAlign.TL:
275 xy = [nodeRegion.left, nodeRegion.top];
277 case PositionAlign.TR:
278 xy = [nodeRegion.right, nodeRegion.top];
280 case PositionAlign.BL:
281 xy = [nodeRegion.left, nodeRegion.bottom];
283 case PositionAlign.BR:
284 xy = [nodeRegion.right, nodeRegion.bottom];
286 case PositionAlign.TC:
287 xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.top];
289 case PositionAlign.BC:
290 xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.bottom];
292 case PositionAlign.LC:
293 xy = [nodeRegion.left, nodeRegion.top + Math.floor(nodeRegion.height/2)];
295 case PositionAlign.RC:
296 xy = [nodeRegion.right, nodeRegion.top + Math.floor(nodeRegion.height/2), widgetPoint];
298 case PositionAlign.CC:
299 xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.top + Math.floor(nodeRegion.height/2), widgetPoint];
306 this._doAlign(widgetPoint, xy[0], xy[1]);
312 * Helper method, used to align the given point on the widget, with the XY page co-ordinates provided.
316 * @param {String} widgetPoint Supported point constant (e.g. WidgetPositionAlign.TL)
317 * @param {Number} x X page co-ordinate to align to
318 * @param {Number} y Y page co-ordinate to align to
320 _doAlign : function(widgetPoint, x, y) {
321 var widgetNode = this._posNode,
324 switch (widgetPoint) {
325 case PositionAlign.TL:
328 case PositionAlign.TR:
329 xy = [x - widgetNode.get(OFFSET_WIDTH), y];
331 case PositionAlign.BL:
332 xy = [x, y - widgetNode.get(OFFSET_HEIGHT)];
334 case PositionAlign.BR:
335 xy = [x - widgetNode.get(OFFSET_WIDTH), y - widgetNode.get(OFFSET_HEIGHT)];
337 case PositionAlign.TC:
338 xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y];
340 case PositionAlign.BC:
341 xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y - widgetNode.get(OFFSET_HEIGHT)];
343 case PositionAlign.LC:
344 xy = [x, y - (widgetNode.get(OFFSET_HEIGHT)/2)];
346 case PositionAlign.RC:
347 xy = [(x - widgetNode.get(OFFSET_WIDTH)), y - (widgetNode.get(OFFSET_HEIGHT)/2)];
349 case PositionAlign.CC:
350 xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y - (widgetNode.get(OFFSET_HEIGHT)/2)];
361 _getRegion : function(node) {
364 nodeRegion = this._posNode.get(VIEWPORT_REGION);
366 node = Y.Node.one(node);
368 nodeRegion = node.get(REGION);
375 * Aligns the Widget to the provided node (or viewport) using the provided
376 * points. The method can be invoked directly, however it will result in
377 * the align attribute being out of sync with current position of the of Widget.
380 * @param {Node | String | null} node A reference (or selector string) for the Node which with the Widget is to be aligned.
381 * If null is passed in, the Widget will be aligned with the viewport.
382 * @param {Array[2]} points A two element array, specifying the points on the Widget and node/viewport which need to be aligned.
383 * The first entry is the point on the Widget, and the second entry is the point on the node/viewport which need to align.
384 * Valid point references are defined as static constants on the WidgetPositionAlign class.
386 * e.g. [WidgetPositionAlign.TL, WidgetPositionAlign.TR] will align the top-left corner of the Widget with the top-right corner of the node/viewport.
388 align: function (node, points) {
389 this.set(ALIGN, {node: node, points:points});
393 * Centers the container in the viewport, or if a node is passed in,
397 * @param {Node | String} node Optional. A node reference or selector string defining the node
398 * inside which the Widget is to be centered. If not passed in, the Widget will be centered in the
401 centered: function (node) {
402 this.align(node, [PositionAlign.CC, PositionAlign.CC]);
406 Y.WidgetPositionAlign = PositionAlign;
409 }, '3.3.0' ,{requires:['widget-position']});