[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/widget-position-constrain/ -> widget-position-constrain-debug.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 Yahoo! Inc. All rights reserved.
   4  Licensed under the BSD License.
   5  http://yuilibrary.com/license/
   6  */
   7  
   8  YUI.add('widget-position-constrain', function (Y, NAME) {
   9  
  10  /**
  11   * Provides constrained xy positioning support for Widgets, through an extension.
  12   *
  13   * It builds on top of the widget-position module, to provide constrained positioning support.
  14   *
  15   * @module widget-position-constrain
  16   */
  17  var CONSTRAIN = "constrain",
  18      CONSTRAIN_XYCHANGE = "constrain|xyChange",
  19      CONSTRAIN_CHANGE = "constrainChange",
  20  
  21      PREVENT_OVERLAP = "preventOverlap",
  22      ALIGN = "align",
  23  
  24      EMPTY_STR = "",
  25  
  26      BINDUI = "bindUI",
  27  
  28      XY = "xy",
  29      X_COORD = "x",
  30      Y_COORD = "y",
  31  
  32      Node = Y.Node,
  33  
  34      VIEWPORT_REGION = "viewportRegion",
  35      REGION = "region",
  36  
  37      PREVENT_OVERLAP_MAP;
  38  
  39  /**
  40   * A widget extension, which can be used to add constrained xy positioning support to the base Widget class,
  41   * through the <a href="Base.html#method_build">Base.build</a> method. This extension requires that
  42   * the WidgetPosition extension be added to the Widget (before WidgetPositionConstrain, if part of the same
  43   * extension list passed to Base.build).
  44   *
  45   * @class WidgetPositionConstrain
  46   * @param {Object} User configuration object
  47   */
  48  function PositionConstrain(config) {}
  49  
  50  /**
  51   * Static property used to define the default attribute
  52   * configuration introduced by WidgetPositionConstrain.
  53   *
  54   * @property ATTRS
  55   * @type Object
  56   * @static
  57   */
  58  PositionConstrain.ATTRS = {
  59  
  60      /**
  61       * @attribute constrain
  62       * @type boolean | Node
  63       * @default null
  64       * @description The node to constrain the widget's bounding box to, when setting xy. Can also be
  65       * set to true, to constrain to the viewport.
  66       */
  67      constrain : {
  68          value: null,
  69          setter: "_setConstrain"
  70      },
  71  
  72      /**
  73       * @attribute preventOverlap
  74       * @type boolean
  75       * @description If set to true, and WidgetPositionAlign is also added to the Widget,
  76       * constrained positioning will attempt to prevent the widget's bounding box from overlapping
  77       * the element to which it has been aligned, by flipping the orientation of the alignment
  78       * for corner based alignments
  79       */
  80      preventOverlap : {
  81          value:false
  82      }
  83  };
  84  
  85  /**
  86   * @property _PREVENT_OVERLAP
  87   * @static
  88   * @protected
  89   * @type Object
  90   * @description The set of positions for which to prevent
  91   * overlap.
  92   */
  93  PREVENT_OVERLAP_MAP = PositionConstrain._PREVENT_OVERLAP = {
  94      x: {
  95          "tltr": 1,
  96          "blbr": 1,
  97          "brbl": 1,
  98          "trtl": 1
  99      },
 100      y : {
 101          "trbr": 1,
 102          "tlbl": 1,
 103          "bltl": 1,
 104          "brtr": 1
 105      }
 106  };
 107  
 108  PositionConstrain.prototype = {
 109  
 110      initializer : function() {
 111          if (!this._posNode) {
 112              Y.error("WidgetPosition needs to be added to the Widget, before WidgetPositionConstrain is added");
 113          }
 114          Y.after(this._bindUIPosConstrained, this, BINDUI);
 115      },
 116  
 117      /**
 118       * Calculates the constrained positions for the XY positions provided, using
 119       * the provided node argument is passed in. If no node value is passed in, the value of
 120       * the "constrain" attribute is used.
 121       *
 122       * @method getConstrainedXY
 123       * @param {Array} xy The xy values to constrain
 124       * @param {Node | boolean} node Optional. The node to constrain to, or true for the viewport
 125       * @return {Array} The constrained xy values
 126       */
 127      getConstrainedXY : function(xy, node) {
 128          node = node || this.get(CONSTRAIN);
 129  
 130          var constrainingRegion = this._getRegion((node === true) ? null : node),
 131              nodeRegion = this._posNode.get(REGION);
 132  
 133          return [
 134              this._constrain(xy[0], X_COORD, nodeRegion, constrainingRegion),
 135              this._constrain(xy[1], Y_COORD, nodeRegion, constrainingRegion)
 136          ];
 137      },
 138  
 139      /**
 140       * Constrains the widget's bounding box to a node (or the viewport). If xy or node are not
 141       * passed in, the current position and the value of "constrain" will be used respectively.
 142       *
 143       * The widget's position will be changed to the constrained position.
 144       *
 145       * @method constrain
 146       * @param {Array} xy Optional. The xy values to constrain
 147       * @param {Node | boolean} node Optional. The node to constrain to, or true for the viewport
 148       */
 149      constrain : function(xy, node) {
 150          var currentXY,
 151              constrainedXY,
 152              constraint = node || this.get(CONSTRAIN);
 153  
 154          if (constraint) {
 155              currentXY = xy || this.get(XY);
 156              constrainedXY = this.getConstrainedXY(currentXY, constraint);
 157  
 158              if (constrainedXY[0] !== currentXY[0] || constrainedXY[1] !== currentXY[1]) {
 159                  this.set(XY, constrainedXY, { constrained:true });
 160              }
 161          }
 162      },
 163  
 164      /**
 165       * The setter implementation for the "constrain" attribute.
 166       *
 167       * @method _setConstrain
 168       * @protected
 169       * @param {Node | boolean} val The attribute value
 170       */
 171      _setConstrain : function(val) {
 172          return (val === true) ? val : Node.one(val);
 173      },
 174  
 175      /**
 176       * The method which performs the actual constrain calculations for a given axis ("x" or "y") based
 177       * on the regions provided.
 178       *
 179       * @method _constrain
 180       * @protected
 181       *
 182       * @param {Number} val The value to constrain
 183       * @param {String} axis The axis to use for constrainment
 184       * @param {Region} nodeRegion The region of the node to constrain
 185       * @param {Region} constrainingRegion The region of the node (or viewport) to constrain to
 186       *
 187       * @return {Number} The constrained value
 188       */
 189      _constrain: function(val, axis, nodeRegion, constrainingRegion) {
 190          if (constrainingRegion) {
 191  
 192              if (this.get(PREVENT_OVERLAP)) {
 193                  val = this._preventOverlap(val, axis, nodeRegion, constrainingRegion);
 194              }
 195  
 196              var x = (axis == X_COORD),
 197  
 198                  regionSize    = (x) ? constrainingRegion.width : constrainingRegion.height,
 199                  nodeSize      = (x) ? nodeRegion.width : nodeRegion.height,
 200                  minConstraint = (x) ? constrainingRegion.left : constrainingRegion.top,
 201                  maxConstraint = (x) ? constrainingRegion.right - nodeSize : constrainingRegion.bottom - nodeSize;
 202  
 203              if (val < minConstraint || val > maxConstraint) {
 204                  if (nodeSize < regionSize) {
 205                      if (val < minConstraint) {
 206                          val = minConstraint;
 207                      } else if (val > maxConstraint) {
 208                          val = maxConstraint;
 209                      }
 210                  } else {
 211                      val = minConstraint;
 212                  }
 213              }
 214          }
 215  
 216          return val;
 217      },
 218  
 219      /**
 220       * The method which performs the preventOverlap calculations for a given axis ("x" or "y") based
 221       * on the value and regions provided.
 222       *
 223       * @method _preventOverlap
 224       * @protected
 225       *
 226       * @param {Number} val The value being constrain
 227       * @param {String} axis The axis to being constrained
 228       * @param {Region} nodeRegion The region of the node being constrained
 229       * @param {Region} constrainingRegion The region of the node (or viewport) we need to constrain to
 230       *
 231       * @return {Number} The constrained value
 232       */
 233      _preventOverlap : function(val, axis, nodeRegion, constrainingRegion) {
 234  
 235          var align = this.get(ALIGN),
 236              x = (axis === X_COORD),
 237              nodeSize,
 238              alignRegion,
 239              nearEdge,
 240              farEdge,
 241              spaceOnNearSide,
 242              spaceOnFarSide;
 243  
 244          if (align && align.points && PREVENT_OVERLAP_MAP[axis][align.points.join(EMPTY_STR)]) {
 245  
 246              alignRegion = this._getRegion(align.node);
 247  
 248              if (alignRegion) {
 249                  nodeSize        = (x) ? nodeRegion.width : nodeRegion.height;
 250                  nearEdge        = (x) ? alignRegion.left : alignRegion.top;
 251                  farEdge         = (x) ? alignRegion.right : alignRegion.bottom;
 252                  spaceOnNearSide = (x) ? alignRegion.left - constrainingRegion.left : alignRegion.top - constrainingRegion.top;
 253                  spaceOnFarSide  = (x) ? constrainingRegion.right - alignRegion.right : constrainingRegion.bottom - alignRegion.bottom;
 254              }
 255  
 256              if (val > nearEdge) {
 257                  if (spaceOnFarSide < nodeSize && spaceOnNearSide > nodeSize) {
 258                      val = nearEdge - nodeSize;
 259                  }
 260              } else {
 261                  if (spaceOnNearSide < nodeSize && spaceOnFarSide > nodeSize) {
 262                      val = farEdge;
 263                  }
 264              }
 265          }
 266  
 267          return val;
 268      },
 269  
 270      /**
 271       * Binds event listeners responsible for updating the UI state in response to
 272       * Widget constrained positioning related state changes.
 273       * <p>
 274       * This method is invoked after bindUI is invoked for the Widget class
 275       * using YUI's aop infrastructure.
 276       * </p>
 277       *
 278       * @method _bindUIPosConstrained
 279       * @protected
 280       */
 281      _bindUIPosConstrained : function() {
 282          this.after(CONSTRAIN_CHANGE, this._afterConstrainChange);
 283          this._enableConstraints(this.get(CONSTRAIN));
 284      },
 285  
 286      /**
 287       * After change listener for the "constrain" attribute, responsible
 288       * for updating the UI, in response to attribute changes.
 289       *
 290       * @method _afterConstrainChange
 291       * @protected
 292       * @param {EventFacade} e The event facade
 293       */
 294      _afterConstrainChange : function(e) {
 295          this._enableConstraints(e.newVal);
 296      },
 297  
 298      /**
 299       * Updates the UI if enabling constraints, and sets up the xyChange event listeners
 300       * to constrain whenever the widget is moved. Disabling constraints removes the listeners.
 301       *
 302       * @method _enableConstraints
 303       * @private
 304       * @param {boolean} enable Enable or disable constraints
 305       */
 306      _enableConstraints : function(enable) {
 307          if (enable) {
 308              this.constrain();
 309              this._cxyHandle = this._cxyHandle || this.on(CONSTRAIN_XYCHANGE, this._constrainOnXYChange);
 310          } else if (this._cxyHandle) {
 311              this._cxyHandle.detach();
 312              this._cxyHandle = null;
 313          }
 314      },
 315  
 316      /**
 317       * The on change listener for the "xy" attribute. Modifies the event facade's
 318       * newVal property with the constrained XY value.
 319       *
 320       * @method _constrainOnXYChange
 321       * @protected
 322       * @param {EventFacade} e The event facade for the attribute change
 323       */
 324      _constrainOnXYChange : function(e) {
 325          if (!e.constrained) {
 326              e.newVal = this.getConstrainedXY(e.newVal);
 327          }
 328      },
 329  
 330      /**
 331       * Utility method to normalize region retrieval from a node instance,
 332       * or the viewport, if no node is provided.
 333       *
 334       * @method _getRegion
 335       * @private
 336       * @param {Node} node Optional.
 337       */
 338      _getRegion : function(node) {
 339          var region;
 340          if (!node) {
 341              region = this._posNode.get(VIEWPORT_REGION);
 342          } else {
 343              node = Node.one(node);
 344              if (node) {
 345                  region = node.get(REGION);
 346              }
 347          }
 348          return region;
 349      }
 350  };
 351  
 352  Y.WidgetPositionConstrain = PositionConstrain;
 353  
 354  
 355  }, '3.17.2', {"requires": ["widget-position"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1