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