src/cm/media/js/lib/yui/yui3-3.15.0/build/widget-position-align/widget-position-align.js
changeset 602 e16a97fb364a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui3-3.15.0/build/widget-position-align/widget-position-align.js	Mon Mar 10 15:19:48 2014 +0100
@@ -0,0 +1,652 @@
+YUI.add('widget-position-align', function (Y, NAME) {
+
+/**
+Provides extended/advanced XY positioning support for Widgets, through an
+extension.
+
+It builds on top of the `widget-position` module, to provide alignment and
+centering support. Future releases aim to add constrained and fixed positioning
+support.
+
+@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 to
+the base Widget class, through the `Base.create` method.
+
+**Note:** This extension requires that the `WidgetPosition` extension be added
+to the Widget (before `WidgetPositionAlign`, if part of the same extension list
+passed 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, with
+    the 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 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. Supported alignment points are defined as static
+        properties on `WidgetPositionAlign`.
+
+    @example Aligns the top-right corner of the widget with the top-left corner
+    of 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 cause
+    the alignment of this widget to be synced to the DOM.
+
+    The `alignOn` Attribute is expected to be an Array of Objects with the
+    following 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 to
+    the 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 provided
+    points. This method can be invoked with no arguments which will cause the
+    widget'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, the
+      widget will be aligned with the viewport.
+    @param {Array[2]} [points] A two item array specifying the points on the
+      widget and `Node`/viewport which will to be aligned. The first entry is
+      the point on the widget, and the second entry is the point on the
+      `Node`/viewport. Valid point references are defined as static constants on
+      the `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 will
+    be centered to that `Node`.
+
+    @method centered
+    @param {Node|String} [node] A `Node` reference or selector String defining
+      the `Node` which the widget should be centered. If a `Node` is not  passed
+      in, 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 appropriate
+    value, 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 structure
+    expected.
+
+    @method _uiSetAlign
+    @param {Node|String|null} [node] The node to align to, or null to indicate
+      the 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 page
+    coordinates 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 if
+    calling 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 event
+    handlers.
+
+    @method _afterAlignOnChange
+    @param {EventFacade} e
+    @protected
+    **/
+    _afterAlignOnChange: function(e) {
+        this._detachPosAlignUIHandles();
+
+        if (this.get(VISIBLE)) {
+            this._attachPosAlignUIHandles();
+        }
+    }
+};
+
+Y.WidgetPositionAlign = PositionAlign;
+
+
+}, '@VERSION@', {"requires": ["widget-position"]});