src/cm/media/js/lib/yui/yui3-3.15.0/build/widget-position-align/widget-position-align-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('widget-position-align', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4 Provides extended/advanced XY positioning support for Widgets, through an
       
     5 extension.
       
     6 
       
     7 It builds on top of the `widget-position` module, to provide alignment and
       
     8 centering support. Future releases aim to add constrained and fixed positioning
       
     9 support.
       
    10 
       
    11 @module widget-position-align
       
    12 **/
       
    13 var Lang = Y.Lang,
       
    14 
       
    15     ALIGN        = 'align',
       
    16     ALIGN_ON     = 'alignOn',
       
    17 
       
    18     VISIBLE      = 'visible',
       
    19     BOUNDING_BOX = 'boundingBox',
       
    20 
       
    21     OFFSET_WIDTH    = 'offsetWidth',
       
    22     OFFSET_HEIGHT   = 'offsetHeight',
       
    23     REGION          = 'region',
       
    24     VIEWPORT_REGION = 'viewportRegion';
       
    25 
       
    26 /**
       
    27 Widget extension, which can be used to add extended XY positioning support to
       
    28 the base Widget class, through the `Base.create` method.
       
    29 
       
    30 **Note:** This extension requires that the `WidgetPosition` extension be added
       
    31 to the Widget (before `WidgetPositionAlign`, if part of the same extension list
       
    32 passed to `Base.build`).
       
    33 
       
    34 @class WidgetPositionAlign
       
    35 @param {Object} config User configuration object.
       
    36 @constructor
       
    37 **/
       
    38 function PositionAlign (config) {}
       
    39 
       
    40 PositionAlign.ATTRS = {
       
    41 
       
    42     /**
       
    43     The alignment configuration for this widget.
       
    44 
       
    45     The `align` attribute is used to align a reference point on the widget, with
       
    46     the reference point on another `Node`, or the viewport. The object which
       
    47     `align` expects has the following properties:
       
    48 
       
    49       * __`node`__: The `Node` to which the widget is to be aligned. If set to
       
    50         `null`, or not provided, the widget is aligned to the viewport.
       
    51 
       
    52       * __`points`__: A two element Array, defining the two points on the widget
       
    53         and `Node`/viewport which are to be aligned. The first element is the
       
    54         point on the widget, and the second element is the point on the
       
    55         `Node`/viewport. Supported alignment points are defined as static
       
    56         properties on `WidgetPositionAlign`.
       
    57 
       
    58     @example Aligns the top-right corner of the widget with the top-left corner
       
    59     of the viewport:
       
    60 
       
    61         myWidget.set('align', {
       
    62             points: [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.TL]
       
    63         });
       
    64 
       
    65     @attribute align
       
    66     @type Object
       
    67     @default null
       
    68     **/
       
    69     align: {
       
    70         value: null
       
    71     },
       
    72 
       
    73     /**
       
    74     A convenience Attribute, which can be used as a shortcut for the `align`
       
    75     Attribute.
       
    76 
       
    77     If set to `true`, the widget is centered in the viewport. If set to a `Node`
       
    78     reference or valid selector String, the widget will be centered within the
       
    79     `Node`. If set to `false`, no center positioning is applied.
       
    80 
       
    81     @attribute centered
       
    82     @type Boolean|Node
       
    83     @default false
       
    84     **/
       
    85     centered: {
       
    86         setter : '_setAlignCenter',
       
    87         lazyAdd:false,
       
    88         value  :false
       
    89     },
       
    90 
       
    91     /**
       
    92     An Array of Objects corresponding to the `Node`s and events that will cause
       
    93     the alignment of this widget to be synced to the DOM.
       
    94 
       
    95     The `alignOn` Attribute is expected to be an Array of Objects with the
       
    96     following properties:
       
    97 
       
    98       * __`eventName`__: The String event name to listen for.
       
    99 
       
   100       * __`node`__: The optional `Node` that will fire the event, it can be a
       
   101         `Node` reference or a selector String. This will default to the widget's
       
   102         `boundingBox`.
       
   103 
       
   104     @example Sync this widget's alignment on window resize:
       
   105 
       
   106         myWidget.set('alignOn', [
       
   107             {
       
   108                 node     : Y.one('win'),
       
   109                 eventName: 'resize'
       
   110             }
       
   111         ]);
       
   112 
       
   113     @attribute alignOn
       
   114     @type Array
       
   115     @default []
       
   116     **/
       
   117     alignOn: {
       
   118         value    : [],
       
   119         validator: Y.Lang.isArray
       
   120     }
       
   121 };
       
   122 
       
   123 /**
       
   124 Constant used to specify the top-left corner for alignment
       
   125 
       
   126 @property TL
       
   127 @type String
       
   128 @value 'tl'
       
   129 @static
       
   130 **/
       
   131 PositionAlign.TL = 'tl';
       
   132 
       
   133 /**
       
   134 Constant used to specify the top-right corner for alignment
       
   135 
       
   136 @property TR
       
   137 @type String
       
   138 @value 'tr'
       
   139 @static
       
   140 **/
       
   141 PositionAlign.TR = 'tr';
       
   142 
       
   143 /**
       
   144 Constant used to specify the bottom-left corner for alignment
       
   145 
       
   146 @property BL
       
   147 @type String
       
   148 @value 'bl'
       
   149 @static
       
   150 **/
       
   151 PositionAlign.BL = 'bl';
       
   152 
       
   153 /**
       
   154 Constant used to specify the bottom-right corner for alignment
       
   155 
       
   156 @property BR
       
   157 @type String
       
   158 @value 'br'
       
   159 @static
       
   160 **/
       
   161 PositionAlign.BR = 'br';
       
   162 
       
   163 /**
       
   164 Constant used to specify the top edge-center point for alignment
       
   165 
       
   166 @property TC
       
   167 @type String
       
   168 @value 'tc'
       
   169 @static
       
   170 **/
       
   171 PositionAlign.TC = 'tc';
       
   172 
       
   173 /**
       
   174 Constant used to specify the right edge, center point for alignment
       
   175 
       
   176 @property RC
       
   177 @type String
       
   178 @value 'rc'
       
   179 @static
       
   180 **/
       
   181 PositionAlign.RC = 'rc';
       
   182 
       
   183 /**
       
   184 Constant used to specify the bottom edge, center point for alignment
       
   185 
       
   186 @property BC
       
   187 @type String
       
   188 @value 'bc'
       
   189 @static
       
   190 **/
       
   191 PositionAlign.BC = 'bc';
       
   192 
       
   193 /**
       
   194 Constant used to specify the left edge, center point for alignment
       
   195 
       
   196 @property LC
       
   197 @type String
       
   198 @value 'lc'
       
   199 @static
       
   200 **/
       
   201 PositionAlign.LC = 'lc';
       
   202 
       
   203 /**
       
   204 Constant used to specify the center of widget/node/viewport for alignment
       
   205 
       
   206 @property CC
       
   207 @type String
       
   208 @value 'cc'
       
   209 @static
       
   210 */
       
   211 PositionAlign.CC = 'cc';
       
   212 
       
   213 PositionAlign.prototype = {
       
   214     // -- Protected Properties -------------------------------------------------
       
   215 
       
   216 
       
   217     initializer : function() {
       
   218         if (!this._posNode) {
       
   219             Y.error('WidgetPosition needs to be added to the Widget, ' +
       
   220                 'before WidgetPositionAlign is added');
       
   221         }
       
   222 
       
   223         Y.after(this._bindUIPosAlign, this, 'bindUI');
       
   224         Y.after(this._syncUIPosAlign, this, 'syncUI');
       
   225     },
       
   226 
       
   227     /**
       
   228     Holds the alignment-syncing event handles.
       
   229 
       
   230     @property _posAlignUIHandles
       
   231     @type Array
       
   232     @default null
       
   233     @protected
       
   234     **/
       
   235     _posAlignUIHandles: null,
       
   236 
       
   237     // -- Lifecycle Methods ----------------------------------------------------
       
   238 
       
   239     destructor: function () {
       
   240         this._detachPosAlignUIHandles();
       
   241     },
       
   242 
       
   243     /**
       
   244     Bind event listeners responsible for updating the UI state in response to
       
   245     the widget's position-align related state changes.
       
   246 
       
   247     This method is invoked after `bindUI` has been invoked for the `Widget`
       
   248     class using the AOP infrastructure.
       
   249 
       
   250     @method _bindUIPosAlign
       
   251     @protected
       
   252     **/
       
   253     _bindUIPosAlign: function () {
       
   254         this.after('alignChange', this._afterAlignChange);
       
   255         this.after('alignOnChange', this._afterAlignOnChange);
       
   256         this.after('visibleChange', this._syncUIPosAlign);
       
   257     },
       
   258 
       
   259     /**
       
   260     Synchronizes the current `align` Attribute value to the DOM.
       
   261 
       
   262     This method is invoked after `syncUI` has been invoked for the `Widget`
       
   263     class using the AOP infrastructure.
       
   264 
       
   265     @method _syncUIPosAlign
       
   266     @protected
       
   267     **/
       
   268     _syncUIPosAlign: function () {
       
   269         var align = this.get(ALIGN);
       
   270 
       
   271         this._uiSetVisiblePosAlign(this.get(VISIBLE));
       
   272 
       
   273         if (align) {
       
   274             this._uiSetAlign(align.node, align.points);
       
   275         }
       
   276     },
       
   277 
       
   278     // -- Public Methods -------------------------------------------------------
       
   279 
       
   280     /**
       
   281     Aligns this widget to the provided `Node` (or viewport) using the provided
       
   282     points. This method can be invoked with no arguments which will cause the
       
   283     widget's current `align` Attribute value to be synced to the DOM.
       
   284 
       
   285     @example Aligning to the top-left corner of the `<body>`:
       
   286 
       
   287         myWidget.align('body',
       
   288             [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.TR]);
       
   289 
       
   290     @method align
       
   291     @param {Node|String|null} [node] A reference (or selector String) for the
       
   292       `Node` which with the widget is to be aligned. If null is passed in, the
       
   293       widget will be aligned with the viewport.
       
   294     @param {Array[2]} [points] A two item array specifying the points on the
       
   295       widget and `Node`/viewport which will to be aligned. The first entry is
       
   296       the point on the widget, and the second entry is the point on the
       
   297       `Node`/viewport. Valid point references are defined as static constants on
       
   298       the `WidgetPositionAlign` extension.
       
   299     @chainable
       
   300     **/
       
   301     align: function (node, points) {
       
   302         if (arguments.length) {
       
   303             // Set the `align` Attribute.
       
   304             this.set(ALIGN, {
       
   305                 node  : node,
       
   306                 points: points
       
   307             });
       
   308         } else {
       
   309             // Sync the current `align` Attribute value to the DOM.
       
   310             this._syncUIPosAlign();
       
   311         }
       
   312 
       
   313         return this;
       
   314     },
       
   315 
       
   316     /**
       
   317     Centers the widget in the viewport, or if a `Node` is passed in, it will
       
   318     be centered to that `Node`.
       
   319 
       
   320     @method centered
       
   321     @param {Node|String} [node] A `Node` reference or selector String defining
       
   322       the `Node` which the widget should be centered. If a `Node` is not  passed
       
   323       in, then the widget will be centered to the viewport.
       
   324     @chainable
       
   325     **/
       
   326     centered: function (node) {
       
   327         return this.align(node, [PositionAlign.CC, PositionAlign.CC]);
       
   328     },
       
   329 
       
   330     // -- Protected Methods ----------------------------------------------------
       
   331 
       
   332     /**
       
   333     Default setter for `center` Attribute changes. Sets up the appropriate
       
   334     value, and passes it through the to the align attribute.
       
   335 
       
   336     @method _setAlignCenter
       
   337     @param {Boolean|Node} val The Attribute value being set.
       
   338     @return {Boolean|Node} the value passed in.
       
   339     @protected
       
   340     **/
       
   341     _setAlignCenter: function (val) {
       
   342         if (val) {
       
   343             this.set(ALIGN, {
       
   344                 node  : val === true ? null : val,
       
   345                 points: [PositionAlign.CC, PositionAlign.CC]
       
   346             });
       
   347         }
       
   348 
       
   349         return val;
       
   350     },
       
   351 
       
   352     /**
       
   353     Updates the UI to reflect the `align` value passed in.
       
   354 
       
   355     **Note:** See the `align` Attribute documentation, for the Object structure
       
   356     expected.
       
   357 
       
   358     @method _uiSetAlign
       
   359     @param {Node|String|null} [node] The node to align to, or null to indicate
       
   360       the viewport.
       
   361     @param {Array} points The alignment points.
       
   362     @protected
       
   363     **/
       
   364     _uiSetAlign: function (node, points) {
       
   365         if ( ! Lang.isArray(points) || points.length !== 2) {
       
   366             Y.error('align: Invalid Points Arguments');
       
   367             return;
       
   368         }
       
   369 
       
   370         var nodeRegion = this._getRegion(node),
       
   371             widgetPoint, nodePoint, xy;
       
   372 
       
   373         if ( ! nodeRegion) {
       
   374             // No-op, nothing to align to.
       
   375             return;
       
   376         }
       
   377 
       
   378         widgetPoint = points[0];
       
   379         nodePoint   = points[1];
       
   380 
       
   381         // TODO: Optimize KWeight - Would lookup table help?
       
   382         switch (nodePoint) {
       
   383         case PositionAlign.TL:
       
   384             xy = [nodeRegion.left, nodeRegion.top];
       
   385             break;
       
   386 
       
   387         case PositionAlign.TR:
       
   388             xy = [nodeRegion.right, nodeRegion.top];
       
   389             break;
       
   390 
       
   391         case PositionAlign.BL:
       
   392             xy = [nodeRegion.left, nodeRegion.bottom];
       
   393             break;
       
   394 
       
   395         case PositionAlign.BR:
       
   396             xy = [nodeRegion.right, nodeRegion.bottom];
       
   397             break;
       
   398 
       
   399         case PositionAlign.TC:
       
   400             xy = [
       
   401                 nodeRegion.left + Math.floor(nodeRegion.width / 2),
       
   402                 nodeRegion.top
       
   403             ];
       
   404             break;
       
   405 
       
   406         case PositionAlign.BC:
       
   407             xy = [
       
   408                 nodeRegion.left + Math.floor(nodeRegion.width / 2),
       
   409                 nodeRegion.bottom
       
   410             ];
       
   411             break;
       
   412 
       
   413         case PositionAlign.LC:
       
   414             xy = [
       
   415                 nodeRegion.left,
       
   416                 nodeRegion.top + Math.floor(nodeRegion.height / 2)
       
   417             ];
       
   418             break;
       
   419 
       
   420         case PositionAlign.RC:
       
   421             xy = [
       
   422                 nodeRegion.right,
       
   423                 nodeRegion.top + Math.floor(nodeRegion.height / 2)
       
   424             ];
       
   425             break;
       
   426 
       
   427         case PositionAlign.CC:
       
   428             xy = [
       
   429                 nodeRegion.left + Math.floor(nodeRegion.width / 2),
       
   430                 nodeRegion.top + Math.floor(nodeRegion.height / 2)
       
   431             ];
       
   432             break;
       
   433 
       
   434         default:
       
   435             Y.log('align: Invalid Points Arguments', 'info',
       
   436                 'widget-position-align');
       
   437             break;
       
   438 
       
   439         }
       
   440 
       
   441         if (xy) {
       
   442             this._doAlign(widgetPoint, xy[0], xy[1]);
       
   443         }
       
   444     },
       
   445 
       
   446     /**
       
   447     Attaches or detaches alignment-syncing event handlers based on the widget's
       
   448     `visible` Attribute state.
       
   449 
       
   450     @method _uiSetVisiblePosAlign
       
   451     @param {Boolean} visible The current value of the widget's `visible`
       
   452       Attribute.
       
   453     @protected
       
   454     **/
       
   455     _uiSetVisiblePosAlign: function (visible) {
       
   456         if (visible) {
       
   457             this._attachPosAlignUIHandles();
       
   458         } else {
       
   459             this._detachPosAlignUIHandles();
       
   460         }
       
   461     },
       
   462 
       
   463     /**
       
   464     Attaches the alignment-syncing event handlers.
       
   465 
       
   466     @method _attachPosAlignUIHandles
       
   467     @protected
       
   468     **/
       
   469     _attachPosAlignUIHandles: function () {
       
   470         if (this._posAlignUIHandles) {
       
   471             // No-op if we have already setup the event handlers.
       
   472             return;
       
   473         }
       
   474 
       
   475         var bb        = this.get(BOUNDING_BOX),
       
   476             syncAlign = Y.bind(this._syncUIPosAlign, this),
       
   477             handles   = [];
       
   478 
       
   479         Y.Array.each(this.get(ALIGN_ON), function (o) {
       
   480             var event = o.eventName,
       
   481                 node  = Y.one(o.node) || bb;
       
   482 
       
   483             if (event) {
       
   484                 handles.push(node.on(event, syncAlign));
       
   485             }
       
   486         });
       
   487 
       
   488         this._posAlignUIHandles = handles;
       
   489     },
       
   490 
       
   491     /**
       
   492     Detaches the alignment-syncing event handlers.
       
   493 
       
   494     @method _detachPosAlignUIHandles
       
   495     @protected
       
   496     **/
       
   497     _detachPosAlignUIHandles: function () {
       
   498         var handles = this._posAlignUIHandles;
       
   499         if (handles) {
       
   500             new Y.EventHandle(handles).detach();
       
   501             this._posAlignUIHandles = null;
       
   502         }
       
   503     },
       
   504 
       
   505     // -- Private Methods ------------------------------------------------------
       
   506 
       
   507     /**
       
   508     Helper method, used to align the given point on the widget, with the XY page
       
   509     coordinates provided.
       
   510 
       
   511     @method _doAlign
       
   512     @param {String} widgetPoint Supported point constant
       
   513       (e.g. WidgetPositionAlign.TL)
       
   514     @param {Number} x X page coordinate to align to.
       
   515     @param {Number} y Y page coordinate to align to.
       
   516     @private
       
   517     **/
       
   518     _doAlign: function (widgetPoint, x, y) {
       
   519         var widgetNode = this._posNode,
       
   520             xy;
       
   521 
       
   522         switch (widgetPoint) {
       
   523         case PositionAlign.TL:
       
   524             xy = [x, y];
       
   525             break;
       
   526 
       
   527         case PositionAlign.TR:
       
   528             xy = [
       
   529                 x - widgetNode.get(OFFSET_WIDTH),
       
   530                 y
       
   531             ];
       
   532             break;
       
   533 
       
   534         case PositionAlign.BL:
       
   535             xy = [
       
   536                 x,
       
   537                 y - widgetNode.get(OFFSET_HEIGHT)
       
   538             ];
       
   539             break;
       
   540 
       
   541         case PositionAlign.BR:
       
   542             xy = [
       
   543                 x - widgetNode.get(OFFSET_WIDTH),
       
   544                 y - widgetNode.get(OFFSET_HEIGHT)
       
   545             ];
       
   546             break;
       
   547 
       
   548         case PositionAlign.TC:
       
   549             xy = [
       
   550                 x - (widgetNode.get(OFFSET_WIDTH) / 2),
       
   551                 y
       
   552             ];
       
   553             break;
       
   554 
       
   555         case PositionAlign.BC:
       
   556             xy = [
       
   557                 x - (widgetNode.get(OFFSET_WIDTH) / 2),
       
   558                 y - widgetNode.get(OFFSET_HEIGHT)
       
   559             ];
       
   560             break;
       
   561 
       
   562         case PositionAlign.LC:
       
   563             xy = [
       
   564                 x,
       
   565                 y - (widgetNode.get(OFFSET_HEIGHT) / 2)
       
   566             ];
       
   567             break;
       
   568 
       
   569         case PositionAlign.RC:
       
   570             xy = [
       
   571                 x - widgetNode.get(OFFSET_WIDTH),
       
   572                 y - (widgetNode.get(OFFSET_HEIGHT) / 2)
       
   573             ];
       
   574             break;
       
   575 
       
   576         case PositionAlign.CC:
       
   577             xy = [
       
   578                 x - (widgetNode.get(OFFSET_WIDTH) / 2),
       
   579                 y - (widgetNode.get(OFFSET_HEIGHT) / 2)
       
   580             ];
       
   581             break;
       
   582 
       
   583         default:
       
   584             Y.log('align: Invalid Points Argument', 'info',
       
   585                 'widget-position-align');
       
   586             break;
       
   587 
       
   588         }
       
   589 
       
   590         if (xy) {
       
   591             this.move(xy);
       
   592         }
       
   593     },
       
   594 
       
   595     /**
       
   596     Returns the region of the passed-in `Node`, or the viewport region if
       
   597     calling with passing in a `Node`.
       
   598 
       
   599     @method _getRegion
       
   600     @param {Node} [node] The node to get the region of.
       
   601     @return {Object} The node's region.
       
   602     @private
       
   603     **/
       
   604     _getRegion: function (node) {
       
   605         var nodeRegion;
       
   606 
       
   607         if ( ! node) {
       
   608             nodeRegion = this._posNode.get(VIEWPORT_REGION);
       
   609         } else {
       
   610             node = Y.Node.one(node);
       
   611             if (node) {
       
   612                 nodeRegion = node.get(REGION);
       
   613             }
       
   614         }
       
   615 
       
   616         return nodeRegion;
       
   617     },
       
   618 
       
   619     // -- Protected Event Handlers ---------------------------------------------
       
   620 
       
   621     /**
       
   622     Handles `alignChange` events by updating the UI in response to `align`
       
   623     Attribute changes.
       
   624 
       
   625     @method _afterAlignChange
       
   626     @param {EventFacade} e
       
   627     @protected
       
   628     **/
       
   629     _afterAlignChange: function (e) {
       
   630         var align = e.newVal;
       
   631         if (align) {
       
   632             this._uiSetAlign(align.node, align.points);
       
   633         }
       
   634     },
       
   635 
       
   636     /**
       
   637     Handles `alignOnChange` events by updating the alignment-syncing event
       
   638     handlers.
       
   639 
       
   640     @method _afterAlignOnChange
       
   641     @param {EventFacade} e
       
   642     @protected
       
   643     **/
       
   644     _afterAlignOnChange: function(e) {
       
   645         this._detachPosAlignUIHandles();
       
   646 
       
   647         if (this.get(VISIBLE)) {
       
   648             this._attachPosAlignUIHandles();
       
   649         }
       
   650     }
       
   651 };
       
   652 
       
   653 Y.WidgetPositionAlign = PositionAlign;
       
   654 
       
   655 
       
   656 }, '@VERSION@', {"requires": ["widget-position"]});