AutorÃa | Ultima modificación | Ver Log |
YUI.add('widget-position-align', function (Y, NAME) {/**Provides extended/advanced XY positioning support for Widgets, through anextension.It builds on top of the `widget-position` module, to provide alignment andcentering support. Future releases aim to add constrained and fixed positioningsupport.@module widget-position-align**/var Lang = Y.Lang,ALIGN = 'align',ALIGN_ON = 'alignOn',VISIBLE = 'visible',BOUNDING_BOX = 'boundingBox',OFFSET_WIDTH = 'offsetWidth',OFFSET_HEIGHT = 'offsetHeight',REGION = 'region',VIEWPORT_REGION = 'viewportRegion';/**Widget extension, which can be used to add extended XY positioning support tothe base Widget class, through the `Base.create` method.**Note:** This extension requires that the `WidgetPosition` extension be addedto the Widget (before `WidgetPositionAlign`, if part of the same extension listpassed to `Base.build`).@class WidgetPositionAlign@param {Object} config User configuration object.@constructor**/function PositionAlign (config) {}PositionAlign.ATTRS = {/**The alignment configuration for this widget.The `align` attribute is used to align a reference point on the widget, withthe reference point on another `Node`, or the viewport. The object which`align` expects has the following properties:* __`node`__: The `Node` to which the widget is to be aligned. If set to`null`, or not provided, the widget is aligned to the viewport.* __`points`__: A two element Array, defining the two points on the widgetand `Node`/viewport which are to be aligned. The first element is thepoint on the widget, and the second element is the point on the`Node`/viewport. Supported alignment points are defined as staticproperties on `WidgetPositionAlign`.@example Aligns the top-right corner of the widget with the top-left cornerof the viewport:myWidget.set('align', {points: [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.TL]});@attribute align@type Object@default null**/align: {value: null},/**A convenience Attribute, which can be used as a shortcut for the `align`Attribute.If set to `true`, the widget is centered in the viewport. If set to a `Node`reference or valid selector String, the widget will be centered within the`Node`. If set to `false`, no center positioning is applied.@attribute centered@type Boolean|Node@default false**/centered: {setter : '_setAlignCenter',lazyAdd:false,value :false},/**An Array of Objects corresponding to the `Node`s and events that will causethe alignment of this widget to be synced to the DOM.The `alignOn` Attribute is expected to be an Array of Objects with thefollowing properties:* __`eventName`__: The String event name to listen for.* __`node`__: The optional `Node` that will fire the event, it can be a`Node` reference or a selector String. This will default to the widget's`boundingBox`.@example Sync this widget's alignment on window resize:myWidget.set('alignOn', [{node : Y.one('win'),eventName: 'resize'}]);@attribute alignOn@type Array@default []**/alignOn: {value : [],validator: Y.Lang.isArray}};/**Constant used to specify the top-left corner for alignment@property TL@type String@value 'tl'@static**/PositionAlign.TL = 'tl';/**Constant used to specify the top-right corner for alignment@property TR@type String@value 'tr'@static**/PositionAlign.TR = 'tr';/**Constant used to specify the bottom-left corner for alignment@property BL@type String@value 'bl'@static**/PositionAlign.BL = 'bl';/**Constant used to specify the bottom-right corner for alignment@property BR@type String@value 'br'@static**/PositionAlign.BR = 'br';/**Constant used to specify the top edge-center point for alignment@property TC@type String@value 'tc'@static**/PositionAlign.TC = 'tc';/**Constant used to specify the right edge, center point for alignment@property RC@type String@value 'rc'@static**/PositionAlign.RC = 'rc';/**Constant used to specify the bottom edge, center point for alignment@property BC@type String@value 'bc'@static**/PositionAlign.BC = 'bc';/**Constant used to specify the left edge, center point for alignment@property LC@type String@value 'lc'@static**/PositionAlign.LC = 'lc';/**Constant used to specify the center of widget/node/viewport for alignment@property CC@type String@value 'cc'@static*/PositionAlign.CC = 'cc';PositionAlign.prototype = {// -- Protected Properties -------------------------------------------------initializer : function() {if (!this._posNode) {Y.error('WidgetPosition needs to be added to the Widget, ' +'before WidgetPositionAlign is added');}Y.after(this._bindUIPosAlign, this, 'bindUI');Y.after(this._syncUIPosAlign, this, 'syncUI');},/**Holds the alignment-syncing event handles.@property _posAlignUIHandles@type Array@default null@protected**/_posAlignUIHandles: null,// -- Lifecycle Methods ----------------------------------------------------destructor: function () {this._detachPosAlignUIHandles();},/**Bind event listeners responsible for updating the UI state in response tothe widget's position-align related state changes.This method is invoked after `bindUI` has been invoked for the `Widget`class using the AOP infrastructure.@method _bindUIPosAlign@protected**/_bindUIPosAlign: function () {this.after('alignChange', this._afterAlignChange);this.after('alignOnChange', this._afterAlignOnChange);this.after('visibleChange', this._syncUIPosAlign);},/**Synchronizes the current `align` Attribute value to the DOM.This method is invoked after `syncUI` has been invoked for the `Widget`class using the AOP infrastructure.@method _syncUIPosAlign@protected**/_syncUIPosAlign: function () {var align = this.get(ALIGN);this._uiSetVisiblePosAlign(this.get(VISIBLE));if (align) {this._uiSetAlign(align.node, align.points);}},// -- Public Methods -------------------------------------------------------/**Aligns this widget to the provided `Node` (or viewport) using the providedpoints. This method can be invoked with no arguments which will cause thewidget's current `align` Attribute value to be synced to the DOM.@example Aligning to the top-left corner of the `<body>`:myWidget.align('body',[Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.TR]);@method align@param {Node|String|null} [node] A reference (or selector String) for the`Node` which with the widget is to be aligned. If null is passed in, thewidget will be aligned with the viewport.@param {Array[2]} [points] A two item array specifying the points on thewidget and `Node`/viewport which will to be aligned. The first entry isthe point on the widget, and the second entry is the point on the`Node`/viewport. Valid point references are defined as static constants onthe `WidgetPositionAlign` extension.@chainable**/align: function (node, points) {if (arguments.length) {// Set the `align` Attribute.this.set(ALIGN, {node : node,points: points});} else {// Sync the current `align` Attribute value to the DOM.this._syncUIPosAlign();}return this;},/**Centers the widget in the viewport, or if a `Node` is passed in, it willbe centered to that `Node`.@method centered@param {Node|String} [node] A `Node` reference or selector String definingthe `Node` which the widget should be centered. If a `Node` is not passedin, then the widget will be centered to the viewport.@chainable**/centered: function (node) {return this.align(node, [PositionAlign.CC, PositionAlign.CC]);},// -- Protected Methods ----------------------------------------------------/**Default setter for `center` Attribute changes. Sets up the appropriatevalue, and passes it through the to the align attribute.@method _setAlignCenter@param {Boolean|Node} val The Attribute value being set.@return {Boolean|Node} the value passed in.@protected**/_setAlignCenter: function (val) {if (val) {this.set(ALIGN, {node : val === true ? null : val,points: [PositionAlign.CC, PositionAlign.CC]});}return val;},/**Updates the UI to reflect the `align` value passed in.**Note:** See the `align` Attribute documentation, for the Object structureexpected.@method _uiSetAlign@param {Node|String|null} [node] The node to align to, or null to indicatethe viewport.@param {Array} points The alignment points.@protected**/_uiSetAlign: function (node, points) {if ( ! Lang.isArray(points) || points.length !== 2) {Y.error('align: Invalid Points Arguments');return;}var nodeRegion = this._getRegion(node),widgetPoint, nodePoint, xy;if ( ! nodeRegion) {// No-op, nothing to align to.return;}widgetPoint = points[0];nodePoint = points[1];// TODO: Optimize KWeight - Would lookup table help?switch (nodePoint) {case PositionAlign.TL:xy = [nodeRegion.left, nodeRegion.top];break;case PositionAlign.TR:xy = [nodeRegion.right, nodeRegion.top];break;case PositionAlign.BL:xy = [nodeRegion.left, nodeRegion.bottom];break;case PositionAlign.BR:xy = [nodeRegion.right, nodeRegion.bottom];break;case PositionAlign.TC:xy = [nodeRegion.left + Math.floor(nodeRegion.width / 2),nodeRegion.top];break;case PositionAlign.BC:xy = [nodeRegion.left + Math.floor(nodeRegion.width / 2),nodeRegion.bottom];break;case PositionAlign.LC:xy = [nodeRegion.left,nodeRegion.top + Math.floor(nodeRegion.height / 2)];break;case PositionAlign.RC:xy = [nodeRegion.right,nodeRegion.top + Math.floor(nodeRegion.height / 2)];break;case PositionAlign.CC:xy = [nodeRegion.left + Math.floor(nodeRegion.width / 2),nodeRegion.top + Math.floor(nodeRegion.height / 2)];break;default:break;}if (xy) {this._doAlign(widgetPoint, xy[0], xy[1]);}},/**Attaches or detaches alignment-syncing event handlers based on the widget's`visible` Attribute state.@method _uiSetVisiblePosAlign@param {Boolean} visible The current value of the widget's `visible`Attribute.@protected**/_uiSetVisiblePosAlign: function (visible) {if (visible) {this._attachPosAlignUIHandles();} else {this._detachPosAlignUIHandles();}},/**Attaches the alignment-syncing event handlers.@method _attachPosAlignUIHandles@protected**/_attachPosAlignUIHandles: function () {if (this._posAlignUIHandles) {// No-op if we have already setup the event handlers.return;}var bb = this.get(BOUNDING_BOX),syncAlign = Y.bind(this._syncUIPosAlign, this),handles = [];Y.Array.each(this.get(ALIGN_ON), function (o) {var event = o.eventName,node = Y.one(o.node) || bb;if (event) {handles.push(node.on(event, syncAlign));}});this._posAlignUIHandles = handles;},/**Detaches the alignment-syncing event handlers.@method _detachPosAlignUIHandles@protected**/_detachPosAlignUIHandles: function () {var handles = this._posAlignUIHandles;if (handles) {new Y.EventHandle(handles).detach();this._posAlignUIHandles = null;}},// -- Private Methods ------------------------------------------------------/**Helper method, used to align the given point on the widget, with the XY pagecoordinates provided.@method _doAlign@param {String} widgetPoint Supported point constant(e.g. WidgetPositionAlign.TL)@param {Number} x X page coordinate to align to.@param {Number} y Y page coordinate to align to.@private**/_doAlign: function (widgetPoint, x, y) {var widgetNode = this._posNode,xy;switch (widgetPoint) {case PositionAlign.TL:xy = [x, y];break;case PositionAlign.TR:xy = [x - widgetNode.get(OFFSET_WIDTH),y];break;case PositionAlign.BL:xy = [x,y - widgetNode.get(OFFSET_HEIGHT)];break;case PositionAlign.BR:xy = [x - widgetNode.get(OFFSET_WIDTH),y - widgetNode.get(OFFSET_HEIGHT)];break;case PositionAlign.TC:xy = [x - (widgetNode.get(OFFSET_WIDTH) / 2),y];break;case PositionAlign.BC:xy = [x - (widgetNode.get(OFFSET_WIDTH) / 2),y - widgetNode.get(OFFSET_HEIGHT)];break;case PositionAlign.LC:xy = [x,y - (widgetNode.get(OFFSET_HEIGHT) / 2)];break;case PositionAlign.RC:xy = [x - widgetNode.get(OFFSET_WIDTH),y - (widgetNode.get(OFFSET_HEIGHT) / 2)];break;case PositionAlign.CC:xy = [x - (widgetNode.get(OFFSET_WIDTH) / 2),y - (widgetNode.get(OFFSET_HEIGHT) / 2)];break;default:break;}if (xy) {this.move(xy);}},/**Returns the region of the passed-in `Node`, or the viewport region ifcalling with passing in a `Node`.@method _getRegion@param {Node} [node] The node to get the region of.@return {Object} The node's region.@private**/_getRegion: function (node) {var nodeRegion;if ( ! node) {nodeRegion = this._posNode.get(VIEWPORT_REGION);} else {node = Y.Node.one(node);if (node) {nodeRegion = node.get(REGION);}}return nodeRegion;},// -- Protected Event Handlers ---------------------------------------------/**Handles `alignChange` events by updating the UI in response to `align`Attribute changes.@method _afterAlignChange@param {EventFacade} e@protected**/_afterAlignChange: function (e) {var align = e.newVal;if (align) {this._uiSetAlign(align.node, align.points);}},/**Handles `alignOnChange` events by updating the alignment-syncing eventhandlers.@method _afterAlignOnChange@param {EventFacade} e@protected**/_afterAlignOnChange: function(e) {this._detachPosAlignUIHandles();if (this.get(VISIBLE)) {this._attachPosAlignUIHandles();}}};Y.WidgetPositionAlign = PositionAlign;}, '3.18.1', {"requires": ["widget-position"]});