2 Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
12 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
13 Code licensed under the BSD License:
14 http://developer.yahoo.net/yui/license.txt
18 * The animation module provides allows effects to be added to HTMLElements.
20 * @requires yahoo, event, dom
25 * Base animation class that provides the interface for building animated effects.
26 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
28 * @namespace YAHOO.util
29 * @requires YAHOO.util.AnimMgr
30 * @requires YAHOO.util.Easing
31 * @requires YAHOO.util.Dom
32 * @requires YAHOO.util.Event
33 * @requires YAHOO.util.CustomEvent
35 * @param {String | HTMLElement} el Reference to the element that will be animated
36 * @param {Object} attributes The attribute(s) to be animated.
37 * Each attribute is an object with at minimum a "to" or "by" member defined.
38 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
39 * All attribute names use camelCase.
40 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
41 * @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)
44 var Anim = function(el, attributes, duration, method) {
46 YAHOO.log('element required to create Anim instance', 'error', 'Anim');
48 this.init(el, attributes, duration, method);
55 * Provides a readable name for the Anim instance.
59 toString: function() {
60 var el = this.getEl() || {};
61 var id = el.id || el.tagName;
62 return (this.constructor.NAME + ': ' + id);
65 patterns: { // cached for performance
66 noNegatives: /width|height|opacity|padding/i, // keep at zero or above
67 offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default
68 defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
69 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
73 * Returns the value computed by the animation's "method".
75 * @param {String} attr The name of the attribute.
76 * @param {Number} start The value this attribute should start from for this animation.
77 * @param {Number} end The value this attribute should end at for this animation.
78 * @return {Number} The Value to be applied to the attribute.
80 doMethod: function(attr, start, end) {
81 return this.method(this.currentFrame, start, end - start, this.totalFrames);
85 * Applies a value to an attribute.
86 * @method setAttribute
87 * @param {String} attr The name of the attribute.
88 * @param {Number} val The value to be applied to the attribute.
89 * @param {String} unit The unit ('px', '%', etc.) of the value.
91 setAttribute: function(attr, val, unit) {
92 if ( this.patterns.noNegatives.test(attr) ) {
93 val = (val > 0) ? val : 0;
96 Y.Dom.setStyle(this.getEl(), attr, val + unit);
100 * Returns current value of the attribute.
101 * @method getAttribute
102 * @param {String} attr The name of the attribute.
103 * @return {Number} val The current value of the attribute.
105 getAttribute: function(attr) {
106 var el = this.getEl();
107 var val = Y.Dom.getStyle(el, attr);
109 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
110 return parseFloat(val);
113 var a = this.patterns.offsetAttribute.exec(attr) || [];
114 var pos = !!( a[3] ); // top or left
115 var box = !!( a[2] ); // width or height
117 // use offsets for width/height and abs pos top/left
118 if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
119 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
120 } else { // default to zero for other 'auto'
128 * Returns the unit to use when none is supplied.
129 * @method getDefaultUnit
130 * @param {attr} attr The name of the attribute.
131 * @return {String} The default unit to be used.
133 getDefaultUnit: function(attr) {
134 if ( this.patterns.defaultUnit.test(attr) ) {
142 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
143 * @method setRuntimeAttribute
144 * @param {Object} attr The attribute object
147 setRuntimeAttribute: function(attr) {
150 var attributes = this.attributes;
152 this.runtimeAttributes[attr] = {};
154 var isset = function(prop) {
155 return (typeof prop !== 'undefined');
158 if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
159 return false; // note return; nothing to animate to
162 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
164 // To beats by, per SMIL 2.1 spec
165 if ( isset(attributes[attr]['to']) ) {
166 end = attributes[attr]['to'];
167 } else if ( isset(attributes[attr]['by']) ) {
168 if (start.constructor == Array) {
170 for (var i = 0, len = start.length; i < len; ++i) {
171 end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by"
174 end = start + attributes[attr]['by'] * 1;
178 this.runtimeAttributes[attr].start = start;
179 this.runtimeAttributes[attr].end = end;
181 // set units if needed
182 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
183 attributes[attr]['unit'] : this.getDefaultUnit(attr);
188 * Constructor for Anim instance.
190 * @param {String | HTMLElement} el Reference to the element that will be animated
191 * @param {Object} attributes The attribute(s) to be animated.
192 * Each attribute is an object with at minimum a "to" or "by" member defined.
193 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
194 * All attribute names use camelCase.
195 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
196 * @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)
198 init: function(el, attributes, duration, method) {
200 * Whether or not the animation is running.
201 * @property isAnimated
205 var isAnimated = false;
208 * A Date object that is created when the animation begins.
209 * @property startTime
213 var startTime = null;
216 * The number of frames this animation was able to execute.
217 * @property actualFrames
221 var actualFrames = 0;
224 * The element to be animated.
232 * The collection of attributes to be animated.
233 * Each attribute must have at least a "to" or "by" defined in order to animate.
234 * If "to" is supplied, the animation will end with the attribute at that value.
235 * If "by" is supplied, the animation will end at that value plus its starting value.
236 * If both are supplied, "to" is used, and "by" is ignored.
237 * 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).
238 * @property attributes
241 this.attributes = attributes || {};
244 * The length of the animation. Defaults to "1" (second).
248 this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
251 * The method that will provide values to the attribute(s) during the animation.
252 * Defaults to "YAHOO.util.Easing.easeNone".
256 this.method = method || Y.Easing.easeNone;
259 * Whether or not the duration should be treated as seconds.
261 * @property useSeconds
264 this.useSeconds = true; // default to seconds
267 * The location of the current animation on the timeline.
268 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
269 * @property currentFrame
272 this.currentFrame = 0;
275 * The total number of frames to be executed.
276 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
277 * @property totalFrames
280 this.totalFrames = Y.AnimMgr.fps;
283 * Changes the animated element
286 this.setEl = function(element) {
287 el = Y.Dom.get(element);
291 * Returns a reference to the animated element.
293 * @return {HTMLElement}
295 this.getEl = function() { return el; };
298 * Checks whether the element is currently animated.
300 * @return {Boolean} current value of isAnimated.
302 this.isAnimated = function() {
307 * Returns the animation start time.
308 * @method getStartTime
309 * @return {Date} current value of startTime.
311 this.getStartTime = function() {
315 this.runtimeAttributes = {};
318 logger.log = function() {YAHOO.log.apply(window, arguments)};
320 logger.log('creating new instance of ' + this);
323 * Starts the animation by registering it with the animation manager.
326 this.animate = function() {
327 if ( this.isAnimated() ) {
331 this.currentFrame = 0;
333 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
335 if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration
336 this.totalFrames = 1;
338 Y.AnimMgr.registerElement(this);
343 * Stops the animation. Normally called by AnimMgr when animation completes.
345 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
347 this.stop = function(finish) {
348 if (!this.isAnimated()) { // nothing to stop
353 this.currentFrame = this.totalFrames;
354 this._onTween.fire();
356 Y.AnimMgr.stop(this);
359 var onStart = function() {
362 this.runtimeAttributes = {};
363 for (var attr in this.attributes) {
364 this.setRuntimeAttribute(attr);
369 startTime = new Date();
373 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
377 var onTween = function() {
379 duration: new Date() - this.getStartTime(),
380 currentFrame: this.currentFrame
383 data.toString = function() {
385 'duration: ' + data.duration +
386 ', currentFrame: ' + data.currentFrame
390 this.onTween.fire(data);
392 var runtimeAttributes = this.runtimeAttributes;
394 for (var attr in runtimeAttributes) {
395 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
401 var onComplete = function() {
402 var actual_duration = (new Date() - startTime) / 1000 ;
405 duration: actual_duration,
406 frames: actualFrames,
407 fps: actualFrames / actual_duration
410 data.toString = function() {
412 'duration: ' + data.duration +
413 ', frames: ' + data.frames +
420 this.onComplete.fire(data);
424 * Custom event that fires after onStart, useful in subclassing
427 this._onStart = new Y.CustomEvent('_start', this, true);
430 * Custom event that fires when animation begins
431 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
434 this.onStart = new Y.CustomEvent('start', this);
437 * Custom event that fires between each frame
438 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
441 this.onTween = new Y.CustomEvent('tween', this);
444 * Custom event that fires after onTween
447 this._onTween = new Y.CustomEvent('_tween', this, true);
450 * Custom event that fires when animation ends
451 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
454 this.onComplete = new Y.CustomEvent('complete', this);
456 * Custom event that fires after onComplete
459 this._onComplete = new Y.CustomEvent('_complete', this, true);
461 this._onStart.subscribe(onStart);
462 this._onTween.subscribe(onTween);
463 this._onComplete.subscribe(onComplete);
470 * Handles animation queueing and threading.
471 * Used by Anim and subclasses.
473 * @namespace YAHOO.util
475 YAHOO.util.AnimMgr = new function() {
477 * Reference to the animation Interval.
485 * The current queue of registered animation objects.
493 * The number of active animations.
494 * @property tweenCount
501 * Base frame rate (frames per second).
502 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
510 * Interval delay in milliseconds, defaults to fastest possible.
518 * Adds an animation instance to the animation queue.
519 * All animation instances must be registered in order to animate.
520 * @method registerElement
521 * @param {object} tween The Anim instance to be be registered
523 this.registerElement = function(tween) {
524 queue[queue.length] = tween;
526 tween._onStart.fire();
531 * removes an animation instance from the animation queue.
532 * All animation instances must be registered in order to animate.
534 * @param {object} tween The Anim instance to be be registered
535 * @param {Int} index The index of the Anim instance
538 this.unRegister = function(tween, index) {
539 index = index || getIndex(tween);
540 if (!tween.isAnimated() || index == -1) {
544 tween._onComplete.fire();
545 queue.splice(index, 1);
548 if (tweenCount <= 0) {
556 * Starts the animation thread.
557 * Only one thread can run at a time.
560 this.start = function() {
561 if (thread === null) {
562 thread = setInterval(this.run, this.delay);
567 * Stops the animation thread or a specific animation instance.
569 * @param {object} tween A specific Anim instance to stop (optional)
570 * If no instance given, Manager stops thread and all animations.
572 this.stop = function(tween) {
574 clearInterval(thread);
576 for (var i = 0, len = queue.length; i < len; ++i) {
577 this.unRegister(queue[0], 0);
585 this.unRegister(tween);
590 * Called per Interval to handle each animation frame.
593 this.run = function() {
594 for (var i = 0, len = queue.length; i < len; ++i) {
595 var tween = queue[i];
596 if ( !tween || !tween.isAnimated() ) { continue; }
598 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
600 tween.currentFrame += 1;
602 if (tween.useSeconds) {
605 tween._onTween.fire();
607 else { YAHOO.util.AnimMgr.stop(tween, i); }
611 var getIndex = function(anim) {
612 for (var i = 0, len = queue.length; i < len; ++i) {
613 if (queue[i] == anim) {
614 return i; // note return;
621 * On the fly frame correction to keep animation on time.
622 * @method correctFrame
624 * @param {Object} tween The Anim instance being corrected.
626 var correctFrame = function(tween) {
627 var frames = tween.totalFrames;
628 var frame = tween.currentFrame;
629 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
630 var elapsed = (new Date() - tween.getStartTime());
633 if (elapsed < tween.duration * 1000) { // check if falling behind
634 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
635 } else { // went over duration, so jump to end
636 tweak = frames - (frame + 1);
638 if (tweak > 0 && isFinite(tweak)) { // adjust if needed
639 if (tween.currentFrame + tweak >= frames) {// dont go past last frame
640 tweak = frames - (frame + 1);
643 tween.currentFrame += tweak;
648 * Used to calculate Bezier splines for any number of control points.
650 * @namespace YAHOO.util
653 YAHOO.util.Bezier = new function() {
655 * Get the current position of the animated element based on t.
656 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
657 * At least 2 points are required (start and end).
658 * First point is start. Last point is end.
659 * Additional control points are optional.
660 * @method getPosition
661 * @param {Array} points An array containing Bezier points
662 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
663 * @return {Array} An array containing int x and y member data
665 this.getPosition = function(points, t) {
666 var n = points.length;
669 for (var i = 0; i < n; ++i){
670 tmp[i] = [points[i][0], points[i][1]]; // save input
673 for (var j = 1; j < n; ++j) {
674 for (i = 0; i < n - j; ++i) {
675 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
676 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
680 return [ tmp[0][0], tmp[0][1] ];
686 * Anim subclass for color transitions.
687 * <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,
688 * [255,255,255], or rgb(255,255,255)</p>
690 * @namespace YAHOO.util
691 * @requires YAHOO.util.Anim
692 * @requires YAHOO.util.AnimMgr
693 * @requires YAHOO.util.Easing
694 * @requires YAHOO.util.Bezier
695 * @requires YAHOO.util.Dom
696 * @requires YAHOO.util.Event
698 * @extends YAHOO.util.Anim
699 * @param {HTMLElement | String} el Reference to the element that will be animated
700 * @param {Object} attributes The attribute(s) to be animated.
701 * Each attribute is an object with at minimum a "to" or "by" member defined.
702 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
703 * All attribute names use camelCase.
704 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
705 * @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)
707 var ColorAnim = function(el, attributes, duration, method) {
708 ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
711 ColorAnim.NAME = 'ColorAnim';
715 YAHOO.extend(ColorAnim, Y.Anim);
717 var superclass = ColorAnim.superclass;
718 var proto = ColorAnim.prototype;
720 proto.patterns.color = /color$/i;
721 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
722 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
723 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
724 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
727 * Attempts to parse the given string and return a 3-tuple.
729 * @param {String} s The string to parse.
730 * @return {Array} The 3-tuple of rgb values.
732 proto.parseColor = function(s) {
733 if (s.length == 3) { return s; }
735 var c = this.patterns.hex.exec(s);
736 if (c && c.length == 4) {
737 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
740 c = this.patterns.rgb.exec(s);
741 if (c && c.length == 4) {
742 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
745 c = this.patterns.hex3.exec(s);
746 if (c && c.length == 4) {
747 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
753 proto.getAttribute = function(attr) {
754 var el = this.getEl();
755 if ( this.patterns.color.test(attr) ) {
756 var val = YAHOO.util.Dom.getStyle(el, attr);
758 if (this.patterns.transparent.test(val)) { // bgcolor default
759 var parent = el.parentNode; // try and get from an ancestor
760 val = Y.Dom.getStyle(parent, attr);
762 while (parent && this.patterns.transparent.test(val)) {
763 parent = parent.parentNode;
764 val = Y.Dom.getStyle(parent, attr);
765 if (parent.tagName.toUpperCase() == 'HTML') {
771 val = superclass.getAttribute.call(this, attr);
777 proto.doMethod = function(attr, start, end) {
780 if ( this.patterns.color.test(attr) ) {
782 for (var i = 0, len = start.length; i < len; ++i) {
783 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
786 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
789 val = superclass.doMethod.call(this, attr, start, end);
795 proto.setRuntimeAttribute = function(attr) {
796 superclass.setRuntimeAttribute.call(this, attr);
798 if ( this.patterns.color.test(attr) ) {
799 var attributes = this.attributes;
800 var start = this.parseColor(this.runtimeAttributes[attr].start);
801 var end = this.parseColor(this.runtimeAttributes[attr].end);
802 // fix colors if going "by"
803 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
804 end = this.parseColor(attributes[attr].by);
806 for (var i = 0, len = start.length; i < len; ++i) {
807 end[i] = start[i] + end[i];
811 this.runtimeAttributes[attr].start = start;
812 this.runtimeAttributes[attr].end = end;
816 Y.ColorAnim = ColorAnim;
819 TERMS OF USE - EASING EQUATIONS
820 Open source under the BSD License.
821 Copyright 2001 Robert Penner All rights reserved.
823 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
825 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
826 * 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.
827 * 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.
829 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.
833 * Singleton that determines how an animation proceeds from start to end.
835 * @namespace YAHOO.util
838 YAHOO.util.Easing = {
841 * Uniform speed between points.
843 * @param {Number} t Time value used to compute current value
844 * @param {Number} b Starting value
845 * @param {Number} c Delta between start and end values
846 * @param {Number} d Total length of animation
847 * @return {Number} The computed value for the current animation frame
849 easeNone: function (t, b, c, d) {
854 * Begins slowly and accelerates towards end. (quadratic)
856 * @param {Number} t Time value used to compute current value
857 * @param {Number} b Starting value
858 * @param {Number} c Delta between start and end values
859 * @param {Number} d Total length of animation
860 * @return {Number} The computed value for the current animation frame
862 easeIn: function (t, b, c, d) {
863 return c*(t/=d)*t + b;
867 * Begins quickly and decelerates towards end. (quadratic)
869 * @param {Number} t Time value used to compute current value
870 * @param {Number} b Starting value
871 * @param {Number} c Delta between start and end values
872 * @param {Number} d Total length of animation
873 * @return {Number} The computed value for the current animation frame
875 easeOut: function (t, b, c, d) {
876 return -c *(t/=d)*(t-2) + b;
880 * Begins slowly and decelerates towards end. (quadratic)
882 * @param {Number} t Time value used to compute current value
883 * @param {Number} b Starting value
884 * @param {Number} c Delta between start and end values
885 * @param {Number} d Total length of animation
886 * @return {Number} The computed value for the current animation frame
888 easeBoth: function (t, b, c, d) {
893 return -c/2 * ((--t)*(t-2) - 1) + b;
897 * Begins slowly and accelerates towards end. (quartic)
898 * @method easeInStrong
899 * @param {Number} t Time value used to compute current value
900 * @param {Number} b Starting value
901 * @param {Number} c Delta between start and end values
902 * @param {Number} d Total length of animation
903 * @return {Number} The computed value for the current animation frame
905 easeInStrong: function (t, b, c, d) {
906 return c*(t/=d)*t*t*t + b;
910 * Begins quickly and decelerates towards end. (quartic)
911 * @method easeOutStrong
912 * @param {Number} t Time value used to compute current value
913 * @param {Number} b Starting value
914 * @param {Number} c Delta between start and end values
915 * @param {Number} d Total length of animation
916 * @return {Number} The computed value for the current animation frame
918 easeOutStrong: function (t, b, c, d) {
919 return -c * ((t=t/d-1)*t*t*t - 1) + b;
923 * Begins slowly and decelerates towards end. (quartic)
924 * @method easeBothStrong
925 * @param {Number} t Time value used to compute current value
926 * @param {Number} b Starting value
927 * @param {Number} c Delta between start and end values
928 * @param {Number} d Total length of animation
929 * @return {Number} The computed value for the current animation frame
931 easeBothStrong: function (t, b, c, d) {
933 return c/2*t*t*t*t + b;
936 return -c/2 * ((t-=2)*t*t*t - 2) + b;
940 * Snap in elastic effect.
942 * @param {Number} t Time value used to compute current value
943 * @param {Number} b Starting value
944 * @param {Number} c Delta between start and end values
945 * @param {Number} d Total length of animation
946 * @param {Number} a Amplitude (optional)
947 * @param {Number} p Period (optional)
948 * @return {Number} The computed value for the current animation frame
951 elasticIn: function (t, b, c, d, a, p) {
955 if ( (t /= d) == 1 ) {
962 if (!a || a < Math.abs(c)) {
967 var s = p/(2*Math.PI) * Math.asin (c/a);
970 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
974 * Snap out elastic effect.
976 * @param {Number} t Time value used to compute current value
977 * @param {Number} b Starting value
978 * @param {Number} c Delta between start and end values
979 * @param {Number} d Total length of animation
980 * @param {Number} a Amplitude (optional)
981 * @param {Number} p Period (optional)
982 * @return {Number} The computed value for the current animation frame
984 elasticOut: function (t, b, c, d, a, p) {
988 if ( (t /= d) == 1 ) {
995 if (!a || a < Math.abs(c)) {
1000 var s = p/(2*Math.PI) * Math.asin (c/a);
1003 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1007 * Snap both elastic effect.
1008 * @method elasticBoth
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} a Amplitude (optional)
1014 * @param {Number} p Period (optional)
1015 * @return {Number} The computed value for the current animation frame
1017 elasticBoth: function (t, b, c, d, a, p) {
1022 if ( (t /= d/2) == 2 ) {
1030 if ( !a || a < Math.abs(c) ) {
1035 var s = p/(2*Math.PI) * Math.asin (c/a);
1039 return -.5*(a*Math.pow(2,10*(t-=1)) *
1040 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1042 return a*Math.pow(2,-10*(t-=1)) *
1043 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1048 * Backtracks slightly, then reverses direction and moves to end.
1050 * @param {Number} t Time value used to compute current value
1051 * @param {Number} b Starting value
1052 * @param {Number} c Delta between start and end values
1053 * @param {Number} d Total length of animation
1054 * @param {Number} s Overshoot (optional)
1055 * @return {Number} The computed value for the current animation frame
1057 backIn: function (t, b, c, d, s) {
1058 if (typeof s == 'undefined') {
1061 return c*(t/=d)*t*((s+1)*t - s) + b;
1065 * Overshoots end, then reverses and comes back to end.
1067 * @param {Number} t Time value used to compute current value
1068 * @param {Number} b Starting value
1069 * @param {Number} c Delta between start and end values
1070 * @param {Number} d Total length of animation
1071 * @param {Number} s Overshoot (optional)
1072 * @return {Number} The computed value for the current animation frame
1074 backOut: function (t, b, c, d, s) {
1075 if (typeof s == 'undefined') {
1078 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1082 * Backtracks slightly, then reverses direction, overshoots end,
1083 * then reverses and comes back to end.
1085 * @param {Number} t Time value used to compute current value
1086 * @param {Number} b Starting value
1087 * @param {Number} c Delta between start and end values
1088 * @param {Number} d Total length of animation
1089 * @param {Number} s Overshoot (optional)
1090 * @return {Number} The computed value for the current animation frame
1092 backBoth: function (t, b, c, d, s) {
1093 if (typeof s == 'undefined') {
1097 if ((t /= d/2 ) < 1) {
1098 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1100 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1104 * Bounce off of start.
1106 * @param {Number} t Time value used to compute current value
1107 * @param {Number} b Starting value
1108 * @param {Number} c Delta between start and end values
1109 * @param {Number} d Total length of animation
1110 * @return {Number} The computed value for the current animation frame
1112 bounceIn: function (t, b, c, d) {
1113 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1119 * @param {Number} t Time value used to compute current value
1120 * @param {Number} b Starting value
1121 * @param {Number} c Delta between start and end values
1122 * @param {Number} d Total length of animation
1123 * @return {Number} The computed value for the current animation frame
1125 bounceOut: function (t, b, c, d) {
1126 if ((t/=d) < (1/2.75)) {
1127 return c*(7.5625*t*t) + b;
1128 } else if (t < (2/2.75)) {
1129 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1130 } else if (t < (2.5/2.75)) {
1131 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1133 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1137 * Bounces off start and end.
1138 * @method bounceBoth
1139 * @param {Number} t Time value used to compute current value
1140 * @param {Number} b Starting value
1141 * @param {Number} c Delta between start and end values
1142 * @param {Number} d Total length of animation
1143 * @return {Number} The computed value for the current animation frame
1145 bounceBoth: function (t, b, c, d) {
1147 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1149 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1155 * Anim subclass for moving elements along a path defined by the "points"
1156 * member of "attributes". All "points" are arrays with x, y coordinates.
1157 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1159 * @namespace YAHOO.util
1160 * @requires YAHOO.util.Anim
1161 * @requires YAHOO.util.AnimMgr
1162 * @requires YAHOO.util.Easing
1163 * @requires YAHOO.util.Bezier
1164 * @requires YAHOO.util.Dom
1165 * @requires YAHOO.util.Event
1166 * @requires YAHOO.util.CustomEvent
1168 * @extends YAHOO.util.ColorAnim
1169 * @param {String | HTMLElement} el Reference to the element that will be animated
1170 * @param {Object} attributes The attribute(s) to be animated.
1171 * Each attribute is an object with at minimum a "to" or "by" member defined.
1172 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1173 * All attribute names use camelCase.
1174 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1175 * @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)
1177 var Motion = function(el, attributes, duration, method) {
1178 if (el) { // dont break existing subclasses not using YAHOO.extend
1179 Motion.superclass.constructor.call(this, el, attributes, duration, method);
1184 Motion.NAME = 'Motion';
1188 YAHOO.extend(Motion, Y.ColorAnim);
1190 var superclass = Motion.superclass;
1191 var proto = Motion.prototype;
1193 proto.patterns.points = /^points$/i;
1195 proto.setAttribute = function(attr, val, unit) {
1196 if ( this.patterns.points.test(attr) ) {
1197 unit = unit || 'px';
1198 superclass.setAttribute.call(this, 'left', val[0], unit);
1199 superclass.setAttribute.call(this, 'top', val[1], unit);
1201 superclass.setAttribute.call(this, attr, val, unit);
1205 proto.getAttribute = function(attr) {
1206 if ( this.patterns.points.test(attr) ) {
1208 superclass.getAttribute.call(this, 'left'),
1209 superclass.getAttribute.call(this, 'top')
1212 val = superclass.getAttribute.call(this, attr);
1218 proto.doMethod = function(attr, start, end) {
1221 if ( this.patterns.points.test(attr) ) {
1222 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1223 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1225 val = superclass.doMethod.call(this, attr, start, end);
1230 proto.setRuntimeAttribute = function(attr) {
1231 if ( this.patterns.points.test(attr) ) {
1232 var el = this.getEl();
1233 var attributes = this.attributes;
1235 var control = attributes['points']['control'] || [];
1239 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1240 control = [control];
1241 } else { // break reference to attributes.points.control
1243 for (i = 0, len = control.length; i< len; ++i) {
1244 tmp[i] = control[i];
1249 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1250 Y.Dom.setStyle(el, 'position', 'relative');
1253 if ( isset(attributes['points']['from']) ) {
1254 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1256 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1258 start = this.getAttribute('points'); // get actual top & left
1260 // TO beats BY, per SMIL 2.1 spec
1261 if ( isset(attributes['points']['to']) ) {
1262 end = translateValues.call(this, attributes['points']['to'], start);
1264 var pageXY = Y.Dom.getXY(this.getEl());
1265 for (i = 0, len = control.length; i < len; ++i) {
1266 control[i] = translateValues.call(this, control[i], start);
1270 } else if ( isset(attributes['points']['by']) ) {
1271 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1273 for (i = 0, len = control.length; i < len; ++i) {
1274 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1278 this.runtimeAttributes[attr] = [start];
1280 if (control.length > 0) {
1281 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1284 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1287 superclass.setRuntimeAttribute.call(this, attr);
1291 var translateValues = function(val, start) {
1292 var pageXY = Y.Dom.getXY(this.getEl());
1293 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1298 var isset = function(prop) {
1299 return (typeof prop !== 'undefined');
1306 * Anim subclass for scrolling elements to a position defined by the "scroll"
1307 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1308 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1310 * @namespace YAHOO.util
1311 * @requires YAHOO.util.Anim
1312 * @requires YAHOO.util.AnimMgr
1313 * @requires YAHOO.util.Easing
1314 * @requires YAHOO.util.Bezier
1315 * @requires YAHOO.util.Dom
1316 * @requires YAHOO.util.Event
1317 * @requires YAHOO.util.CustomEvent
1318 * @extends YAHOO.util.ColorAnim
1320 * @param {String or HTMLElement} el Reference to the element that will be animated
1321 * @param {Object} attributes The attribute(s) to be animated.
1322 * Each attribute is an object with at minimum a "to" or "by" member defined.
1323 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1324 * All attribute names use camelCase.
1325 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1326 * @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)
1328 var Scroll = function(el, attributes, duration, method) {
1329 if (el) { // dont break existing subclasses not using YAHOO.extend
1330 Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1334 Scroll.NAME = 'Scroll';
1338 YAHOO.extend(Scroll, Y.ColorAnim);
1340 var superclass = Scroll.superclass;
1341 var proto = Scroll.prototype;
1343 proto.doMethod = function(attr, start, end) {
1346 if (attr == 'scroll') {
1348 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1349 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1353 val = superclass.doMethod.call(this, attr, start, end);
1358 proto.getAttribute = function(attr) {
1360 var el = this.getEl();
1362 if (attr == 'scroll') {
1363 val = [ el.scrollLeft, el.scrollTop ];
1365 val = superclass.getAttribute.call(this, attr);
1371 proto.setAttribute = function(attr, val, unit) {
1372 var el = this.getEl();
1374 if (attr == 'scroll') {
1375 el.scrollLeft = val[0];
1376 el.scrollTop = val[1];
1378 superclass.setAttribute.call(this, attr, val, unit);
1384 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.5.2", build: "1076"});