2 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
8 * The animation module provides allows effects to be added to HTMLElements.
10 * @requires yahoo, event, dom
15 * Base animation class that provides the interface for building animated effects.
16 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
18 * @namespace YAHOO.util
19 * @requires YAHOO.util.AnimMgr
20 * @requires YAHOO.util.Easing
21 * @requires YAHOO.util.Dom
22 * @requires YAHOO.util.Event
23 * @requires YAHOO.util.CustomEvent
25 * @param {String | HTMLElement} el Reference to the element that will be animated
26 * @param {Object} attributes The attribute(s) to be animated.
27 * Each attribute is an object with at minimum a "to" or "by" member defined.
28 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
29 * All attribute names use camelCase.
30 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
31 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
34 YAHOO.util.Anim = function(el, attributes, duration, method) {
36 this.init(el, attributes, duration, method);
40 YAHOO.util.Anim.prototype = {
42 * Provides a readable name for the Anim instance.
46 toString: function() {
47 var el = this.getEl();
48 var id = el.id || el.tagName;
49 return ("Anim " + id);
52 patterns: { // cached for performance
53 noNegatives: /width|height|opacity|padding/i, // keep at zero or above
54 offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default
55 defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
56 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
60 * Returns the value computed by the animation's "method".
62 * @param {String} attr The name of the attribute.
63 * @param {Number} start The value this attribute should start from for this animation.
64 * @param {Number} end The value this attribute should end at for this animation.
65 * @return {Number} The Value to be applied to the attribute.
67 doMethod: function(attr, start, end) {
68 return this.method(this.currentFrame, start, end - start, this.totalFrames);
72 * Applies a value to an attribute.
73 * @method setAttribute
74 * @param {String} attr The name of the attribute.
75 * @param {Number} val The value to be applied to the attribute.
76 * @param {String} unit The unit ('px', '%', etc.) of the value.
78 setAttribute: function(attr, val, unit) {
79 if ( this.patterns.noNegatives.test(attr) ) {
80 val = (val > 0) ? val : 0;
83 YAHOO.util.Dom.setStyle(this.getEl(), attr, val + unit);
87 * Returns current value of the attribute.
88 * @method getAttribute
89 * @param {String} attr The name of the attribute.
90 * @return {Number} val The current value of the attribute.
92 getAttribute: function(attr) {
93 var el = this.getEl();
94 var val = YAHOO.util.Dom.getStyle(el, attr);
96 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
97 return parseFloat(val);
100 var a = this.patterns.offsetAttribute.exec(attr) || [];
101 var pos = !!( a[3] ); // top or left
102 var box = !!( a[2] ); // width or height
104 // use offsets for width/height and abs pos top/left
105 if ( box || (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
106 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
107 } else { // default to zero for other 'auto'
115 * Returns the unit to use when none is supplied.
116 * @method getDefaultUnit
117 * @param {attr} attr The name of the attribute.
118 * @return {String} The default unit to be used.
120 getDefaultUnit: function(attr) {
121 if ( this.patterns.defaultUnit.test(attr) ) {
129 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
130 * @method setRuntimeAttribute
131 * @param {Object} attr The attribute object
134 setRuntimeAttribute: function(attr) {
137 var attributes = this.attributes;
139 this.runtimeAttributes[attr] = {};
141 var isset = function(prop) {
142 return (typeof prop !== 'undefined');
145 if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
146 return false; // note return; nothing to animate to
149 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
151 // To beats by, per SMIL 2.1 spec
152 if ( isset(attributes[attr]['to']) ) {
153 end = attributes[attr]['to'];
154 } else if ( isset(attributes[attr]['by']) ) {
155 if (start.constructor == Array) {
157 for (var i = 0, len = start.length; i < len; ++i) {
158 end[i] = start[i] + attributes[attr]['by'][i];
161 end = start + attributes[attr]['by'];
165 this.runtimeAttributes[attr].start = start;
166 this.runtimeAttributes[attr].end = end;
168 // set units if needed
169 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
173 * Constructor for Anim instance.
175 * @param {String | HTMLElement} el Reference to the element that will be animated
176 * @param {Object} attributes The attribute(s) to be animated.
177 * Each attribute is an object with at minimum a "to" or "by" member defined.
178 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
179 * All attribute names use camelCase.
180 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
181 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
183 init: function(el, attributes, duration, method) {
185 * Whether or not the animation is running.
186 * @property isAnimated
190 var isAnimated = false;
193 * A Date object that is created when the animation begins.
194 * @property startTime
198 var startTime = null;
201 * The number of frames this animation was able to execute.
202 * @property actualFrames
206 var actualFrames = 0;
209 * The element to be animated.
214 el = YAHOO.util.Dom.get(el);
217 * The collection of attributes to be animated.
218 * Each attribute must have at least a "to" or "by" defined in order to animate.
219 * If "to" is supplied, the animation will end with the attribute at that value.
220 * If "by" is supplied, the animation will end at that value plus its starting value.
221 * If both are supplied, "to" is used, and "by" is ignored.
222 * Optional additional member include "from" (the value the attribute should start animating from, defaults to current value), and "unit" (the units to apply to the values).
223 * @property attributes
226 this.attributes = attributes || {};
229 * The length of the animation. Defaults to "1" (second).
233 this.duration = duration || 1;
236 * The method that will provide values to the attribute(s) during the animation.
237 * Defaults to "YAHOO.util.Easing.easeNone".
241 this.method = method || YAHOO.util.Easing.easeNone;
244 * Whether or not the duration should be treated as seconds.
246 * @property useSeconds
249 this.useSeconds = true; // default to seconds
252 * The location of the current animation on the timeline.
253 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
254 * @property currentFrame
257 this.currentFrame = 0;
260 * The total number of frames to be executed.
261 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
262 * @property totalFrames
265 this.totalFrames = YAHOO.util.AnimMgr.fps;
269 * Returns a reference to the animated element.
271 * @return {HTMLElement}
273 this.getEl = function() { return el; };
276 * Checks whether the element is currently animated.
278 * @return {Boolean} current value of isAnimated.
280 this.isAnimated = function() {
285 * Returns the animation start time.
286 * @method getStartTime
287 * @return {Date} current value of startTime.
289 this.getStartTime = function() {
293 this.runtimeAttributes = {};
296 logger.log = function() {YAHOO.log.apply(window, arguments)};
298 logger.log('creating new instance of ' + this);
301 * Starts the animation by registering it with the animation manager.
304 this.animate = function() {
305 if ( this.isAnimated() ) {
309 this.currentFrame = 0;
311 this.totalFrames = ( this.useSeconds ) ? Math.ceil(YAHOO.util.AnimMgr.fps * this.duration) : this.duration;
313 YAHOO.util.AnimMgr.registerElement(this);
317 * Stops the animation. Normally called by AnimMgr when animation completes.
319 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
321 this.stop = function(finish) {
323 this.currentFrame = this.totalFrames;
324 this._onTween.fire();
326 YAHOO.util.AnimMgr.stop(this);
329 var onStart = function() {
332 this.runtimeAttributes = {};
333 for (var attr in this.attributes) {
334 this.setRuntimeAttribute(attr);
339 startTime = new Date();
343 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
347 var onTween = function() {
349 duration: new Date() - this.getStartTime(),
350 currentFrame: this.currentFrame
353 data.toString = function() {
355 'duration: ' + data.duration +
356 ', currentFrame: ' + data.currentFrame
360 this.onTween.fire(data);
362 var runtimeAttributes = this.runtimeAttributes;
364 for (var attr in runtimeAttributes) {
365 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
371 var onComplete = function() {
372 var actual_duration = (new Date() - startTime) / 1000 ;
375 duration: actual_duration,
376 frames: actualFrames,
377 fps: actualFrames / actual_duration
380 data.toString = function() {
382 'duration: ' + data.duration +
383 ', frames: ' + data.frames +
390 this.onComplete.fire(data);
394 * Custom event that fires after onStart, useful in subclassing
397 this._onStart = new YAHOO.util.CustomEvent('_start', this, true);
400 * Custom event that fires when animation begins
401 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
404 this.onStart = new YAHOO.util.CustomEvent('start', this);
407 * Custom event that fires between each frame
408 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
411 this.onTween = new YAHOO.util.CustomEvent('tween', this);
414 * Custom event that fires after onTween
417 this._onTween = new YAHOO.util.CustomEvent('_tween', this, true);
420 * Custom event that fires when animation ends
421 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
424 this.onComplete = new YAHOO.util.CustomEvent('complete', this);
426 * Custom event that fires after onComplete
429 this._onComplete = new YAHOO.util.CustomEvent('_complete', this, true);
431 this._onStart.subscribe(onStart);
432 this._onTween.subscribe(onTween);
433 this._onComplete.subscribe(onComplete);
438 * Handles animation queueing and threading.
439 * Used by Anim and subclasses.
441 * @namespace YAHOO.util
443 YAHOO.util.AnimMgr = new function() {
445 * Reference to the animation Interval.
453 * The current queue of registered animation objects.
461 * The number of active animations.
462 * @property tweenCount
469 * Base frame rate (frames per second).
470 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
478 * Interval delay in milliseconds, defaults to fastest possible.
486 * Adds an animation instance to the animation queue.
487 * All animation instances must be registered in order to animate.
488 * @method registerElement
489 * @param {object} tween The Anim instance to be be registered
491 this.registerElement = function(tween) {
492 queue[queue.length] = tween;
494 tween._onStart.fire();
499 * removes an animation instance from the animation queue.
500 * All animation instances must be registered in order to animate.
502 * @param {object} tween The Anim instance to be be registered
503 * @param {Int} index The index of the Anim instance
506 this.unRegister = function(tween, index) {
507 tween._onComplete.fire();
508 index = index || getIndex(tween);
509 if (index != -1) { queue.splice(index, 1); }
512 if (tweenCount <= 0) { this.stop(); }
516 * Starts the animation thread.
517 * Only one thread can run at a time.
520 this.start = function() {
521 if (thread === null) { thread = setInterval(this.run, this.delay); }
525 * Stops the animation thread or a specific animation instance.
527 * @param {object} tween A specific Anim instance to stop (optional)
528 * If no instance given, Manager stops thread and all animations.
530 this.stop = function(tween) {
532 clearInterval(thread);
533 for (var i = 0, len = queue.length; i < len; ++i) {
534 if (queue[i].isAnimated()) {
535 this.unRegister(tween, i);
543 this.unRegister(tween);
548 * Called per Interval to handle each animation frame.
551 this.run = function() {
552 for (var i = 0, len = queue.length; i < len; ++i) {
553 var tween = queue[i];
554 if ( !tween || !tween.isAnimated() ) { continue; }
556 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
558 tween.currentFrame += 1;
560 if (tween.useSeconds) {
563 tween._onTween.fire();
565 else { YAHOO.util.AnimMgr.stop(tween, i); }
569 var getIndex = function(anim) {
570 for (var i = 0, len = queue.length; i < len; ++i) {
571 if (queue[i] == anim) {
572 return i; // note return;
579 * On the fly frame correction to keep animation on time.
580 * @method correctFrame
582 * @param {Object} tween The Anim instance being corrected.
584 var correctFrame = function(tween) {
585 var frames = tween.totalFrames;
586 var frame = tween.currentFrame;
587 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
588 var elapsed = (new Date() - tween.getStartTime());
591 if (elapsed < tween.duration * 1000) { // check if falling behind
592 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
593 } else { // went over duration, so jump to end
594 tweak = frames - (frame + 1);
596 if (tweak > 0 && isFinite(tweak)) { // adjust if needed
597 if (tween.currentFrame + tweak >= frames) {// dont go past last frame
598 tweak = frames - (frame + 1);
601 tween.currentFrame += tweak;
606 * Used to calculate Bezier splines for any number of control points.
608 * @namespace YAHOO.util
611 YAHOO.util.Bezier = new function() {
613 * Get the current position of the animated element based on t.
614 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
615 * At least 2 points are required (start and end).
616 * First point is start. Last point is end.
617 * Additional control points are optional.
618 * @method getPosition
619 * @param {Array} points An array containing Bezier points
620 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
621 * @return {Array} An array containing int x and y member data
623 this.getPosition = function(points, t) {
624 var n = points.length;
627 for (var i = 0; i < n; ++i){
628 tmp[i] = [points[i][0], points[i][1]]; // save input
631 for (var j = 1; j < n; ++j) {
632 for (i = 0; i < n - j; ++i) {
633 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
634 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
638 return [ tmp[0][0], tmp[0][1] ];
644 * Anim subclass for color transitions.
645 * <p>Usage: <code>var myAnim = new Y.ColorAnim(el, { backgroundColor: { from: '#FF0000', to: '#FFFFFF' } }, 1, Y.Easing.easeOut);</code> Color values can be specified with either 112233, #112233,
646 * [255,255,255], or rgb(255,255,255)</p>
648 * @namespace YAHOO.util
649 * @requires YAHOO.util.Anim
650 * @requires YAHOO.util.AnimMgr
651 * @requires YAHOO.util.Easing
652 * @requires YAHOO.util.Bezier
653 * @requires YAHOO.util.Dom
654 * @requires YAHOO.util.Event
656 * @extends YAHOO.util.Anim
657 * @param {HTMLElement | String} el Reference to the element that will be animated
658 * @param {Object} attributes The attribute(s) to be animated.
659 * Each attribute is an object with at minimum a "to" or "by" member defined.
660 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
661 * All attribute names use camelCase.
662 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
663 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
665 YAHOO.util.ColorAnim = function(el, attributes, duration, method) {
666 YAHOO.util.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
669 YAHOO.extend(YAHOO.util.ColorAnim, YAHOO.util.Anim);
673 var superclass = Y.ColorAnim.superclass;
674 var proto = Y.ColorAnim.prototype;
676 proto.toString = function() {
677 var el = this.getEl();
678 var id = el.id || el.tagName;
679 return ("ColorAnim " + id);
682 proto.patterns.color = /color$/i;
683 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
684 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
685 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
686 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
689 * Attempts to parse the given string and return a 3-tuple.
691 * @param {String} s The string to parse.
692 * @return {Array} The 3-tuple of rgb values.
694 proto.parseColor = function(s) {
695 if (s.length == 3) { return s; }
697 var c = this.patterns.hex.exec(s);
698 if (c && c.length == 4) {
699 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
702 c = this.patterns.rgb.exec(s);
703 if (c && c.length == 4) {
704 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
707 c = this.patterns.hex3.exec(s);
708 if (c && c.length == 4) {
709 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
715 proto.getAttribute = function(attr) {
716 var el = this.getEl();
717 if ( this.patterns.color.test(attr) ) {
718 var val = YAHOO.util.Dom.getStyle(el, attr);
720 if (this.patterns.transparent.test(val)) { // bgcolor default
721 var parent = el.parentNode; // try and get from an ancestor
722 val = Y.Dom.getStyle(parent, attr);
724 while (parent && this.patterns.transparent.test(val)) {
725 parent = parent.parentNode;
726 val = Y.Dom.getStyle(parent, attr);
727 if (parent.tagName.toUpperCase() == 'HTML') {
733 val = superclass.getAttribute.call(this, attr);
739 proto.doMethod = function(attr, start, end) {
742 if ( this.patterns.color.test(attr) ) {
744 for (var i = 0, len = start.length; i < len; ++i) {
745 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
748 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
751 val = superclass.doMethod.call(this, attr, start, end);
757 proto.setRuntimeAttribute = function(attr) {
758 superclass.setRuntimeAttribute.call(this, attr);
760 if ( this.patterns.color.test(attr) ) {
761 var attributes = this.attributes;
762 var start = this.parseColor(this.runtimeAttributes[attr].start);
763 var end = this.parseColor(this.runtimeAttributes[attr].end);
764 // fix colors if going "by"
765 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
766 end = this.parseColor(attributes[attr].by);
768 for (var i = 0, len = start.length; i < len; ++i) {
769 end[i] = start[i] + end[i];
773 this.runtimeAttributes[attr].start = start;
774 this.runtimeAttributes[attr].end = end;
778 TERMS OF USE - EASING EQUATIONS
779 Open source under the BSD License.
780 Copyright 2001 Robert Penner All rights reserved.
782 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
784 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
785 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
786 * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
788 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
792 * Singleton that determines how an animation proceeds from start to end.
794 * @namespace YAHOO.util
797 YAHOO.util.Easing = {
800 * Uniform speed between points.
802 * @param {Number} t Time value used to compute current value
803 * @param {Number} b Starting value
804 * @param {Number} c Delta between start and end values
805 * @param {Number} d Total length of animation
806 * @return {Number} The computed value for the current animation frame
808 easeNone: function (t, b, c, d) {
813 * Begins slowly and accelerates towards end. (quadratic)
815 * @param {Number} t Time value used to compute current value
816 * @param {Number} b Starting value
817 * @param {Number} c Delta between start and end values
818 * @param {Number} d Total length of animation
819 * @return {Number} The computed value for the current animation frame
821 easeIn: function (t, b, c, d) {
822 return c*(t/=d)*t + b;
826 * Begins quickly and decelerates towards end. (quadratic)
828 * @param {Number} t Time value used to compute current value
829 * @param {Number} b Starting value
830 * @param {Number} c Delta between start and end values
831 * @param {Number} d Total length of animation
832 * @return {Number} The computed value for the current animation frame
834 easeOut: function (t, b, c, d) {
835 return -c *(t/=d)*(t-2) + b;
839 * Begins slowly and decelerates towards end. (quadratic)
841 * @param {Number} t Time value used to compute current value
842 * @param {Number} b Starting value
843 * @param {Number} c Delta between start and end values
844 * @param {Number} d Total length of animation
845 * @return {Number} The computed value for the current animation frame
847 easeBoth: function (t, b, c, d) {
852 return -c/2 * ((--t)*(t-2) - 1) + b;
856 * Begins slowly and accelerates towards end. (quartic)
857 * @method easeInStrong
858 * @param {Number} t Time value used to compute current value
859 * @param {Number} b Starting value
860 * @param {Number} c Delta between start and end values
861 * @param {Number} d Total length of animation
862 * @return {Number} The computed value for the current animation frame
864 easeInStrong: function (t, b, c, d) {
865 return c*(t/=d)*t*t*t + b;
869 * Begins quickly and decelerates towards end. (quartic)
870 * @method easeOutStrong
871 * @param {Number} t Time value used to compute current value
872 * @param {Number} b Starting value
873 * @param {Number} c Delta between start and end values
874 * @param {Number} d Total length of animation
875 * @return {Number} The computed value for the current animation frame
877 easeOutStrong: function (t, b, c, d) {
878 return -c * ((t=t/d-1)*t*t*t - 1) + b;
882 * Begins slowly and decelerates towards end. (quartic)
883 * @method easeBothStrong
884 * @param {Number} t Time value used to compute current value
885 * @param {Number} b Starting value
886 * @param {Number} c Delta between start and end values
887 * @param {Number} d Total length of animation
888 * @return {Number} The computed value for the current animation frame
890 easeBothStrong: function (t, b, c, d) {
892 return c/2*t*t*t*t + b;
895 return -c/2 * ((t-=2)*t*t*t - 2) + b;
899 * Snap in elastic effect.
901 * @param {Number} t Time value used to compute current value
902 * @param {Number} b Starting value
903 * @param {Number} c Delta between start and end values
904 * @param {Number} d Total length of animation
905 * @param {Number} a Amplitude (optional)
906 * @param {Number} p Period (optional)
907 * @return {Number} The computed value for the current animation frame
910 elasticIn: function (t, b, c, d, a, p) {
914 if ( (t /= d) == 1 ) {
921 if (!a || a < Math.abs(c)) {
926 var s = p/(2*Math.PI) * Math.asin (c/a);
929 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
933 * Snap out elastic effect.
935 * @param {Number} t Time value used to compute current value
936 * @param {Number} b Starting value
937 * @param {Number} c Delta between start and end values
938 * @param {Number} d Total length of animation
939 * @param {Number} a Amplitude (optional)
940 * @param {Number} p Period (optional)
941 * @return {Number} The computed value for the current animation frame
943 elasticOut: function (t, b, c, d, a, p) {
947 if ( (t /= d) == 1 ) {
954 if (!a || a < Math.abs(c)) {
959 var s = p/(2*Math.PI) * Math.asin (c/a);
962 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
966 * Snap both elastic effect.
967 * @method elasticBoth
968 * @param {Number} t Time value used to compute current value
969 * @param {Number} b Starting value
970 * @param {Number} c Delta between start and end values
971 * @param {Number} d Total length of animation
972 * @param {Number} a Amplitude (optional)
973 * @param {Number} p Period (optional)
974 * @return {Number} The computed value for the current animation frame
976 elasticBoth: function (t, b, c, d, a, p) {
981 if ( (t /= d/2) == 2 ) {
989 if ( !a || a < Math.abs(c) ) {
994 var s = p/(2*Math.PI) * Math.asin (c/a);
998 return -.5*(a*Math.pow(2,10*(t-=1)) *
999 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1001 return a*Math.pow(2,-10*(t-=1)) *
1002 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1007 * Backtracks slightly, then reverses direction and moves to end.
1009 * @param {Number} t Time value used to compute current value
1010 * @param {Number} b Starting value
1011 * @param {Number} c Delta between start and end values
1012 * @param {Number} d Total length of animation
1013 * @param {Number} s Overshoot (optional)
1014 * @return {Number} The computed value for the current animation frame
1016 backIn: function (t, b, c, d, s) {
1017 if (typeof s == 'undefined') {
1020 return c*(t/=d)*t*((s+1)*t - s) + b;
1024 * Overshoots end, then reverses and comes back to end.
1026 * @param {Number} t Time value used to compute current value
1027 * @param {Number} b Starting value
1028 * @param {Number} c Delta between start and end values
1029 * @param {Number} d Total length of animation
1030 * @param {Number} s Overshoot (optional)
1031 * @return {Number} The computed value for the current animation frame
1033 backOut: function (t, b, c, d, s) {
1034 if (typeof s == 'undefined') {
1037 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1041 * Backtracks slightly, then reverses direction, overshoots end,
1042 * then reverses and comes back to end.
1044 * @param {Number} t Time value used to compute current value
1045 * @param {Number} b Starting value
1046 * @param {Number} c Delta between start and end values
1047 * @param {Number} d Total length of animation
1048 * @param {Number} s Overshoot (optional)
1049 * @return {Number} The computed value for the current animation frame
1051 backBoth: function (t, b, c, d, s) {
1052 if (typeof s == 'undefined') {
1056 if ((t /= d/2 ) < 1) {
1057 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1059 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1063 * Bounce off of start.
1065 * @param {Number} t Time value used to compute current value
1066 * @param {Number} b Starting value
1067 * @param {Number} c Delta between start and end values
1068 * @param {Number} d Total length of animation
1069 * @return {Number} The computed value for the current animation frame
1071 bounceIn: function (t, b, c, d) {
1072 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1078 * @param {Number} t Time value used to compute current value
1079 * @param {Number} b Starting value
1080 * @param {Number} c Delta between start and end values
1081 * @param {Number} d Total length of animation
1082 * @return {Number} The computed value for the current animation frame
1084 bounceOut: function (t, b, c, d) {
1085 if ((t/=d) < (1/2.75)) {
1086 return c*(7.5625*t*t) + b;
1087 } else if (t < (2/2.75)) {
1088 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1089 } else if (t < (2.5/2.75)) {
1090 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1092 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1096 * Bounces off start and end.
1097 * @method bounceBoth
1098 * @param {Number} t Time value used to compute current value
1099 * @param {Number} b Starting value
1100 * @param {Number} c Delta between start and end values
1101 * @param {Number} d Total length of animation
1102 * @return {Number} The computed value for the current animation frame
1104 bounceBoth: function (t, b, c, d) {
1106 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1108 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1114 * Anim subclass for moving elements along a path defined by the "points"
1115 * member of "attributes". All "points" are arrays with x, y coordinates.
1116 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1118 * @namespace YAHOO.util
1119 * @requires YAHOO.util.Anim
1120 * @requires YAHOO.util.AnimMgr
1121 * @requires YAHOO.util.Easing
1122 * @requires YAHOO.util.Bezier
1123 * @requires YAHOO.util.Dom
1124 * @requires YAHOO.util.Event
1125 * @requires YAHOO.util.CustomEvent
1127 * @extends YAHOO.util.Anim
1128 * @param {String | HTMLElement} el Reference to the element that will be animated
1129 * @param {Object} attributes The attribute(s) to be animated.
1130 * Each attribute is an object with at minimum a "to" or "by" member defined.
1131 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1132 * All attribute names use camelCase.
1133 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1134 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1136 YAHOO.util.Motion = function(el, attributes, duration, method) {
1137 if (el) { // dont break existing subclasses not using YAHOO.extend
1138 YAHOO.util.Motion.superclass.constructor.call(this, el, attributes, duration, method);
1142 YAHOO.extend(YAHOO.util.Motion, YAHOO.util.ColorAnim);
1146 var superclass = Y.Motion.superclass;
1147 var proto = Y.Motion.prototype;
1149 proto.toString = function() {
1150 var el = this.getEl();
1151 var id = el.id || el.tagName;
1152 return ("Motion " + id);
1155 proto.patterns.points = /^points$/i;
1157 proto.setAttribute = function(attr, val, unit) {
1158 if ( this.patterns.points.test(attr) ) {
1159 unit = unit || 'px';
1160 superclass.setAttribute.call(this, 'left', val[0], unit);
1161 superclass.setAttribute.call(this, 'top', val[1], unit);
1163 superclass.setAttribute.call(this, attr, val, unit);
1167 proto.getAttribute = function(attr) {
1168 if ( this.patterns.points.test(attr) ) {
1170 superclass.getAttribute.call(this, 'left'),
1171 superclass.getAttribute.call(this, 'top')
1174 val = superclass.getAttribute.call(this, attr);
1180 proto.doMethod = function(attr, start, end) {
1183 if ( this.patterns.points.test(attr) ) {
1184 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1185 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1187 val = superclass.doMethod.call(this, attr, start, end);
1192 proto.setRuntimeAttribute = function(attr) {
1193 if ( this.patterns.points.test(attr) ) {
1194 var el = this.getEl();
1195 var attributes = this.attributes;
1197 var control = attributes['points']['control'] || [];
1201 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1202 control = [control];
1203 } else { // break reference to attributes.points.control
1205 for (i = 0, len = control.length; i< len; ++i) {
1206 tmp[i] = control[i];
1211 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1212 Y.Dom.setStyle(el, 'position', 'relative');
1215 if ( isset(attributes['points']['from']) ) {
1216 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1218 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1220 start = this.getAttribute('points'); // get actual top & left
1222 // TO beats BY, per SMIL 2.1 spec
1223 if ( isset(attributes['points']['to']) ) {
1224 end = translateValues.call(this, attributes['points']['to'], start);
1226 var pageXY = Y.Dom.getXY(this.getEl());
1227 for (i = 0, len = control.length; i < len; ++i) {
1228 control[i] = translateValues.call(this, control[i], start);
1232 } else if ( isset(attributes['points']['by']) ) {
1233 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1235 for (i = 0, len = control.length; i < len; ++i) {
1236 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1240 this.runtimeAttributes[attr] = [start];
1242 if (control.length > 0) {
1243 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1246 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1249 superclass.setRuntimeAttribute.call(this, attr);
1253 var translateValues = function(val, start) {
1254 var pageXY = Y.Dom.getXY(this.getEl());
1255 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1260 var isset = function(prop) {
1261 return (typeof prop !== 'undefined');
1266 * Anim subclass for scrolling elements to a position defined by the "scroll"
1267 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1268 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1270 * @namespace YAHOO.util
1271 * @requires YAHOO.util.Anim
1272 * @requires YAHOO.util.AnimMgr
1273 * @requires YAHOO.util.Easing
1274 * @requires YAHOO.util.Bezier
1275 * @requires YAHOO.util.Dom
1276 * @requires YAHOO.util.Event
1277 * @requires YAHOO.util.CustomEvent
1278 * @extends YAHOO.util.Anim
1280 * @param {String or HTMLElement} el Reference to the element that will be animated
1281 * @param {Object} attributes The attribute(s) to be animated.
1282 * Each attribute is an object with at minimum a "to" or "by" member defined.
1283 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1284 * All attribute names use camelCase.
1285 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1286 * @param {Function} method (optional, defaults to YAHOO.util.Easing.easeNone) Computes the values that are applied to the attributes per frame (generally a YAHOO.util.Easing method)
1288 YAHOO.util.Scroll = function(el, attributes, duration, method) {
1289 if (el) { // dont break existing subclasses not using YAHOO.extend
1290 YAHOO.util.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1294 YAHOO.extend(YAHOO.util.Scroll, YAHOO.util.ColorAnim);
1298 var superclass = Y.Scroll.superclass;
1299 var proto = Y.Scroll.prototype;
1301 proto.toString = function() {
1302 var el = this.getEl();
1303 var id = el.id || el.tagName;
1304 return ("Scroll " + id);
1307 proto.doMethod = function(attr, start, end) {
1310 if (attr == 'scroll') {
1312 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1313 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1317 val = superclass.doMethod.call(this, attr, start, end);
1322 proto.getAttribute = function(attr) {
1324 var el = this.getEl();
1326 if (attr == 'scroll') {
1327 val = [ el.scrollLeft, el.scrollTop ];
1329 val = superclass.getAttribute.call(this, attr);
1335 proto.setAttribute = function(attr, val, unit) {
1336 var el = this.getEl();
1338 if (attr == 'scroll') {
1339 el.scrollLeft = val[0];
1340 el.scrollTop = val[1];
1342 superclass.setAttribute.call(this, attr, val, unit);