[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/anim-base/ -> anim-base-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('anim-base', function (Y, NAME) {
   9  
  10  /**
  11  * The Animation Utility provides an API for creating advanced transitions.
  12  * @module anim
  13  */
  14  
  15  /**
  16  * Provides the base Anim class, for animating numeric properties.
  17  *
  18  * @module anim
  19  * @submodule anim-base
  20  */
  21  
  22      /**
  23       * A class for constructing animation instances.
  24       * @class Anim
  25       * @for Anim
  26       * @constructor
  27       * @extends Base
  28       */
  29  
  30      var RUNNING = 'running',
  31          START_TIME = 'startTime',
  32          ELAPSED_TIME = 'elapsedTime',
  33          /**
  34          * @for Anim
  35          * @event start
  36          * @description fires when an animation begins.
  37          * @param {Event} ev The start event.
  38          * @type Event.Custom
  39          */
  40          START = 'start',
  41  
  42          /**
  43          * @event tween
  44          * @description fires every frame of the animation.
  45          * @param {Event} ev The tween event.
  46          * @type Event.Custom
  47          */
  48          TWEEN = 'tween',
  49  
  50          /**
  51          * @event end
  52          * @description fires after the animation completes.
  53          * @param {Event} ev The end event.
  54          * @type Event.Custom
  55          */
  56          END = 'end',
  57          NODE = 'node',
  58          PAUSED = 'paused',
  59          REVERSE = 'reverse', // TODO: cleanup
  60          ITERATION_COUNT = 'iterationCount',
  61  
  62          NUM = Number;
  63  
  64      var _running = {},
  65          _timer;
  66  
  67      Y.Anim = function() {
  68          Y.Anim.superclass.constructor.apply(this, arguments);
  69          Y.Anim._instances[Y.stamp(this)] = this;
  70      };
  71  
  72      Y.Anim.NAME = 'anim';
  73  
  74      Y.Anim._instances = {};
  75  
  76      /**
  77       * Regex of properties that should use the default unit.
  78       *
  79       * @property RE_DEFAULT_UNIT
  80       * @static
  81       */
  82      Y.Anim.RE_DEFAULT_UNIT = /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i;
  83  
  84      /**
  85       * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
  86       *
  87       * @property DEFAULT_UNIT
  88       * @static
  89       */
  90      Y.Anim.DEFAULT_UNIT = 'px';
  91  
  92      Y.Anim.DEFAULT_EASING = function (t, b, c, d) {
  93          return c * t / d + b; // linear easing
  94      };
  95  
  96      /**
  97       * Time in milliseconds passed to setInterval for frame processing
  98       *
  99       * @property intervalTime
 100       * @default 20
 101       * @static
 102       */
 103      Y.Anim._intervalTime = 20;
 104  
 105      /**
 106       * Bucket for custom getters and setters
 107       *
 108       * @property behaviors
 109       * @static
 110       */
 111      Y.Anim.behaviors = {
 112          left: {
 113              get: function(anim, attr) {
 114                  return anim._getOffset(attr);
 115              }
 116          }
 117      };
 118  
 119      Y.Anim.behaviors.top = Y.Anim.behaviors.left;
 120  
 121      /**
 122       * The default setter to use when setting object properties.
 123       *
 124       * @property DEFAULT_SETTER
 125       * @static
 126       */
 127      Y.Anim.DEFAULT_SETTER = function(anim, att, from, to, elapsed, duration, fn, unit) {
 128          var node = anim._node,
 129              domNode = node._node,
 130              val = fn(elapsed, NUM(from), NUM(to) - NUM(from), duration);
 131  
 132          if (domNode) {
 133              if ('style' in domNode && (att in domNode.style || att in Y.DOM.CUSTOM_STYLES)) {
 134                  unit = unit || '';
 135                  node.setStyle(att, val + unit);
 136              } else if ('attributes' in domNode && att in domNode.attributes) {
 137                  node.setAttribute(att, val);
 138              } else if (att in domNode) {
 139                  domNode[att] = val;
 140              }
 141          } else if (node.set) {
 142              node.set(att, val);
 143          } else if (att in node) {
 144              node[att] = val;
 145          }
 146      };
 147  
 148      /**
 149       * The default getter to use when getting object properties.
 150       *
 151       * @property DEFAULT_GETTER
 152       * @static
 153       */
 154      Y.Anim.DEFAULT_GETTER = function(anim, att) {
 155          var node = anim._node,
 156              domNode = node._node,
 157              val = '';
 158  
 159          if (domNode) {
 160              if ('style' in domNode && (att in domNode.style || att in Y.DOM.CUSTOM_STYLES)) {
 161                  val = node.getComputedStyle(att);
 162              } else if ('attributes' in domNode && att in domNode.attributes) {
 163                  val = node.getAttribute(att);
 164              } else if (att in domNode) {
 165                  val = domNode[att];
 166              }
 167          } else if (node.get) {
 168              val = node.get(att);
 169          } else if (att in node) {
 170              val = node[att];
 171          }
 172  
 173          return val;
 174      };
 175  
 176      Y.Anim.ATTRS = {
 177          /**
 178           * The object to be animated.
 179           * @attribute node
 180           * @type Node
 181           */
 182          node: {
 183              setter: function(node) {
 184                  if (node) {
 185                      if (typeof node === 'string' || node.nodeType) {
 186                          node = Y.one(node);
 187                      }
 188                  }
 189  
 190                  this._node = node;
 191                  if (!node) {
 192                      Y.log(node + ' is not a valid node', 'warn', 'Anim');
 193                  }
 194                  return node;
 195              }
 196          },
 197  
 198          /**
 199           * The length of the animation.  Defaults to "1" (second).
 200           * @attribute duration
 201           * @type NUM
 202           */
 203          duration: {
 204              value: 1
 205          },
 206  
 207          /**
 208           * The method that will provide values to the attribute(s) during the animation.
 209           * Defaults to "Easing.easeNone".
 210           * @attribute easing
 211           * @type Function
 212           */
 213          easing: {
 214              value: Y.Anim.DEFAULT_EASING,
 215  
 216              setter: function(val) {
 217                  if (typeof val === 'string' && Y.Easing) {
 218                      return Y.Easing[val];
 219                  }
 220              }
 221          },
 222  
 223          /**
 224           * The starting values for the animated properties.
 225           *
 226           * Fields may be strings, numbers, or functions.
 227           * If a function is used, the return value becomes the from value.
 228           * If no from value is specified, the DEFAULT_GETTER will be used.
 229           * Supports any unit, provided it matches the "to" (or default)
 230           * unit (e.g. `{width: '10em', color: 'rgb(0, 0, 0)', borderColor: '#ccc'}`).
 231           *
 232           * If using the default ('px' for length-based units), the unit may be omitted
 233           * (e.g. `{width: 100}, borderColor: 'ccc'}`, which defaults to pixels
 234           * and hex, respectively).
 235           *
 236           * @attribute from
 237           * @type Object
 238           */
 239          from: {},
 240  
 241          /**
 242           * The ending values for the animated properties.
 243           *
 244           * Fields may be strings, numbers, or functions.
 245           * Supports any unit, provided it matches the "from" (or default)
 246           * unit (e.g. `{width: '50%', color: 'red', borderColor: '#ccc'}`).
 247           *
 248           * If using the default ('px' for length-based units), the unit may be omitted
 249           * (e.g. `{width: 100, borderColor: 'ccc'}`, which defaults to pixels
 250           * and hex, respectively).
 251           *
 252           * @attribute to
 253           * @type Object
 254           */
 255          to: {},
 256  
 257          /**
 258           * Date stamp for the first frame of the animation.
 259           * @attribute startTime
 260           * @type Int
 261           * @default 0
 262           * @readOnly
 263           */
 264          startTime: {
 265              value: 0,
 266              readOnly: true
 267          },
 268  
 269          /**
 270           * Current time the animation has been running.
 271           * @attribute elapsedTime
 272           * @type Int
 273           * @default 0
 274           * @readOnly
 275           */
 276          elapsedTime: {
 277              value: 0,
 278              readOnly: true
 279          },
 280  
 281          /**
 282           * Whether or not the animation is currently running.
 283           * @attribute running
 284           * @type Boolean
 285           * @default false
 286           * @readOnly
 287           */
 288          running: {
 289              getter: function() {
 290                  return !!_running[Y.stamp(this)];
 291              },
 292              value: false,
 293              readOnly: true
 294          },
 295  
 296          /**
 297           * The number of times the animation should run
 298           * @attribute iterations
 299           * @type Int
 300           * @default 1
 301           */
 302          iterations: {
 303              value: 1
 304          },
 305  
 306          /**
 307           * The number of iterations that have occurred.
 308           * Resets when an animation ends (reaches iteration count or stop() called).
 309           * @attribute iterationCount
 310           * @type Int
 311           * @default 0
 312           * @readOnly
 313           */
 314          iterationCount: {
 315              value: 0,
 316              readOnly: true
 317          },
 318  
 319          /**
 320           * How iterations of the animation should behave.
 321           * Possible values are "normal" and "alternate".
 322           * Normal will repeat the animation, alternate will reverse on every other pass.
 323           *
 324           * @attribute direction
 325           * @type String
 326           * @default "normal"
 327           */
 328          direction: {
 329              value: 'normal' // | alternate (fwd on odd, rev on even per spec)
 330          },
 331  
 332          /**
 333           * Whether or not the animation is currently paused.
 334           * @attribute paused
 335           * @type Boolean
 336           * @default false
 337           * @readOnly
 338           */
 339          paused: {
 340              readOnly: true,
 341              value: false
 342          },
 343  
 344          /**
 345           * If true, the `from` and `to` attributes are swapped, 
 346           * and the animation is then run starting from `from`.
 347           * @attribute reverse
 348           * @type Boolean
 349           * @default false
 350           */
 351          reverse: {
 352              value: false
 353          }
 354  
 355  
 356      };
 357  
 358      /**
 359       * Runs all animation instances.
 360       * @method run
 361       * @static
 362       */
 363      Y.Anim.run = function() {
 364          var instances = Y.Anim._instances,
 365              i;
 366          for (i in instances) {
 367              if (instances[i].run) {
 368                  instances[i].run();
 369              }
 370          }
 371      };
 372  
 373      /**
 374       * Pauses all animation instances.
 375       * @method pause
 376       * @static
 377       */
 378      Y.Anim.pause = function() {
 379          for (var i in _running) { // stop timer if nothing running
 380              if (_running[i].pause) {
 381                  _running[i].pause();
 382              }
 383          }
 384  
 385          Y.Anim._stopTimer();
 386      };
 387  
 388      /**
 389       * Stops all animation instances.
 390       * @method stop
 391       * @static
 392       */
 393      Y.Anim.stop = function() {
 394          for (var i in _running) { // stop timer if nothing running
 395              if (_running[i].stop) {
 396                  _running[i].stop();
 397              }
 398          }
 399          Y.Anim._stopTimer();
 400      };
 401  
 402      Y.Anim._startTimer = function() {
 403          if (!_timer) {
 404              _timer = setInterval(Y.Anim._runFrame, Y.Anim._intervalTime);
 405          }
 406      };
 407  
 408      Y.Anim._stopTimer = function() {
 409          clearInterval(_timer);
 410          _timer = 0;
 411      };
 412  
 413      /**
 414       * Called per Interval to handle each animation frame.
 415       * @method _runFrame
 416       * @private
 417       * @static
 418       */
 419      Y.Anim._runFrame = function() {
 420          var done = true,
 421              anim;
 422          for (anim in _running) {
 423              if (_running[anim]._runFrame) {
 424                  done = false;
 425                  _running[anim]._runFrame();
 426              }
 427          }
 428  
 429          if (done) {
 430              Y.Anim._stopTimer();
 431          }
 432      };
 433  
 434      Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/;
 435  
 436      var proto = {
 437          /**
 438           * Starts or resumes an animation.
 439           * @method run
 440           * @chainable
 441           */
 442          run: function() {
 443              if (this.get(PAUSED)) {
 444                  this._resume();
 445              } else if (!this.get(RUNNING)) {
 446                  this._start();
 447              }
 448              return this;
 449          },
 450  
 451          /**
 452           * Pauses the animation and
 453           * freezes it in its current state and time.
 454           * Calling run() will continue where it left off.
 455           * @method pause
 456           * @chainable
 457           */
 458          pause: function() {
 459              if (this.get(RUNNING)) {
 460                  this._pause();
 461              }
 462              return this;
 463          },
 464  
 465          /**
 466           * Stops the animation and resets its time.
 467           * @method stop
 468           * @param {Boolean} finish If true, the animation will move to the last frame
 469           * @chainable
 470           */
 471          stop: function(finish) {
 472              if (this.get(RUNNING) || this.get(PAUSED)) {
 473                  this._end(finish);
 474              }
 475              return this;
 476          },
 477  
 478          _added: false,
 479  
 480          _start: function() {
 481              this._set(START_TIME, new Date() - this.get(ELAPSED_TIME));
 482              this._actualFrames = 0;
 483              if (!this.get(PAUSED)) {
 484                  this._initAnimAttr();
 485              }
 486              _running[Y.stamp(this)] = this;
 487              Y.Anim._startTimer();
 488  
 489              this.fire(START);
 490          },
 491  
 492          _pause: function() {
 493              this._set(START_TIME, null);
 494              this._set(PAUSED, true);
 495              delete _running[Y.stamp(this)];
 496  
 497              /**
 498              * @event pause
 499              * @description fires when an animation is paused.
 500              * @param {Event} ev The pause event.
 501              * @type Event.Custom
 502              */
 503              this.fire('pause');
 504          },
 505  
 506          _resume: function() {
 507              this._set(PAUSED, false);
 508              _running[Y.stamp(this)] = this;
 509              this._set(START_TIME, new Date() - this.get(ELAPSED_TIME));
 510              Y.Anim._startTimer();
 511  
 512              /**
 513              * @event resume
 514              * @description fires when an animation is resumed (run from pause).
 515              * @param {Event} ev The pause event.
 516              * @type Event.Custom
 517              */
 518              this.fire('resume');
 519          },
 520  
 521          _end: function(finish) {
 522              var duration = this.get('duration') * 1000;
 523              if (finish) { // jump to last frame
 524                  this._runAttrs(duration, duration, this.get(REVERSE));
 525              }
 526  
 527              this._set(START_TIME, null);
 528              this._set(ELAPSED_TIME, 0);
 529              this._set(PAUSED, false);
 530  
 531              delete _running[Y.stamp(this)];
 532              this.fire(END, {elapsed: this.get(ELAPSED_TIME)});
 533          },
 534  
 535          _runFrame: function() {
 536              var d = this._runtimeAttr.duration,
 537                  t = new Date() - this.get(START_TIME),
 538                  reverse = this.get(REVERSE),
 539                  done = (t >= d);
 540  
 541              this._runAttrs(t, d, reverse);
 542              this._actualFrames += 1;
 543              this._set(ELAPSED_TIME, t);
 544  
 545              this.fire(TWEEN);
 546              if (done) {
 547                  this._lastFrame();
 548              }
 549          },
 550  
 551          _runAttrs: function(t, d, reverse) {
 552              var attr = this._runtimeAttr,
 553                  customAttr = Y.Anim.behaviors,
 554                  easing = attr.easing,
 555                  lastFrame = d,
 556                  done = false,
 557                  attribute,
 558                  setter,
 559                  i;
 560  
 561              if (t >= d) {
 562                  done = true;
 563              }
 564  
 565              if (reverse) {
 566                  t = d - t;
 567                  lastFrame = 0;
 568              }
 569  
 570              for (i in attr) {
 571                  if (attr[i].to) {
 572                      attribute = attr[i];
 573                      setter = (i in customAttr && 'set' in customAttr[i]) ?
 574                              customAttr[i].set : Y.Anim.DEFAULT_SETTER;
 575  
 576                      if (!done) {
 577                          setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit);
 578                      } else {
 579                          setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit);
 580                      }
 581                  }
 582              }
 583  
 584  
 585          },
 586  
 587          _lastFrame: function() {
 588              var iter = this.get('iterations'),
 589                  iterCount = this.get(ITERATION_COUNT);
 590  
 591              iterCount += 1;
 592              if (iter === 'infinite' || iterCount < iter) {
 593                  if (this.get('direction') === 'alternate') {
 594                      this.set(REVERSE, !this.get(REVERSE)); // flip it
 595                  }
 596                  /**
 597                  * @event iteration
 598                  * @description fires when an animation begins an iteration.
 599                  * @param {Event} ev The iteration event.
 600                  * @type Event.Custom
 601                  */
 602                  this.fire('iteration');
 603              } else {
 604                  iterCount = 0;
 605                  this._end();
 606              }
 607  
 608              this._set(START_TIME, new Date());
 609              this._set(ITERATION_COUNT, iterCount);
 610          },
 611  
 612          _initAnimAttr: function() {
 613              var from = this.get('from') || {},
 614                  to = this.get('to') || {},
 615                  attr = {
 616                      duration: this.get('duration') * 1000,
 617                      easing: this.get('easing')
 618                  },
 619                  customAttr = Y.Anim.behaviors,
 620                  node = this.get(NODE), // implicit attr init
 621                  unit, begin, end;
 622  
 623              Y.each(to, function(val, name) {
 624                  if (typeof val === 'function') {
 625                      val = val.call(this, node);
 626                  }
 627  
 628                  begin = from[name];
 629                  if (begin === undefined) {
 630                      begin = (name in customAttr && 'get' in customAttr[name])  ?
 631                              customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name);
 632                  } else if (typeof begin === 'function') {
 633                      begin = begin.call(this, node);
 634                  }
 635  
 636                  var mFrom = Y.Anim.RE_UNITS.exec(begin),
 637                      mTo = Y.Anim.RE_UNITS.exec(val);
 638  
 639                  begin = mFrom ? mFrom[1] : begin;
 640                  end = mTo ? mTo[1] : val;
 641                  unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
 642  
 643                  if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) {
 644                      unit = Y.Anim.DEFAULT_UNIT;
 645                  }
 646  
 647                  if (!begin || !end) {
 648                      Y.error('invalid "from" or "to" for "' + name + '"', 'Anim');
 649                      return;
 650                  }
 651  
 652                  attr[name] = {
 653                      from: Y.Lang.isObject(begin) ? Y.clone(begin) : begin,
 654                      to: end,
 655                      unit: unit
 656                  };
 657  
 658              }, this);
 659  
 660              this._runtimeAttr = attr;
 661          },
 662  
 663  
 664          // TODO: move to computedStyle? (browsers dont agree on default computed offsets)
 665          _getOffset: function(attr) {
 666              var node = this._node,
 667                  val = node.getComputedStyle(attr),
 668                  get = (attr === 'left') ? 'getX': 'getY',
 669                  set = (attr === 'left') ? 'setX': 'setY',
 670                  position;
 671  
 672              if (val === 'auto') {
 673                  position = node.getStyle('position');
 674                  if (position === 'absolute' || position === 'fixed') {
 675                      val = node[get]();
 676                      node[set](val);
 677                  } else {
 678                      val = 0;
 679                  }
 680              }
 681  
 682              return val;
 683          },
 684  
 685          destructor: function() {
 686              delete Y.Anim._instances[Y.stamp(this)];
 687          }
 688      };
 689  
 690      Y.extend(Y.Anim, Y.Base, proto);
 691  
 692  
 693  }, '3.17.2', {"requires": ["base-base", "node-style", "color-base"]});


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