diff -r 000000000000 -r 40c8f766c9b8 src/cm/media/js/lib/yui/yui_3.0.0b1/build/anim/anim-base.js --- /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']});