]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/widget/widget-position-align.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / widget / widget-position-align.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('widget-position-align', function(Y) {
9
10 /**
11  * Provides extended/advanced XY positioning support for Widgets, through an extension.
12  *
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.
15  *
16  * @module widget-position-align
17  */
18         var L = Y.Lang,
19             ALIGN = "align",
20
21             BINDUI = "bindUI",
22             SYNCUI = "syncUI",
23
24             OFFSET_WIDTH = "offsetWidth",
25             OFFSET_HEIGHT = "offsetHeight",
26             VIEWPORT_REGION = "viewportRegion",
27             REGION = "region",
28
29             AlignChange = "alignChange";
30
31         /**
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).
36          *
37          * @class WidgetPositionAlign
38          * @param {Object} User configuration object
39          */
40         function PositionAlign(config) {
41             if (!this._posNode) {
42                 Y.error("WidgetPosition needs to be added to the Widget, before WidgetPositionAlign is added"); 
43             }
44             Y.after(this._syncUIPosAlign, this, SYNCUI);
45             Y.after(this._bindUIPosAlign, this, BINDUI);
46         }
47
48         /**
49          * Static property used to define the default attribute 
50          * configuration introduced by WidgetPositionAlign.
51          * 
52          * @property WidgetPositionAlign.ATTRS
53          * @type Object
54          * @static
55          */
56         PositionAlign.ATTRS = {
57
58             /**
59              * @attribute align
60              * @type Object
61              * @default null
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:
64              * <dl>
65              *       <dt>node</dt>
66              *       <dd>
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
68              *       </dd>
69              *       <dt>points</dt>
70              *       <dd>
71              *         <p>
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>.
74              *         </p>
75              *         <p>
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.
79              *         </p>
80              *       </dd>
81              *   </dl>
82              */
83             align: {
84                 value:null
85             },
86
87             /**
88              * @attribute centered
89              * @type {boolean | node} 
90              * @default false
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.
94              */
95             centered: {
96                 setter: "_setAlignCenter",
97                 lazyAdd:false,
98                 value:false
99             }
100         };
101
102         /**
103          * Constant used to specify the top-left corner for alignment
104          * 
105          * @property WidgetPositionAlign.TL
106          * @type String
107          * @static
108          * @value "tl"
109          */
110         PositionAlign.TL = "tl";
111         /**
112          * Constant used to specify the top-right corner for alignment
113          * 
114          * @property WidgetPositionAlign.TR
115          * @type String
116          * @static
117          * @value "tr"
118          */
119         PositionAlign.TR = "tr";
120         /**
121          * Constant used to specify the bottom-left corner for alignment
122          * 
123          * @property WidgetPositionAlign.BL
124          * @type String
125          * @static
126          * @value "bl"
127          */
128         PositionAlign.BL = "bl";
129         /**
130          * Constant used to specify the bottom-right corner for alignment
131          * 
132          * @property WidgetPositionAlign.BR
133          * @type String
134          * @static
135          * @value "br"
136          */
137         PositionAlign.BR = "br";
138         /**
139          * Constant used to specify the top edge-center point for alignment
140          * 
141          * @property WidgetPositionAlign.TC
142          * @type String
143          * @static
144          * @value "tc"
145          */
146         PositionAlign.TC = "tc";
147         /**
148          * Constant used to specify the right edge, center point for alignment
149          * 
150          * @property WidgetPositionAlign.RC
151          * @type String
152          * @static
153          * @value "rc"
154          */
155         PositionAlign.RC = "rc";
156         /**
157          * Constant used to specify the bottom edge, center point for alignment
158          * 
159          * @property WidgetPositionAlign.BC
160          * @type String
161          * @static
162          * @value "bc"
163          */
164         PositionAlign.BC = "bc";
165         /**
166          * Constant used to specify the left edge, center point for alignment
167          * 
168          * @property WidgetPositionAlign.LC
169          * @type String
170          * @static
171          * @value "lc"
172          */
173         PositionAlign.LC = "lc";
174         /**
175          * Constant used to specify the center of widget/node/viewport for alignment
176          * 
177          * @property WidgetPositionAlign.CC
178          * @type String
179          * @static
180          * @value "cc"
181          */
182         PositionAlign.CC = "cc";
183
184         PositionAlign.prototype = {
185
186             /**
187              * Synchronizes the UI to match the Widgets align configuration.
188              * 
189              * This method in invoked after syncUI is invoked for the Widget class
190              * using YUI's aop infrastructure.
191              *
192              * @method _syncUIPosAlign
193              * @protected
194              */
195             _syncUIPosAlign : function() {
196                 var align = this.get(ALIGN);
197                 if (align) {
198                     this._uiSetAlign(align.node, align.points);
199                 }
200             },
201
202             /**
203              * Binds event listeners responsible for updating the UI state in response to 
204              * Widget extended positioning related state changes.
205              * <p>
206              * This method is invoked after bindUI is invoked for the Widget class
207              * using YUI's aop infrastructure.
208              * </p>
209              * @method _bindUIStack
210              * @protected
211              */
212             _bindUIPosAlign : function() {
213                 this.after(AlignChange, this._afterAlignChange);
214             },
215
216             /**
217              * Default setter for center attribute changes. Sets up the appropriate value, and passes 
218              * it through the to the align attribute.
219              *
220              * @method _setAlignCenter
221              * @protected
222              * @param {boolean | node} The attribute value being set. 
223              * @return {Number} The attribute value being set.
224              */
225             _setAlignCenter : function(val) {
226                 if (val) {
227                     this.set(ALIGN, {
228                         node: val === true ? null : val,
229                         points: [PositionAlign.CC, PositionAlign.CC]
230                     });
231                 }
232                 return val;
233             },
234
235             /**
236              * Default attribute change listener for the align attribute, responsible
237              * for updating the UI, in response to attribute changes.
238              * 
239              * @method _afterAlignChange
240              * @protected
241              * @param {EventFacade} e The event facade for the attribute change
242              */
243             _afterAlignChange : function(e) {
244                 if (e.newVal) {
245                     this._uiSetAlign(e.newVal.node, e.newVal.points);
246                 }
247             },
248
249             /**
250              * Updates the UI to reflect the align value passed in (see the align attribute documentation, for the object stucture expected)
251              * @method _uiSetAlign
252              * @protected
253              * @param {Node | null} The node to align to, or null to indicate the viewport
254              */
255             _uiSetAlign: function (node, points) {
256
257                 if (!L.isArray(points) || points.length != 2) {
258                     Y.error("align: Invalid Points Arguments");
259                     return;
260                 }
261
262                 var nodeRegion = this._getRegion(node), 
263                     widgetPoint, 
264                     nodePoint, 
265                     xy;
266
267                 if (nodeRegion) {
268
269                     widgetPoint = points[0];
270                     nodePoint = points[1];
271
272                     // TODO: Optimize KWeight - Would lookup table help?
273                     switch (nodePoint) {
274                         case PositionAlign.TL:
275                             xy = [nodeRegion.left, nodeRegion.top];
276                             break;
277                         case PositionAlign.TR:
278                             xy = [nodeRegion.right, nodeRegion.top];
279                             break;
280                         case PositionAlign.BL:
281                             xy = [nodeRegion.left, nodeRegion.bottom];
282                             break;
283                         case PositionAlign.BR:
284                             xy = [nodeRegion.right, nodeRegion.bottom];
285                             break;
286                         case PositionAlign.TC:
287                             xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.top];
288                             break;
289                         case PositionAlign.BC:
290                             xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.bottom];
291                             break;
292                         case PositionAlign.LC:
293                             xy = [nodeRegion.left, nodeRegion.top + Math.floor(nodeRegion.height/2)];
294                             break;
295                         case PositionAlign.RC:
296                             xy = [nodeRegion.right, nodeRegion.top + Math.floor(nodeRegion.height/2), widgetPoint];
297                             break;
298                         case PositionAlign.CC:
299                             xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.top + Math.floor(nodeRegion.height/2), widgetPoint];
300                             break;
301                         default:
302                             break;
303                     }
304
305                     if (xy) {
306                         this._doAlign(widgetPoint, xy[0], xy[1]);
307                     }
308                 }
309             },
310
311             /**
312              * Helper method, used to align the given point on the widget, with the XY page co-ordinates provided.
313              *
314              * @method _doAlign
315              * @private
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
319              */
320             _doAlign : function(widgetPoint, x, y) {
321                 var widgetNode = this._posNode,
322                     xy;
323
324                 switch (widgetPoint) {
325                     case PositionAlign.TL:
326                         xy = [x, y];
327                         break;
328                     case PositionAlign.TR:
329                         xy = [x - widgetNode.get(OFFSET_WIDTH), y];
330                         break;
331                     case PositionAlign.BL:
332                         xy = [x, y - widgetNode.get(OFFSET_HEIGHT)];
333                         break;
334                     case PositionAlign.BR:
335                         xy = [x - widgetNode.get(OFFSET_WIDTH), y - widgetNode.get(OFFSET_HEIGHT)];
336                         break;
337                     case PositionAlign.TC:
338                         xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y];
339                         break;
340                     case PositionAlign.BC:
341                         xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y - widgetNode.get(OFFSET_HEIGHT)];
342                         break;
343                     case PositionAlign.LC:
344                         xy = [x, y - (widgetNode.get(OFFSET_HEIGHT)/2)];
345                         break;
346                     case PositionAlign.RC:
347                         xy = [(x - widgetNode.get(OFFSET_WIDTH)), y - (widgetNode.get(OFFSET_HEIGHT)/2)];
348                         break;
349                     case PositionAlign.CC:
350                         xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y - (widgetNode.get(OFFSET_HEIGHT)/2)];
351                         break;
352                     default:
353                         break;
354                 }
355
356                 if (xy) {
357                     this.move(xy);
358                 }
359             },
360
361             _getRegion : function(node) {
362                 var nodeRegion;
363                 if (!node) {
364                     nodeRegion = this._posNode.get(VIEWPORT_REGION);
365                 } else {
366                     node = Y.Node.one(node);
367                     if (node) {
368                         nodeRegion = node.get(REGION);
369                     }
370                 }
371                 return nodeRegion;
372             },
373
374             /**
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.
378              * 
379              * @method align
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. 
385              * 
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.
387              */
388             align: function (node, points) {
389                 this.set(ALIGN, {node: node, points:points});
390             },
391
392             /**
393              * Centers the container in the viewport, or if a node is passed in,
394              * the node.
395              *
396              * @method centered
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 
399              * viewport.
400              */
401             centered: function (node) {
402                 this.align(node, [PositionAlign.CC, PositionAlign.CC]);
403             }
404         };
405
406         Y.WidgetPositionAlign = PositionAlign;
407
408
409 }, '3.3.0' ,{requires:['widget-position']});