src/cm/media/js/lib/yui/yui_3.10.3/build/anim-base/anim-base-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 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, animation begins from last frame
       
   346          * @attribute reverse
       
   347          * @type Boolean
       
   348          * @default false
       
   349          */
       
   350         reverse: {
       
   351             value: false
       
   352         }
       
   353 
       
   354 
       
   355     };
       
   356 
       
   357     /**
       
   358      * Runs all animation instances.
       
   359      * @method run
       
   360      * @static
       
   361      */
       
   362     Y.Anim.run = function() {
       
   363         var instances = Y.Anim._instances,
       
   364             i;
       
   365         for (i in instances) {
       
   366             if (instances[i].run) {
       
   367                 instances[i].run();
       
   368             }
       
   369         }
       
   370     };
       
   371 
       
   372     /**
       
   373      * Pauses all animation instances.
       
   374      * @method pause
       
   375      * @static
       
   376      */
       
   377     Y.Anim.pause = function() {
       
   378         for (var i in _running) { // stop timer if nothing running
       
   379             if (_running[i].pause) {
       
   380                 _running[i].pause();
       
   381             }
       
   382         }
       
   383 
       
   384         Y.Anim._stopTimer();
       
   385     };
       
   386 
       
   387     /**
       
   388      * Stops all animation instances.
       
   389      * @method stop
       
   390      * @static
       
   391      */
       
   392     Y.Anim.stop = function() {
       
   393         for (var i in _running) { // stop timer if nothing running
       
   394             if (_running[i].stop) {
       
   395                 _running[i].stop();
       
   396             }
       
   397         }
       
   398         Y.Anim._stopTimer();
       
   399     };
       
   400 
       
   401     Y.Anim._startTimer = function() {
       
   402         if (!_timer) {
       
   403             _timer = setInterval(Y.Anim._runFrame, Y.Anim._intervalTime);
       
   404         }
       
   405     };
       
   406 
       
   407     Y.Anim._stopTimer = function() {
       
   408         clearInterval(_timer);
       
   409         _timer = 0;
       
   410     };
       
   411 
       
   412     /**
       
   413      * Called per Interval to handle each animation frame.
       
   414      * @method _runFrame
       
   415      * @private
       
   416      * @static
       
   417      */
       
   418     Y.Anim._runFrame = function() {
       
   419         var done = true,
       
   420             anim;
       
   421         for (anim in _running) {
       
   422             if (_running[anim]._runFrame) {
       
   423                 done = false;
       
   424                 _running[anim]._runFrame();
       
   425             }
       
   426         }
       
   427 
       
   428         if (done) {
       
   429             Y.Anim._stopTimer();
       
   430         }
       
   431     };
       
   432 
       
   433     Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/;
       
   434 
       
   435     var proto = {
       
   436         /**
       
   437          * Starts or resumes an animation.
       
   438          * @method run
       
   439          * @chainable
       
   440          */
       
   441         run: function() {
       
   442             if (this.get(PAUSED)) {
       
   443                 this._resume();
       
   444             } else if (!this.get(RUNNING)) {
       
   445                 this._start();
       
   446             }
       
   447             return this;
       
   448         },
       
   449 
       
   450         /**
       
   451          * Pauses the animation and
       
   452          * freezes it in its current state and time.
       
   453          * Calling run() will continue where it left off.
       
   454          * @method pause
       
   455          * @chainable
       
   456          */
       
   457         pause: function() {
       
   458             if (this.get(RUNNING)) {
       
   459                 this._pause();
       
   460             }
       
   461             return this;
       
   462         },
       
   463 
       
   464         /**
       
   465          * Stops the animation and resets its time.
       
   466          * @method stop
       
   467          * @param {Boolean} finish If true, the animation will move to the last frame
       
   468          * @chainable
       
   469          */
       
   470         stop: function(finish) {
       
   471             if (this.get(RUNNING) || this.get(PAUSED)) {
       
   472                 this._end(finish);
       
   473             }
       
   474             return this;
       
   475         },
       
   476 
       
   477         _added: false,
       
   478 
       
   479         _start: function() {
       
   480             this._set(START_TIME, new Date() - this.get(ELAPSED_TIME));
       
   481             this._actualFrames = 0;
       
   482             if (!this.get(PAUSED)) {
       
   483                 this._initAnimAttr();
       
   484             }
       
   485             _running[Y.stamp(this)] = this;
       
   486             Y.Anim._startTimer();
       
   487 
       
   488             this.fire(START);
       
   489         },
       
   490 
       
   491         _pause: function() {
       
   492             this._set(START_TIME, null);
       
   493             this._set(PAUSED, true);
       
   494             delete _running[Y.stamp(this)];
       
   495 
       
   496             /**
       
   497             * @event pause
       
   498             * @description fires when an animation is paused.
       
   499             * @param {Event} ev The pause event.
       
   500             * @type Event.Custom
       
   501             */
       
   502             this.fire('pause');
       
   503         },
       
   504 
       
   505         _resume: function() {
       
   506             this._set(PAUSED, false);
       
   507             _running[Y.stamp(this)] = this;
       
   508             this._set(START_TIME, new Date() - this.get(ELAPSED_TIME));
       
   509             Y.Anim._startTimer();
       
   510 
       
   511             /**
       
   512             * @event resume
       
   513             * @description fires when an animation is resumed (run from pause).
       
   514             * @param {Event} ev The pause event.
       
   515             * @type Event.Custom
       
   516             */
       
   517             this.fire('resume');
       
   518         },
       
   519 
       
   520         _end: function(finish) {
       
   521             var duration = this.get('duration') * 1000;
       
   522             if (finish) { // jump to last frame
       
   523                 this._runAttrs(duration, duration, this.get(REVERSE));
       
   524             }
       
   525 
       
   526             this._set(START_TIME, null);
       
   527             this._set(ELAPSED_TIME, 0);
       
   528             this._set(PAUSED, false);
       
   529 
       
   530             delete _running[Y.stamp(this)];
       
   531             this.fire(END, {elapsed: this.get(ELAPSED_TIME)});
       
   532         },
       
   533 
       
   534         _runFrame: function() {
       
   535             var d = this._runtimeAttr.duration,
       
   536                 t = new Date() - this.get(START_TIME),
       
   537                 reverse = this.get(REVERSE),
       
   538                 done = (t >= d);
       
   539 
       
   540             this._runAttrs(t, d, reverse);
       
   541             this._actualFrames += 1;
       
   542             this._set(ELAPSED_TIME, t);
       
   543 
       
   544             this.fire(TWEEN);
       
   545             if (done) {
       
   546                 this._lastFrame();
       
   547             }
       
   548         },
       
   549 
       
   550         _runAttrs: function(t, d, reverse) {
       
   551             var attr = this._runtimeAttr,
       
   552                 customAttr = Y.Anim.behaviors,
       
   553                 easing = attr.easing,
       
   554                 lastFrame = d,
       
   555                 done = false,
       
   556                 attribute,
       
   557                 setter,
       
   558                 i;
       
   559 
       
   560             if (t >= d) {
       
   561                 done = true;
       
   562             }
       
   563 
       
   564             if (reverse) {
       
   565                 t = d - t;
       
   566                 lastFrame = 0;
       
   567             }
       
   568 
       
   569             for (i in attr) {
       
   570                 if (attr[i].to) {
       
   571                     attribute = attr[i];
       
   572                     setter = (i in customAttr && 'set' in customAttr[i]) ?
       
   573                             customAttr[i].set : Y.Anim.DEFAULT_SETTER;
       
   574 
       
   575                     if (!done) {
       
   576                         setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit);
       
   577                     } else {
       
   578                         setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit);
       
   579                     }
       
   580                 }
       
   581             }
       
   582 
       
   583 
       
   584         },
       
   585 
       
   586         _lastFrame: function() {
       
   587             var iter = this.get('iterations'),
       
   588                 iterCount = this.get(ITERATION_COUNT);
       
   589 
       
   590             iterCount += 1;
       
   591             if (iter === 'infinite' || iterCount < iter) {
       
   592                 if (this.get('direction') === 'alternate') {
       
   593                     this.set(REVERSE, !this.get(REVERSE)); // flip it
       
   594                 }
       
   595                 /**
       
   596                 * @event iteration
       
   597                 * @description fires when an animation begins an iteration.
       
   598                 * @param {Event} ev The iteration event.
       
   599                 * @type Event.Custom
       
   600                 */
       
   601                 this.fire('iteration');
       
   602             } else {
       
   603                 iterCount = 0;
       
   604                 this._end();
       
   605             }
       
   606 
       
   607             this._set(START_TIME, new Date());
       
   608             this._set(ITERATION_COUNT, iterCount);
       
   609         },
       
   610 
       
   611         _initAnimAttr: function() {
       
   612             var from = this.get('from') || {},
       
   613                 to = this.get('to') || {},
       
   614                 attr = {
       
   615                     duration: this.get('duration') * 1000,
       
   616                     easing: this.get('easing')
       
   617                 },
       
   618                 customAttr = Y.Anim.behaviors,
       
   619                 node = this.get(NODE), // implicit attr init
       
   620                 unit, begin, end;
       
   621 
       
   622             Y.each(to, function(val, name) {
       
   623                 if (typeof val === 'function') {
       
   624                     val = val.call(this, node);
       
   625                 }
       
   626 
       
   627                 begin = from[name];
       
   628                 if (begin === undefined) {
       
   629                     begin = (name in customAttr && 'get' in customAttr[name])  ?
       
   630                             customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name);
       
   631                 } else if (typeof begin === 'function') {
       
   632                     begin = begin.call(this, node);
       
   633                 }
       
   634 
       
   635                 var mFrom = Y.Anim.RE_UNITS.exec(begin),
       
   636                     mTo = Y.Anim.RE_UNITS.exec(val);
       
   637 
       
   638                 begin = mFrom ? mFrom[1] : begin;
       
   639                 end = mTo ? mTo[1] : val;
       
   640                 unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
       
   641 
       
   642                 if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) {
       
   643                     unit = Y.Anim.DEFAULT_UNIT;
       
   644                 }
       
   645 
       
   646                 if (!begin || !end) {
       
   647                     Y.error('invalid "from" or "to" for "' + name + '"', 'Anim');
       
   648                     return;
       
   649                 }
       
   650 
       
   651                 attr[name] = {
       
   652                     from: Y.Lang.isObject(begin) ? Y.clone(begin) : begin,
       
   653                     to: end,
       
   654                     unit: unit
       
   655                 };
       
   656 
       
   657             }, this);
       
   658 
       
   659             this._runtimeAttr = attr;
       
   660         },
       
   661 
       
   662 
       
   663         // TODO: move to computedStyle? (browsers dont agree on default computed offsets)
       
   664         _getOffset: function(attr) {
       
   665             var node = this._node,
       
   666                 val = node.getComputedStyle(attr),
       
   667                 get = (attr === 'left') ? 'getX': 'getY',
       
   668                 set = (attr === 'left') ? 'setX': 'setY',
       
   669                 position;
       
   670 
       
   671             if (val === 'auto') {
       
   672                 position = node.getStyle('position');
       
   673                 if (position === 'absolute' || position === 'fixed') {
       
   674                     val = node[get]();
       
   675                     node[set](val);
       
   676                 } else {
       
   677                     val = 0;
       
   678                 }
       
   679             }
       
   680 
       
   681             return val;
       
   682         },
       
   683 
       
   684         destructor: function() {
       
   685             delete Y.Anim._instances[Y.stamp(this)];
       
   686         }
       
   687     };
       
   688 
       
   689     Y.extend(Y.Anim, Y.Base, proto);
       
   690 
       
   691 
       
   692 }, '3.10.3', {"requires": ["base-base", "node-style"]});