src/cm/media/js/lib/yui/yui_3.0.0b1/build/anim/anim-base.js
changeset 0 40c8f766c9b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.0.0b1/build/anim/anim-base.js	Mon Nov 23 15:14:29 2009 +0100
@@ -0,0 +1,603 @@
+/*
+Copyright (c) 2009, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 3.0.0b1
+build: 1163
+*/
+YUI.add('anim-base', function(Y) {
+
+/**
+* The Animation Utility provides an API for creating advanced transitions.
+* @module anim
+*/
+
+/**
+* Provides the base Anim class, for animating numeric properties.
+*
+* @module anim
+* @submodule anim-base
+*/
+
+    /**
+     * A class for constructing animation instances.
+     * @class Anim
+     * @for Anim
+     * @constructor
+     * @extends Base
+     */
+
+    var RUNNING = 'running',
+        START_TIME = 'startTime',
+        ELAPSED_TIME = 'elapsedTime',
+        /**
+        * @for Anim
+        * @event start
+        * @description fires when an animation begins.
+        * @param {Event} ev The start event.
+        * @type Event.Custom
+        */
+        START = 'start',
+
+        /**
+        * @event tween
+        * @description fires every frame of the animation.
+        * @param {Event} ev The tween event.
+        * @type Event.Custom
+        */
+        TWEEN = 'tween',
+
+        /**
+        * @event end
+        * @description fires after the animation completes.
+        * @param {Event} ev The end event.
+        * @type Event.Custom
+        */
+        END = 'end',
+        NODE = 'node',
+        PAUSED = 'paused',
+        REVERSE = 'reverse', // TODO: cleanup
+        ITERATION_COUNT = 'iterationCount',
+
+        NUM = Number;
+
+    var _running = {},
+        _instances = {},
+        _timer;
+
+    Y.Anim = function() {
+        Y.Anim.superclass.constructor.apply(this, arguments);
+        _instances[Y.stamp(this)] = this;
+    };
+
+    Y.Anim.NAME = 'anim';
+
+    /**
+     * Regex of properties that should use the default unit.
+     *
+     * @property RE_DEFAULT_UNIT
+     * @static
+     */
+    Y.Anim.RE_DEFAULT_UNIT = /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i;
+
+    /**
+     * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
+     *
+     * @property DEFAULT_UNIT
+     * @static
+     */
+    Y.Anim.DEFAULT_UNIT = 'px';
+
+    Y.Anim.DEFAULT_EASING = function (t, b, c, d) {
+        return c * t / d + b; // linear easing
+    };
+
+    /**
+     * Bucket for custom getters and setters
+     *
+     * @property behaviors
+     * @static
+     */
+    Y.Anim.behaviors = {
+        left: {
+            get: function(anim, attr) {
+                return anim._getOffset(attr);
+            }
+        }
+    };
+
+    Y.Anim.behaviors.top = Y.Anim.behaviors.left;
+
+    /**
+     * The default setter to use when setting object properties.
+     *
+     * @property DEFAULT_SETTER
+     * @static
+     */
+    Y.Anim.DEFAULT_SETTER = function(anim, att, from, to, elapsed, duration, fn, unit) {
+        unit = unit || '';
+        anim._node.setStyle(att, fn(elapsed, NUM(from), NUM(to) - NUM(from), duration) + unit);
+    };
+
+    /**
+     * The default getter to use when getting object properties.
+     *
+     * @property DEFAULT_GETTER
+     * @static
+     */
+    Y.Anim.DEFAULT_GETTER = function(anim, prop) {
+        return anim._node.getComputedStyle(prop);
+    };
+
+    Y.Anim.ATTRS = {
+        /**
+         * The object to be animated.
+         * @attribute node
+         * @type Node
+         */
+        node: {
+            setter: function(node) {
+                node = Y.get(node);
+                this._node = node;
+                if (!node) {
+                }
+                return node;
+            }
+        },
+
+        /**
+         * The length of the animation.  Defaults to "1" (second).
+         * @attribute duration
+         * @type NUM
+         */
+        duration: {
+            value: 1
+        },
+
+        /**
+         * The method that will provide values to the attribute(s) during the animation. 
+         * Defaults to "Easing.easeNone".
+         * @attribute easing
+         * @type Function
+         */
+        easing: {
+            value: Y.Anim.DEFAULT_EASING,
+
+            setter: function(val) {
+                if (typeof val === 'string' && Y.Easing) {
+                    return Y.Easing[val];
+                }
+            }
+        },
+
+        /**
+         * The starting values for the animated properties. 
+         * Fields may be strings, numbers, or functions.
+         * If a function is used, the return value becomes the from value.
+         * If no from value is specified, the DEFAULT_GETTER will be used. 
+         * @attribute from
+         * @type Object
+         */
+        from: {},
+
+        /**
+         * The ending values for the animated properties. 
+         * Fields may be strings, numbers, or functions.
+         * @attribute to
+         * @type Object
+         */
+        to: {},
+
+        /**
+         * Date stamp for the first frame of the animation.
+         * @attribute startTime
+         * @type Int
+         * @default 0 
+         * @readOnly
+         */
+        startTime: {
+            value: 0,
+            readOnly: true
+        },
+
+        /**
+         * Current time the animation has been running.
+         * @attribute elapsedTime
+         * @type Int
+         * @default 0 
+         * @readOnly
+         */
+        elapsedTime: {
+            value: 0,
+            readOnly: true
+        },
+
+        /**
+         * Whether or not the animation is currently running.
+         * @attribute running 
+         * @type Boolean
+         * @default false 
+         * @readOnly
+         */
+        running: {
+            getter: function() {
+                return !!_running[Y.stamp(this)];
+            },
+            value: false,
+            readOnly: true
+        },
+
+        /**
+         * The number of times the animation should run 
+         * @attribute iterations
+         * @type Int
+         * @default 1 
+         */
+        iterations: {
+            value: 1
+        },
+
+        /**
+         * The number of iterations that have occurred.
+         * Resets when an animation ends (reaches iteration count or stop() called). 
+         * @attribute iterationCount
+         * @type Int
+         * @default 0
+         * @readOnly
+         */
+        iterationCount: {
+            value: 0,
+            readOnly: true
+        },
+
+        /**
+         * How iterations of the animation should behave. 
+         * Possible values are "normal" and "alternate".
+         * Normal will repeat the animation, alternate will reverse on every other pass.
+         *
+         * @attribute direction
+         * @type String
+         * @default "normal"
+         */
+        direction: {
+            value: 'normal' // | alternate (fwd on odd, rev on even per spec)
+        },
+
+        /**
+         * Whether or not the animation is currently paused.
+         * @attribute running 
+         * @type Boolean
+         * @default false 
+         * @readOnly
+         */
+        paused: {
+            readOnly: true,
+            value: false
+        },
+
+        /**
+         * If true, animation begins from last frame
+         * @attribute reverse
+         * @type Boolean
+         * @default false 
+         */
+        reverse: {
+            value: false
+        }
+
+
+    };
+
+    /**
+     * Runs all animation instances.
+     * @method run
+     * @static
+     */    
+    Y.Anim.run = function() {
+        for (var i in _instances) {
+            if (_instances[i].run) {
+                _instances[i].run();
+            }
+        }
+    };
+
+    /**
+     * Pauses all animation instances.
+     * @method pause
+     * @static
+     */    
+    Y.Anim.pause = function() {
+        for (var i in _running) { // stop timer if nothing running
+            if (_running[i].pause) {
+                _running[i].pause();
+            }
+        }
+        Y.Anim._stopTimer();
+    };
+
+    /**
+     * Stops all animation instances.
+     * @method stop
+     * @static
+     */    
+    Y.Anim.stop = function() {
+        for (var i in _running) { // stop timer if nothing running
+            if (_running[i].stop) {
+                _running[i].stop();
+            }
+        }
+        Y.Anim._stopTimer();
+    };
+    
+    Y.Anim._startTimer = function() {
+        if (!_timer) {
+            _timer = setInterval(Y.Anim._runFrame, 1);
+        }
+    };
+
+    Y.Anim._stopTimer = function() {
+        clearInterval(_timer);
+        _timer = 0;
+    };
+
+    /**
+     * Called per Interval to handle each animation frame.
+     * @method _runFrame
+     * @private
+     * @static
+     */    
+    Y.Anim._runFrame = function() {
+        var done = true;
+        for (var anim in _running) {
+            if (_running[anim]._runFrame) {
+                done = false;
+                _running[anim]._runFrame();
+            }
+        }
+
+        if (done) {
+            Y.Anim._stopTimer();
+        }
+    };
+
+    Y.Anim.RE_UNITS = /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/;
+
+    var proto = {
+        /**
+         * Starts or resumes an animation.
+         * percent start time marker.
+         * @method run
+         * @chainable
+         */    
+        run: function() {
+            if (!this.get(RUNNING)) {
+                this._start();
+            } else if (this.get(PAUSED)) {
+                this._resume();
+            }
+            return this;
+        },
+
+        /**
+         * Pauses the animation and
+         * freezes it in its current state and time.
+         * Calling run() will continue where it left off.
+         * @method pause
+         * @chainable
+         */    
+        pause: function() {
+            if (this.get(RUNNING)) {
+                this._pause();
+            }
+            return this;
+        },
+
+        /**
+         * Stops the animation and resets its time.
+         * @method stop
+         * @chainable
+         */    
+        stop: function(finish) {
+            if (this.get(RUNNING) || this.get(PAUSED)) {
+                this._end(finish);
+            }
+            return this;
+        },
+
+        _added: false,
+
+        _start: function() {
+            this._set(START_TIME, new Date() - this.get(ELAPSED_TIME));
+            this._actualFrames = 0;
+            if (!this.get(PAUSED)) {
+                this._initAnimAttr();
+            }
+            _running[Y.stamp(this)] = this;
+            Y.Anim._startTimer();
+
+            this.fire(START);
+        },
+
+        _pause: function() {
+            this._set(START_TIME, null);
+            this._set(PAUSED, true);
+            delete _running[Y.stamp(this)];
+
+            /**
+            * @event pause
+            * @description fires when an animation is paused.
+            * @param {Event} ev The pause event.
+            * @type Event.Custom
+            */
+            this.fire('pause');
+        },
+
+        _resume: function() {
+            this._set(PAUSED, false);
+            _running[Y.stamp(this)] = this;
+
+            /**
+            * @event resume
+            * @description fires when an animation is resumed (run from pause).
+            * @param {Event} ev The pause event.
+            * @type Event.Custom
+            */
+            this.fire('resume');
+        },
+
+        _end: function(finish) {
+            this._set(START_TIME, null);
+            this._set(ELAPSED_TIME, 0);
+            this._set(PAUSED, false);
+
+            delete _running[Y.stamp(this)];
+            this.fire(END, {elapsed: this.get(ELAPSED_TIME)});
+        },
+
+        _runFrame: function() {
+            var attr = this._runtimeAttr,
+                customAttr = Y.Anim.behaviors,
+                easing = attr.easing,
+                d = attr.duration,
+                t = new Date() - this.get(START_TIME),
+                reversed = this.get(REVERSE),
+                done = (t >= d),
+                lastFrame = d,
+                attribute,
+                setter;
+                
+            if (reversed) {
+                t = d - t;
+                done = (t <= 0);
+                lastFrame = 0;
+            }
+
+            for (var i in attr) {
+                if (attr[i].to) {
+                    attribute = attr[i];
+                    setter = (i in customAttr && 'set' in customAttr[i]) ?
+                            customAttr[i].set : Y.Anim.DEFAULT_SETTER;
+
+                    if (!done) {
+                        setter(this, i, attribute.from, attribute.to, t, d, easing, attribute.unit); 
+                    } else { // ensure final frame value is set
+                       // TODO: handle keyframes 
+                        setter(this, i, attribute.from, attribute.to, lastFrame, d, easing, attribute.unit); 
+                    }
+                }
+            }
+
+            this._actualFrames += 1;
+            this._set(ELAPSED_TIME, t);
+
+            this.fire(TWEEN);
+            if (done) {
+                this._lastFrame();
+            }
+        },
+
+        _lastFrame: function() {
+            var iter = this.get('iterations'),
+                iterCount = this.get(ITERATION_COUNT);
+
+            iterCount += 1;
+            if (iter === 'infinite' || iterCount < iter) {
+                if (this.get('direction') === 'alternate') {
+                    this.set(REVERSE, !this.get(REVERSE)); // flip it
+                }
+                /**
+                * @event iteration
+                * @description fires when an animation begins an iteration.
+                * @param {Event} ev The iteration event.
+                * @type Event.Custom
+                */
+                this.fire('iteration');
+            } else {
+                iterCount = 0;
+                this._end();
+            }
+
+            this._set(START_TIME, new Date());
+            this._set(ITERATION_COUNT, iterCount);
+        },
+
+        _initAnimAttr: function() {
+            var from = this.get('from') || {},
+                to = this.get('to') || {},
+                dur = this.get('duration') * 1000,
+                node = this.get(NODE),
+                easing = this.get('easing') || {},
+                attr = {},
+                customAttr = Y.Anim.behaviors,
+                unit, begin, end;
+
+            Y.each(to, function(val, name) {
+                if (typeof val === 'function') {
+                    val = val.call(this, node);
+                }
+
+                begin = from[name];
+                if (begin === undefined) {
+                    begin = (name in customAttr && 'get' in customAttr[name])  ?
+                            customAttr[name].get(this, name) : Y.Anim.DEFAULT_GETTER(this, name);
+                } else if (typeof begin === 'function') {
+                    begin = begin.call(this, node);
+                }
+
+                var mFrom = Y.Anim.RE_UNITS.exec(begin);
+                var mTo = Y.Anim.RE_UNITS.exec(val);
+
+                begin = mFrom ? mFrom[1] : begin;
+                end = mTo ? mTo[1] : val;
+                unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
+
+                if (!unit && Y.Anim.RE_DEFAULT_UNIT.test(name)) {
+                    unit = Y.Anim.DEFAULT_UNIT;
+                }
+
+                if (!begin || !end) {
+                    Y.error('invalid "from" or "to" for "' + name + '"', 'Anim');
+                    return;
+                }
+
+                attr[name] = {
+                    from: begin,
+                    to: end,
+                    unit: unit
+                };
+
+                attr.duration = dur;
+                attr.easing = easing;
+
+            }, this);
+
+            this._runtimeAttr = attr;
+        },
+
+
+        // TODO: move to computedStyle? (browsers dont agree on default computed offsets)
+        _getOffset: function(attr) {
+            var node = this._node,
+                val = node.getComputedStyle(attr),
+                get = (attr === 'left') ? 'getX': 'getY',
+                set = (attr === 'left') ? 'setX': 'setY';
+
+            if (val === 'auto') {
+                var position = node.getStyle('position');
+                if (position === 'absolute' || position === 'fixed') {
+                    val = node[get]();
+                    node[set](val);
+                } else {
+                    val = 0;
+                }
+            }
+
+            return val;
+        }
+    };
+
+    Y.extend(Y.Anim, Y.Base, proto);
+
+
+
+}, '3.0.0b1' ,{requires:['base', 'node']});