]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/widget/widget-position-ext.js
Release 6.2.1
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / widget / widget-position-ext.js
1 /*
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 3.0.0
6 build: 1549
7 */
8 YUI.add('widget-position-ext', 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-ext
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 WidgetPositionExt, if part of the same 
35          * extension list passed to Base.build).
36          *
37          * @class WidgetPositionExt
38          * @param {Object} User configuration object
39          */
40         function PositionExt(config) {
41             if (!this._posNode) {
42                 Y.error("WidgetPosition needs to be added to the Widget, before WidgetPositionExt is added"); 
43             }
44             Y.after(this._syncUIPosExtras, this, SYNCUI);
45             Y.after(this._bindUIPosExtras, this, BINDUI);
46         }
47
48         /**
49          * Static property used to define the default attribute 
50          * configuration introduced by WidgetPositionExt.
51          * 
52          * @property WidgetPositionExt.ATTRS
53          * @type Object
54          * @static
55          */
56         PositionExt.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>WidgetPositionExt</code>.
74              *         </p>
75              *         <p>
76              *         e.g. <code>[WidgetPositionExt.TR, WidgetPositionExt.TL]</code> aligns the Top-Right corner of the Widget with the
77              *         Top-Left corner of the node/viewport, and <code>[WidgetPositionExt.CC, WidgetPositionExt.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: function(val) {
97                     return this._setAlignCenter(val);
98                 },
99                 lazyAdd:false,
100                 value:false
101             }
102         };
103
104         /**
105          * Constant used to specify the top-left corner for alignment
106          * 
107          * @property WidgetPositionExt.TL
108          * @type String
109          * @static
110          * @value "tl"
111          */
112         PositionExt.TL = "tl";
113         /**
114          * Constant used to specify the top-right corner for alignment
115          * 
116          * @property WidgetPositionExt.TR
117          * @type String
118          * @static
119          * @value "tr"
120          */
121         PositionExt.TR = "tr";
122         /**
123          * Constant used to specify the bottom-left corner for alignment
124          * 
125          * @property WidgetPositionExt.BL
126          * @type String
127          * @static
128          * @value "bl"
129          */
130         PositionExt.BL = "bl";
131         /**
132          * Constant used to specify the bottom-right corner for alignment
133          * 
134          * @property WidgetPositionExt.BR
135          * @type String
136          * @static
137          * @value "br"
138          */
139         PositionExt.BR = "br";
140         /**
141          * Constant used to specify the top edge-center point for alignment
142          * 
143          * @property WidgetPositionExt.TC
144          * @type String
145          * @static
146          * @value "tc"
147          */
148         PositionExt.TC = "tc";
149         /**
150          * Constant used to specify the right edge, center point for alignment
151          * 
152          * @property WidgetPositionExt.RC
153          * @type String
154          * @static
155          * @value "rc"
156          */
157         PositionExt.RC = "rc";
158         /**
159          * Constant used to specify the bottom edge, center point for alignment
160          * 
161          * @property WidgetPositionExt.BC
162          * @type String
163          * @static
164          * @value "bc"
165          */
166         PositionExt.BC = "bc";
167         /**
168          * Constant used to specify the left edge, center point for alignment
169          * 
170          * @property WidgetPositionExt.LC
171          * @type String
172          * @static
173          * @value "lc"
174          */
175         PositionExt.LC = "lc";
176         /**
177          * Constant used to specify the center of widget/node/viewport for alignment
178          * 
179          * @property WidgetPositionExt.CC
180          * @type String
181          * @static
182          * @value "cc"
183          */
184         PositionExt.CC = "cc";
185
186         PositionExt.prototype = {
187
188             /**
189              * Synchronizes the UI to match the Widgets extended positioning state.
190              * This method in invoked after syncUI is invoked for the Widget class
191              * using YUI's aop infrastructure.
192              *
193              * @method _syncUIPosExtras
194              * @protected
195              */
196             _syncUIPosExtras : function() {
197                 var align = this.get(ALIGN);
198                 if (align) {
199                     this._uiSetAlign(align.node, align.points);
200                 }
201             },
202
203             /**
204              * Binds event listeners responsible for updating the UI state in response to 
205              * Widget extended positioning related state changes.
206              * <p>
207              * This method is invoked after bindUI is invoked for the Widget class
208              * using YUI's aop infrastructure.
209              * </p>
210              * @method _bindUIStack
211              * @protected
212              */
213             _bindUIPosExtras : function() {
214                 this.after(AlignChange, this._afterAlignChange);
215             },
216
217             /**
218              * Default setter for center attribute changes. Sets up the appropriate value, and passes 
219              * it through the to the align attribute.
220              *
221              * @method _setAlignCenter
222              * @protected
223              * @param {boolean | node} The attribute value being set. 
224              * @return {Number} The attribute value being set.
225              */
226             _setAlignCenter : function(val) {
227                 if (val) {
228                     this.set(ALIGN, {
229                         node: val === true ? null : val,
230                         points: [PositionExt.CC, PositionExt.CC]
231                     });
232                 }
233                 return val;
234             },
235
236             /**
237              * Default attribute change listener for the align attribute, responsible
238              * for updating the UI, in response to attribute changes.
239              * 
240              * @method _afterAlignChange
241              * @protected
242              * @param {EventFacade} e The event facade for the attribute change
243              */
244             _afterAlignChange : function(e) {
245                 if (e.newVal) {
246                     this._uiSetAlign(e.newVal.node, e.newVal.points);
247                 }
248             },
249
250             /**
251              * Updates the UI to reflect the align value passed in (see the align attribute documentation, for the object stucture expected)
252              * @method _uiSetAlign
253              * @protected
254              * @param {Node | null} The node to align to, or null to indicate the viewport
255              */
256             _uiSetAlign: function (node, points) {
257
258                 if (!L.isArray(points) || points.length != 2) {
259                     Y.error("align: Invalid Points Arguments");
260                     return;
261                 }
262
263                 var nodeRegion, widgetPoint, nodePoint, xy;
264
265                 if (!node) {
266                     nodeRegion = this._posNode.get(VIEWPORT_REGION);
267                 } else {
268                     node = Y.Node.get(node);
269                     if (node) {
270                         nodeRegion = node.get(REGION);
271                     }
272                 }
273
274                 if (nodeRegion) {
275
276                     // TODO: ViewportRegion doesn't have width/height - Workaround until normalized in Node/Dom
277                     nodeRegion.width = nodeRegion.width || nodeRegion.right - nodeRegion.left;
278                     nodeRegion.height = nodeRegion.height || nodeRegion.bottom - nodeRegion.top;
279
280                     widgetPoint = points[0];
281                     nodePoint = points[1];
282
283                     // TODO: Optimize KWeight - Would lookup table help?
284                     switch (nodePoint) {
285                         case PositionExt.TL:
286                             xy = [nodeRegion.left, nodeRegion.top];
287                             break;
288                         case PositionExt.TR:
289                             xy = [nodeRegion.right, nodeRegion.top];
290                             break;
291                         case PositionExt.BL:
292                             xy = [nodeRegion.left, nodeRegion.bottom];
293                             break;
294                         case PositionExt.BR:
295                             xy = [nodeRegion.right, nodeRegion.bottom];
296                             break;
297                         case PositionExt.TC:
298                             xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.top];
299                             break;
300                         case PositionExt.BC:
301                             xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.bottom];
302                             break;
303                         case PositionExt.LC:
304                             xy = [nodeRegion.left, nodeRegion.top + Math.floor(nodeRegion.height/2)];
305                             break;
306                         case PositionExt.RC:
307                             xy = [nodeRegion.right, nodeRegion.top + Math.floor(nodeRegion.height/2), widgetPoint];
308                             break;
309                         case PositionExt.CC:
310                             xy = [nodeRegion.left + Math.floor(nodeRegion.width/2), nodeRegion.top + Math.floor(nodeRegion.height/2), widgetPoint];
311                             break;
312                         default:
313                             break;
314                     }
315
316                     if (xy) {
317                         this._doAlign(widgetPoint, xy[0], xy[1]);
318                     }
319                 }
320             },
321
322             /**
323              * Helper method, used to align the given point on the widget, with the XY page co-ordinates provided.
324              *
325              * @method _doAlign
326              * @private
327              * @param {String} widgetPoint Supported point constant (e.g. WidgetPositionExt.TL)
328              * @param {Number} x X page co-ordinate to align to
329              * @param {Number} y Y page co-ordinate to align to
330              */
331             _doAlign : function(widgetPoint, x, y) {
332                 var widgetNode = this._posNode,
333                     xy;
334
335                 switch (widgetPoint) {
336                     case PositionExt.TL:
337                         xy = [x, y];
338                         break;
339                     case PositionExt.TR:
340                         xy = [x - widgetNode.get(OFFSET_WIDTH), y];
341                         break;
342                     case PositionExt.BL:
343                         xy = [x, y - widgetNode.get(OFFSET_HEIGHT)];
344                         break;
345                     case PositionExt.BR:
346                         xy = [x - widgetNode.get(OFFSET_WIDTH), y - widgetNode.get(OFFSET_HEIGHT)];
347                         break;
348                     case PositionExt.TC:
349                         xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y];
350                         break;
351                     case PositionExt.BC:
352                         xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y - widgetNode.get(OFFSET_HEIGHT)];
353                         break;
354                     case PositionExt.LC:
355                         xy = [x, y - (widgetNode.get(OFFSET_HEIGHT)/2)];
356                         break;
357                     case PositionExt.RC:
358                         xy = [(x - widgetNode.get(OFFSET_WIDTH)), y - (widgetNode.get(OFFSET_HEIGHT)/2)];
359                         break;
360                     case PositionExt.CC:
361                         xy = [x - (widgetNode.get(OFFSET_WIDTH)/2), y - (widgetNode.get(OFFSET_HEIGHT)/2)];
362                         break;
363                     default:
364                         break;
365                 }
366
367                 if (xy) {
368                     this.move(xy);
369                 }
370             },
371
372             /**
373              * Aligns the Widget to the provided node (or viewport) using the provided
374              * points. The method can be invoked directly, however it will result in 
375              * the align attribute being out of sync with current position of the of Widget.
376              * 
377              * @method align
378              * @param {Node | String | null} node A reference (or selector string) for the Node which with the Widget is to be aligned.
379              * If null is passed in, the Widget will be aligned with the viewport.
380              * @param {Array[2]} points A two element array, specifying the points on the Widget and node/viewport which need to be aligned. 
381              * The first entry is the point on the Widget, and the second entry is the point on the node/viewport which need to align.
382              * Valid point references are defined as static constants on the WidgetPositionExt class. 
383              * 
384              * e.g. [WidgetPositionExt.TL, WidgetPositionExt.TR] will align the top-left corner of the Widget with the top-right corner of the node/viewport.
385              */
386             align: function (node, points) {
387                 this.set(ALIGN, {node: node, points:points});
388             },
389
390             /**
391              * Centers the container in the viewport, or if a node is passed in,
392              * the node.
393              *
394              * @method centered
395              * @param {Node | String} node Optional. A node reference or selector string defining the node 
396              * inside which the Widget is to be centered. If not passed in, the Widget will be centered in the 
397              * viewport.
398              */
399             centered: function (node) {
400                 this.align(node, [PositionExt.CC, PositionExt.CC]);
401             }
402         };
403
404         Y.WidgetPositionExt = PositionExt;
405
406
407 }, '3.0.0' ,{requires:['widget', 'widget-position']});