[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/node-flick/ -> node-flick.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('node-flick', function (Y, NAME) {
   9  
  10  /**
  11   * Provide a simple Flick plugin, which can be used along with the "flick" gesture event, to
  12   * animate the motion of the host node in response to a (mouse or touch) flick gesture.
  13   *
  14   * <p>The current implementation is designed to move the node, relative to the bounds of a parent node and is suitable
  15   * for scroll/carousel type implementations. Future versions will remove that constraint, to allow open ended movement within
  16   * the document.</p>
  17   *
  18   * @module node-flick
  19   */
  20  
  21      var HOST = "host",
  22          PARENT_NODE = "parentNode",
  23          BOUNDING_BOX = "boundingBox",
  24          OFFSET_HEIGHT = "offsetHeight",
  25          OFFSET_WIDTH = "offsetWidth",
  26          SCROLL_HEIGHT = "scrollHeight",
  27          SCROLL_WIDTH = "scrollWidth",
  28          BOUNCE = "bounce",
  29          MIN_DISTANCE = "minDistance",
  30          MIN_VELOCITY = "minVelocity",
  31          BOUNCE_DISTANCE = "bounceDistance",
  32          DECELERATION = "deceleration",
  33          STEP = "step",
  34          DURATION = "duration",
  35          EASING = "easing",
  36          FLICK = "flick",
  37  
  38          getClassName = Y.ClassNameManager.getClassName;
  39  
  40      /**
  41       * A plugin class which can be used to animate the motion of a node, in response to a flick gesture.
  42       *
  43       * @class Flick
  44       * @namespace Plugin
  45       * @param {Object} config The initial attribute values for the plugin
  46       */
  47      function Flick(config) {
  48          Flick.superclass.constructor.apply(this, arguments);
  49      }
  50  
  51      Flick.ATTRS = {
  52  
  53          /**
  54           * Drag coefficent for inertial scrolling. The closer to 1 this
  55           * value is, the less friction during scrolling.
  56           *
  57           * @attribute deceleration
  58           * @default 0.98
  59           */
  60          deceleration : {
  61              value: 0.98
  62          },
  63  
  64          /**
  65           * Drag coefficient for intertial scrolling at the upper
  66           * and lower boundaries of the scrollview. Set to 0 to
  67           * disable "rubber-banding".
  68           *
  69           * @attribute bounce
  70           * @type Number
  71           * @default 0.7
  72           */
  73          bounce : {
  74              value: 0.7
  75          },
  76  
  77          /**
  78           * The bounce distance in pixels
  79           *
  80           * @attribute bounceDistance
  81           * @type Number
  82           * @default 150
  83           */
  84          bounceDistance : {
  85              value: 150
  86          },
  87  
  88          /**
  89           * The minimum flick gesture velocity (px/ms) at which to trigger the flick response
  90           *
  91           * @attribute minVelocity
  92           * @type Number
  93           * @default 0
  94           */
  95          minVelocity : {
  96              value: 0
  97          },
  98  
  99          /**
 100           * The minimum flick gesture distance (px) for which to trigger the flick response
 101           *
 102           * @attribute minVelocity
 103           * @type Number
 104           * @default 10
 105           */
 106          minDistance : {
 107              value: 10
 108          },
 109  
 110          /**
 111           * The constraining box relative to which the flick animation and bounds should be calculated.
 112           *
 113           * @attribute boundingBox
 114           * @type Node
 115           * @default parentNode
 116           */
 117          boundingBox : {
 118              valueFn : function() {
 119                  return this.get(HOST).get(PARENT_NODE);
 120              }
 121          },
 122  
 123          /**
 124           * Time between flick animation frames.
 125           *
 126           * @attribute step
 127           * @type Number
 128           * @default 10
 129           */
 130          step : {
 131              value:10
 132          },
 133  
 134          /**
 135           * The custom duration to apply to the flick animation. By default,
 136           * the animation duration is controlled by the deceleration factor.
 137           *
 138           * @attribute duration
 139           * @type Number
 140           * @default null
 141           */
 142          duration : {
 143              value:null
 144          },
 145  
 146          /**
 147           * The custom transition easing to use for the flick animation. If not
 148           * provided defaults to internally to Flick.EASING, or Flick.SNAP_EASING based
 149           * on whether or not we're animating the flick or bounce step.
 150           *
 151           * @attribute easing
 152           * @type String
 153           * @default null
 154           */
 155          easing : {
 156              value:null
 157          }
 158      };
 159  
 160      /**
 161       * The NAME of the Flick class. Used to prefix events generated
 162       * by the plugin.
 163       *
 164       * @property NAME
 165       * @static
 166       * @type String
 167       * @default "pluginFlick"
 168       */
 169      Flick.NAME = "pluginFlick";
 170  
 171      /**
 172       * The namespace for the plugin. This will be the property on the node, which will
 173       * reference the plugin instance, when it's plugged in.
 174       *
 175       * @property NS
 176       * @static
 177       * @type String
 178       * @default "flick"
 179       */
 180      Flick.NS = "flick";
 181  
 182      Y.extend(Flick, Y.Plugin.Base, {
 183  
 184          /**
 185           * The initializer lifecycle implementation.
 186           *
 187           * @method initializer
 188           * @param {Object} config The user configuration for the plugin
 189           */
 190          initializer : function(config) {
 191              this._node = this.get(HOST);
 192  
 193              this._renderClasses();
 194              this.setBounds();
 195  
 196              this._node.on(FLICK, Y.bind(this._onFlick, this), {
 197                  minDistance : this.get(MIN_DISTANCE),
 198                  minVelocity : this.get(MIN_VELOCITY)
 199              });
 200          },
 201  
 202          /**
 203           * Sets the min/max boundaries for the flick animation,
 204           * based on the boundingBox dimensions.
 205           *
 206           * @method setBounds
 207           */
 208          setBounds : function () {
 209              var box = this.get(BOUNDING_BOX),
 210                  node = this._node,
 211  
 212                  boxHeight = box.get(OFFSET_HEIGHT),
 213                  boxWidth = box.get(OFFSET_WIDTH),
 214  
 215                  contentHeight = node.get(SCROLL_HEIGHT),
 216                  contentWidth = node.get(SCROLL_WIDTH);
 217  
 218              if (contentHeight > boxHeight) {
 219                  this._maxY = contentHeight - boxHeight;
 220                  this._minY = 0;
 221                  this._scrollY = true;
 222              }
 223  
 224              if (contentWidth > boxWidth) {
 225                  this._maxX = contentWidth - boxWidth;
 226                  this._minX = 0;
 227                  this._scrollX = true;
 228              }
 229  
 230              this._x = this._y = 0;
 231  
 232              node.set("top", this._y + "px");
 233              node.set("left", this._x + "px");
 234          },
 235  
 236          /**
 237           * Adds the CSS classes, necessary to set up overflow/position properties on the
 238           * node and boundingBox.
 239           *
 240           * @method _renderClasses
 241           * @protected
 242           */
 243          _renderClasses : function() {
 244              this.get(BOUNDING_BOX).addClass(Flick.CLASS_NAMES.box);
 245              this._node.addClass(Flick.CLASS_NAMES.content);
 246          },
 247  
 248          /**
 249           * The flick event listener. Kicks off the flick animation.
 250           *
 251           * @method _onFlick
 252           * @param e {EventFacade} The flick event facade, containing e.flick.distance, e.flick.velocity etc.
 253           * @protected
 254           */
 255          _onFlick: function(e) {
 256              this._v = e.flick.velocity;
 257              this._flick = true;
 258              this._flickAnim();
 259          },
 260  
 261          /**
 262           * Executes a single frame in the flick animation
 263           *
 264           * @method _flickFrame
 265           * @protected
 266           */
 267          _flickAnim: function() {
 268  
 269              var y = this._y,
 270                  x = this._x,
 271  
 272                  maxY = this._maxY,
 273                  minY = this._minY,
 274                  maxX = this._maxX,
 275                  minX = this._minX,
 276                  velocity = this._v,
 277  
 278                  step = this.get(STEP),
 279                  deceleration = this.get(DECELERATION),
 280                  bounce = this.get(BOUNCE);
 281  
 282              this._v = (velocity * deceleration);
 283  
 284              this._snapToEdge = false;
 285  
 286              if (this._scrollX) {
 287                  x = x - (velocity * step);
 288              }
 289  
 290              if (this._scrollY) {
 291                  y = y - (velocity * step);
 292              }
 293  
 294              if (Math.abs(velocity).toFixed(4) <= Flick.VELOCITY_THRESHOLD) {
 295  
 296                  this._flick = false;
 297  
 298                  this._killTimer(!(this._exceededYBoundary || this._exceededXBoundary));
 299  
 300                  if (this._scrollX) {
 301                      if (x < minX) {
 302                          this._snapToEdge = true;
 303                          this._setX(minX);
 304                      } else if (x > maxX) {
 305                          this._snapToEdge = true;
 306                          this._setX(maxX);
 307                      }
 308                  }
 309  
 310                  if (this._scrollY) {
 311                      if (y < minY) {
 312                          this._snapToEdge = true;
 313                          this._setY(minY);
 314                      } else if (y > maxY) {
 315                          this._snapToEdge = true;
 316                          this._setY(maxY);
 317                      }
 318                  }
 319  
 320              } else {
 321  
 322                  if (this._scrollX && (x < minX || x > maxX)) {
 323                      this._exceededXBoundary = true;
 324                      this._v *= bounce;
 325                  }
 326  
 327                  if (this._scrollY && (y < minY || y > maxY)) {
 328                      this._exceededYBoundary = true;
 329                      this._v *= bounce;
 330                  }
 331  
 332                  if (this._scrollX) {
 333                      this._setX(x);
 334                  }
 335  
 336                  if (this._scrollY) {
 337                      this._setY(y);
 338                  }
 339  
 340                  this._flickTimer = Y.later(step, this, this._flickAnim);
 341              }
 342          },
 343  
 344          /**
 345           * Internal utility method to set the X offset position
 346           *
 347           * @method _setX
 348           * @param {Number} val
 349           * @private
 350           */
 351          _setX : function(val) {
 352              this._move(val, null, this.get(DURATION), this.get(EASING));
 353          },
 354  
 355          /**
 356           * Internal utility method to set the Y offset position
 357           *
 358           * @method _setY
 359           * @param {Number} val
 360           * @private
 361           */
 362          _setY : function(val) {
 363              this._move(null, val, this.get(DURATION), this.get(EASING));
 364          },
 365  
 366          /**
 367           * Internal utility method to move the node to a given XY position,
 368           * using transitions, if specified.
 369           *
 370           * @method _move
 371           * @param {Number} x The X offset position
 372           * @param {Number} y The Y offset position
 373           * @param {Number} duration The duration to use for the transition animation
 374           * @param {String} easing The easing to use for the transition animation.
 375           *
 376           * @private
 377           */
 378          _move: function(x, y, duration, easing) {
 379  
 380              if (x !== null) {
 381                  x = this._bounce(x);
 382              } else {
 383                  x = this._x;
 384              }
 385  
 386              if (y !== null) {
 387                  y = this._bounce(y);
 388              } else {
 389                  y = this._y;
 390              }
 391  
 392              duration = duration || this._snapToEdge ? Flick.SNAP_DURATION : 0;
 393              easing = easing || this._snapToEdge ? Flick.SNAP_EASING : Flick.EASING;
 394  
 395              this._x = x;
 396              this._y = y;
 397  
 398              this._anim(x, y, duration, easing);
 399          },
 400  
 401          /**
 402           * Internal utility method to perform the transition step
 403           *
 404           * @method _anim
 405           * @param {Number} x The X offset position
 406           * @param {Number} y The Y offset position
 407           * @param {Number} duration The duration to use for the transition animation
 408           * @param {String} easing The easing to use for the transition animation.
 409           *
 410           * @private
 411           */
 412          _anim : function(x, y, duration, easing) {
 413              var xn = x * -1,
 414                  yn = y * -1,
 415  
 416                  transition = {
 417                      duration : duration / 1000,
 418                      easing : easing
 419                  };
 420  
 421  
 422              if (Y.Transition.useNative) {
 423                  transition.transform = 'translate('+ (xn) + 'px,' + (yn) +'px)';
 424              } else {
 425                  transition.left = xn + 'px';
 426                  transition.top = yn + 'px';
 427              }
 428  
 429              this._node.transition(transition);
 430          },
 431  
 432          /**
 433           * Internal utility method to constrain the offset value
 434           * based on the bounce criteria.
 435           *
 436           * @method _bounce
 437           * @param {Number} x The offset value to constrain.
 438           * @param {Number} max The max offset value.
 439           *
 440           * @private
 441           */
 442          _bounce : function(val, max) {
 443              var bounce = this.get(BOUNCE),
 444                  dist = this.get(BOUNCE_DISTANCE),
 445                  min = bounce ? -dist : 0;
 446  
 447              max = bounce ? max + dist : max;
 448  
 449              if(!bounce) {
 450                  if(val < min) {
 451                      val = min;
 452                  } else if(val > max) {
 453                      val = max;
 454                  }
 455              }
 456              return val;
 457          },
 458  
 459          /**
 460           * Stop the animation timer
 461           *
 462           * @method _killTimer
 463           * @private
 464           */
 465          _killTimer: function() {
 466              if(this._flickTimer) {
 467                  this._flickTimer.cancel();
 468              }
 469          }
 470  
 471      }, {
 472  
 473          /**
 474           * The threshold used to determine when the decelerated velocity of the node
 475           * is practically 0.
 476           *
 477           * @property VELOCITY_THRESHOLD
 478           * @static
 479           * @type Number
 480           * @default 0.015
 481           */
 482          VELOCITY_THRESHOLD : 0.015,
 483  
 484          /**
 485           * The duration to use for the bounce snap-back transition
 486           *
 487           * @property SNAP_DURATION
 488           * @static
 489           * @type Number
 490           * @default 400
 491           */
 492           SNAP_DURATION : 400,
 493  
 494          /**
 495           * The default easing to use for the main flick movement transition
 496           *
 497           * @property EASING
 498           * @static
 499           * @type String
 500           * @default 'cubic-bezier(0, 0.1, 0, 1.0)'
 501           */
 502          EASING : 'cubic-bezier(0, 0.1, 0, 1.0)',
 503  
 504          /**
 505           * The default easing to use for the bounce snap-back transition
 506           *
 507           * @property SNAP_EASING
 508           * @static
 509           * @type String
 510           * @default 'ease-out'
 511           */
 512          SNAP_EASING : 'ease-out',
 513  
 514          /**
 515           * The default CSS class names used by the plugin
 516           *
 517           * @property CLASS_NAMES
 518           * @static
 519           * @type Object
 520           */
 521          CLASS_NAMES : {
 522              box: getClassName(Flick.NS),
 523              content: getClassName(Flick.NS, "content")
 524          }
 525      });
 526  
 527      Y.Plugin.Flick = Flick;
 528  
 529  
 530  }, '3.17.2', {"requires": ["classnamemanager", "transition", "event-flick", "plugin"], "skinnable": true});


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