2 Copyright (c) 2009, 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 var el = this.getEl();
93 if ( this.patterns.noNegatives.test(attr) ) {
94 val = (val > 0) ? val : 0;
98 Y.Dom.setStyle(el, attr, val + unit);
99 } else if (attr in el) {
105 * Returns current value of the attribute.
106 * @method getAttribute
107 * @param {String} attr The name of the attribute.
108 * @return {Number} val The current value of the attribute.
110 getAttribute: function(attr) {
111 var el = this.getEl();
112 var val = Y.Dom.getStyle(el, attr);
114 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
115 return parseFloat(val);
118 var a = this.patterns.offsetAttribute.exec(attr) || [];
119 var pos = !!( a[3] ); // top or left
120 var box = !!( a[2] ); // width or height
123 // use offsets for width/height and abs pos top/left
124 if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
125 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
126 } else { // default to zero for other 'auto'
129 } else if (attr in el) {
137 * Returns the unit to use when none is supplied.
138 * @method getDefaultUnit
139 * @param {attr} attr The name of the attribute.
140 * @return {String} The default unit to be used.
142 getDefaultUnit: function(attr) {
143 if ( this.patterns.defaultUnit.test(attr) ) {
151 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
152 * @method setRuntimeAttribute
153 * @param {Object} attr The attribute object
156 setRuntimeAttribute: function(attr) {
159 var attributes = this.attributes;
161 this.runtimeAttributes[attr] = {};
163 var isset = function(prop) {
164 return (typeof prop !== 'undefined');
167 if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
168 return false; // note return; nothing to animate to
171 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
173 // To beats by, per SMIL 2.1 spec
174 if ( isset(attributes[attr]['to']) ) {
175 end = attributes[attr]['to'];
176 } else if ( isset(attributes[attr]['by']) ) {
177 if (start.constructor == Array) {
179 for (var i = 0, len = start.length; i < len; ++i) {
180 end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by"
183 end = start + attributes[attr]['by'] * 1;
187 this.runtimeAttributes[attr].start = start;
188 this.runtimeAttributes[attr].end = end;
190 // set units if needed
191 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
192 attributes[attr]['unit'] : this.getDefaultUnit(attr);
197 * Constructor for Anim instance.
199 * @param {String | HTMLElement} el Reference to the element that will be animated
200 * @param {Object} attributes The attribute(s) to be animated.
201 * Each attribute is an object with at minimum a "to" or "by" member defined.
202 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
203 * All attribute names use camelCase.
204 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
205 * @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)
207 init: function(el, attributes, duration, method) {
209 * Whether or not the animation is running.
210 * @property isAnimated
214 var isAnimated = false;
217 * A Date object that is created when the animation begins.
218 * @property startTime
222 var startTime = null;
225 * The number of frames this animation was able to execute.
226 * @property actualFrames
230 var actualFrames = 0;
233 * The element to be animated.
241 * The collection of attributes to be animated.
242 * Each attribute must have at least a "to" or "by" defined in order to animate.
243 * If "to" is supplied, the animation will end with the attribute at that value.
244 * If "by" is supplied, the animation will end at that value plus its starting value.
245 * If both are supplied, "to" is used, and "by" is ignored.
246 * 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).
247 * @property attributes
250 this.attributes = attributes || {};
253 * The length of the animation. Defaults to "1" (second).
257 this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
260 * The method that will provide values to the attribute(s) during the animation.
261 * Defaults to "YAHOO.util.Easing.easeNone".
265 this.method = method || Y.Easing.easeNone;
268 * Whether or not the duration should be treated as seconds.
270 * @property useSeconds
273 this.useSeconds = true; // default to seconds
276 * The location of the current animation on the timeline.
277 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
278 * @property currentFrame
281 this.currentFrame = 0;
284 * The total number of frames to be executed.
285 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
286 * @property totalFrames
289 this.totalFrames = Y.AnimMgr.fps;
292 * Changes the animated element
295 this.setEl = function(element) {
296 el = Y.Dom.get(element);
300 * Returns a reference to the animated element.
302 * @return {HTMLElement}
304 this.getEl = function() { return el; };
307 * Checks whether the element is currently animated.
309 * @return {Boolean} current value of isAnimated.
311 this.isAnimated = function() {
316 * Returns the animation start time.
317 * @method getStartTime
318 * @return {Date} current value of startTime.
320 this.getStartTime = function() {
324 this.runtimeAttributes = {};
327 logger.log = function() {YAHOO.log.apply(window, arguments)};
329 logger.log('creating new instance of ' + this);
332 * Starts the animation by registering it with the animation manager.
335 this.animate = function() {
336 if ( this.isAnimated() ) {
340 this.currentFrame = 0;
342 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
344 if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration
345 this.totalFrames = 1;
347 Y.AnimMgr.registerElement(this);
352 * Stops the animation. Normally called by AnimMgr when animation completes.
354 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
356 this.stop = function(finish) {
357 if (!this.isAnimated()) { // nothing to stop
362 this.currentFrame = this.totalFrames;
363 this._onTween.fire();
365 Y.AnimMgr.stop(this);
368 var onStart = function() {
371 this.runtimeAttributes = {};
372 for (var attr in this.attributes) {
373 this.setRuntimeAttribute(attr);
378 startTime = new Date();
382 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
386 var onTween = function() {
388 duration: new Date() - this.getStartTime(),
389 currentFrame: this.currentFrame
392 data.toString = function() {
394 'duration: ' + data.duration +
395 ', currentFrame: ' + data.currentFrame
399 this.onTween.fire(data);
401 var runtimeAttributes = this.runtimeAttributes;
403 for (var attr in runtimeAttributes) {
404 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
410 var onComplete = function() {
411 var actual_duration = (new Date() - startTime) / 1000 ;
414 duration: actual_duration,
415 frames: actualFrames,
416 fps: actualFrames / actual_duration
419 data.toString = function() {
421 'duration: ' + data.duration +
422 ', frames: ' + data.frames +
429 this.onComplete.fire(data);
433 * Custom event that fires after onStart, useful in subclassing
436 this._onStart = new Y.CustomEvent('_start', this, true);
439 * Custom event that fires when animation begins
440 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
443 this.onStart = new Y.CustomEvent('start', this);
446 * Custom event that fires between each frame
447 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
450 this.onTween = new Y.CustomEvent('tween', this);
453 * Custom event that fires after onTween
456 this._onTween = new Y.CustomEvent('_tween', this, true);
459 * Custom event that fires when animation ends
460 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
463 this.onComplete = new Y.CustomEvent('complete', this);
465 * Custom event that fires after onComplete
468 this._onComplete = new Y.CustomEvent('_complete', this, true);
470 this._onStart.subscribe(onStart);
471 this._onTween.subscribe(onTween);
472 this._onComplete.subscribe(onComplete);
479 * Handles animation queueing and threading.
480 * Used by Anim and subclasses.
482 * @namespace YAHOO.util
484 YAHOO.util.AnimMgr = new function() {
486 * Reference to the animation Interval.
494 * The current queue of registered animation objects.
502 * The number of active animations.
503 * @property tweenCount
510 * Base frame rate (frames per second).
511 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
519 * Interval delay in milliseconds, defaults to fastest possible.
527 * Adds an animation instance to the animation queue.
528 * All animation instances must be registered in order to animate.
529 * @method registerElement
530 * @param {object} tween The Anim instance to be be registered
532 this.registerElement = function(tween) {
533 queue[queue.length] = tween;
535 tween._onStart.fire();
540 * removes an animation instance from the animation queue.
541 * All animation instances must be registered in order to animate.
543 * @param {object} tween The Anim instance to be be registered
544 * @param {Int} index The index of the Anim instance
547 this.unRegister = function(tween, index) {
548 index = index || getIndex(tween);
549 if (!tween.isAnimated() || index == -1) {
553 tween._onComplete.fire();
554 queue.splice(index, 1);
557 if (tweenCount <= 0) {
565 * Starts the animation thread.
566 * Only one thread can run at a time.
569 this.start = function() {
570 if (thread === null) {
571 thread = setInterval(this.run, this.delay);
576 * Stops the animation thread or a specific animation instance.
578 * @param {object} tween A specific Anim instance to stop (optional)
579 * If no instance given, Manager stops thread and all animations.
581 this.stop = function(tween) {
583 clearInterval(thread);
585 for (var i = 0, len = queue.length; i < len; ++i) {
586 this.unRegister(queue[0], 0);
594 this.unRegister(tween);
599 * Called per Interval to handle each animation frame.
602 this.run = function() {
603 for (var i = 0, len = queue.length; i < len; ++i) {
604 var tween = queue[i];
605 if ( !tween || !tween.isAnimated() ) { continue; }
607 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
609 tween.currentFrame += 1;
611 if (tween.useSeconds) {
614 tween._onTween.fire();
616 else { YAHOO.util.AnimMgr.stop(tween, i); }
620 var getIndex = function(anim) {
621 for (var i = 0, len = queue.length; i < len; ++i) {
622 if (queue[i] == anim) {
623 return i; // note return;
630 * On the fly frame correction to keep animation on time.
631 * @method correctFrame
633 * @param {Object} tween The Anim instance being corrected.
635 var correctFrame = function(tween) {
636 var frames = tween.totalFrames;
637 var frame = tween.currentFrame;
638 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
639 var elapsed = (new Date() - tween.getStartTime());
642 if (elapsed < tween.duration * 1000) { // check if falling behind
643 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
644 } else { // went over duration, so jump to end
645 tweak = frames - (frame + 1);
647 if (tweak > 0 && isFinite(tweak)) { // adjust if needed
648 if (tween.currentFrame + tweak >= frames) {// dont go past last frame
649 tweak = frames - (frame + 1);
652 tween.currentFrame += tweak;
657 * Used to calculate Bezier splines for any number of control points.
659 * @namespace YAHOO.util
662 YAHOO.util.Bezier = new function() {
664 * Get the current position of the animated element based on t.
665 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
666 * At least 2 points are required (start and end).
667 * First point is start. Last point is end.
668 * Additional control points are optional.
669 * @method getPosition
670 * @param {Array} points An array containing Bezier points
671 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
672 * @return {Array} An array containing int x and y member data
674 this.getPosition = function(points, t) {
675 var n = points.length;
678 for (var i = 0; i < n; ++i){
679 tmp[i] = [points[i][0], points[i][1]]; // save input
682 for (var j = 1; j < n; ++j) {
683 for (i = 0; i < n - j; ++i) {
684 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
685 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
689 return [ tmp[0][0], tmp[0][1] ];
695 * Anim subclass for color transitions.
696 * <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,
697 * [255,255,255], or rgb(255,255,255)</p>
699 * @namespace YAHOO.util
700 * @requires YAHOO.util.Anim
701 * @requires YAHOO.util.AnimMgr
702 * @requires YAHOO.util.Easing
703 * @requires YAHOO.util.Bezier
704 * @requires YAHOO.util.Dom
705 * @requires YAHOO.util.Event
707 * @extends YAHOO.util.Anim
708 * @param {HTMLElement | String} el Reference to the element that will be animated
709 * @param {Object} attributes The attribute(s) to be animated.
710 * Each attribute is an object with at minimum a "to" or "by" member defined.
711 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
712 * All attribute names use camelCase.
713 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
714 * @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)
716 var ColorAnim = function(el, attributes, duration, method) {
717 ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
720 ColorAnim.NAME = 'ColorAnim';
722 ColorAnim.DEFAULT_BGCOLOR = '#fff';
725 YAHOO.extend(ColorAnim, Y.Anim);
727 var superclass = ColorAnim.superclass;
728 var proto = ColorAnim.prototype;
730 proto.patterns.color = /color$/i;
731 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
732 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
733 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
734 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
737 * Attempts to parse the given string and return a 3-tuple.
739 * @param {String} s The string to parse.
740 * @return {Array} The 3-tuple of rgb values.
742 proto.parseColor = function(s) {
743 if (s.length == 3) { return s; }
745 var c = this.patterns.hex.exec(s);
746 if (c && c.length == 4) {
747 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
750 c = this.patterns.rgb.exec(s);
751 if (c && c.length == 4) {
752 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
755 c = this.patterns.hex3.exec(s);
756 if (c && c.length == 4) {
757 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
763 proto.getAttribute = function(attr) {
764 var el = this.getEl();
765 if (this.patterns.color.test(attr) ) {
766 var val = YAHOO.util.Dom.getStyle(el, attr);
769 if (this.patterns.transparent.test(val)) { // bgcolor default
770 var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
771 return !that.patterns.transparent.test(val);
775 val = Y.Dom.getStyle(parent, attr);
777 val = ColorAnim.DEFAULT_BGCOLOR;
781 val = superclass.getAttribute.call(this, attr);
787 proto.doMethod = function(attr, start, end) {
790 if ( this.patterns.color.test(attr) ) {
792 for (var i = 0, len = start.length; i < len; ++i) {
793 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
796 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
799 val = superclass.doMethod.call(this, attr, start, end);
805 proto.setRuntimeAttribute = function(attr) {
806 superclass.setRuntimeAttribute.call(this, attr);
808 if ( this.patterns.color.test(attr) ) {
809 var attributes = this.attributes;
810 var start = this.parseColor(this.runtimeAttributes[attr].start);
811 var end = this.parseColor(this.runtimeAttributes[attr].end);
812 // fix colors if going "by"
813 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
814 end = this.parseColor(attributes[attr].by);
816 for (var i = 0, len = start.length; i < len; ++i) {
817 end[i] = start[i] + end[i];
821 this.runtimeAttributes[attr].start = start;
822 this.runtimeAttributes[attr].end = end;
826 Y.ColorAnim = ColorAnim;
829 TERMS OF USE - EASING EQUATIONS
830 Open source under the BSD License.
831 Copyright 2001 Robert Penner All rights reserved.
833 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
835 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
836 * 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.
837 * 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.
839 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.
843 * Singleton that determines how an animation proceeds from start to end.
845 * @namespace YAHOO.util
848 YAHOO.util.Easing = {
851 * Uniform speed between points.
853 * @param {Number} t Time value used to compute current value
854 * @param {Number} b Starting value
855 * @param {Number} c Delta between start and end values
856 * @param {Number} d Total length of animation
857 * @return {Number} The computed value for the current animation frame
859 easeNone: function (t, b, c, d) {
864 * Begins slowly and accelerates towards end.
866 * @param {Number} t Time value used to compute current value
867 * @param {Number} b Starting value
868 * @param {Number} c Delta between start and end values
869 * @param {Number} d Total length of animation
870 * @return {Number} The computed value for the current animation frame
872 easeIn: function (t, b, c, d) {
873 return c*(t/=d)*t + b;
877 * Begins quickly and decelerates towards end.
879 * @param {Number} t Time value used to compute current value
880 * @param {Number} b Starting value
881 * @param {Number} c Delta between start and end values
882 * @param {Number} d Total length of animation
883 * @return {Number} The computed value for the current animation frame
885 easeOut: function (t, b, c, d) {
886 return -c *(t/=d)*(t-2) + b;
890 * Begins slowly and decelerates towards end.
892 * @param {Number} t Time value used to compute current value
893 * @param {Number} b Starting value
894 * @param {Number} c Delta between start and end values
895 * @param {Number} d Total length of animation
896 * @return {Number} The computed value for the current animation frame
898 easeBoth: function (t, b, c, d) {
903 return -c/2 * ((--t)*(t-2) - 1) + b;
907 * Begins slowly and accelerates towards end.
908 * @method easeInStrong
909 * @param {Number} t Time value used to compute current value
910 * @param {Number} b Starting value
911 * @param {Number} c Delta between start and end values
912 * @param {Number} d Total length of animation
913 * @return {Number} The computed value for the current animation frame
915 easeInStrong: function (t, b, c, d) {
916 return c*(t/=d)*t*t*t + b;
920 * Begins quickly and decelerates towards end.
921 * @method easeOutStrong
922 * @param {Number} t Time value used to compute current value
923 * @param {Number} b Starting value
924 * @param {Number} c Delta between start and end values
925 * @param {Number} d Total length of animation
926 * @return {Number} The computed value for the current animation frame
928 easeOutStrong: function (t, b, c, d) {
929 return -c * ((t=t/d-1)*t*t*t - 1) + b;
933 * Begins slowly and decelerates towards end.
934 * @method easeBothStrong
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 * @return {Number} The computed value for the current animation frame
941 easeBothStrong: function (t, b, c, d) {
943 return c/2*t*t*t*t + b;
946 return -c/2 * ((t-=2)*t*t*t - 2) + b;
950 * Snap in elastic effect.
952 * @param {Number} t Time value used to compute current value
953 * @param {Number} b Starting value
954 * @param {Number} c Delta between start and end values
955 * @param {Number} d Total length of animation
956 * @param {Number} a Amplitude (optional)
957 * @param {Number} p Period (optional)
958 * @return {Number} The computed value for the current animation frame
961 elasticIn: function (t, b, c, d, a, p) {
965 if ( (t /= d) == 1 ) {
972 if (!a || a < Math.abs(c)) {
977 var s = p/(2*Math.PI) * Math.asin (c/a);
980 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
984 * Snap out elastic effect.
986 * @param {Number} t Time value used to compute current value
987 * @param {Number} b Starting value
988 * @param {Number} c Delta between start and end values
989 * @param {Number} d Total length of animation
990 * @param {Number} a Amplitude (optional)
991 * @param {Number} p Period (optional)
992 * @return {Number} The computed value for the current animation frame
994 elasticOut: function (t, b, c, d, a, p) {
998 if ( (t /= d) == 1 ) {
1005 if (!a || a < Math.abs(c)) {
1010 var s = p/(2*Math.PI) * Math.asin (c/a);
1013 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1017 * Snap both elastic effect.
1018 * @method elasticBoth
1019 * @param {Number} t Time value used to compute current value
1020 * @param {Number} b Starting value
1021 * @param {Number} c Delta between start and end values
1022 * @param {Number} d Total length of animation
1023 * @param {Number} a Amplitude (optional)
1024 * @param {Number} p Period (optional)
1025 * @return {Number} The computed value for the current animation frame
1027 elasticBoth: function (t, b, c, d, a, p) {
1032 if ( (t /= d/2) == 2 ) {
1040 if ( !a || a < Math.abs(c) ) {
1045 var s = p/(2*Math.PI) * Math.asin (c/a);
1049 return -.5*(a*Math.pow(2,10*(t-=1)) *
1050 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1052 return a*Math.pow(2,-10*(t-=1)) *
1053 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1058 * Backtracks slightly, then reverses direction and moves to end.
1060 * @param {Number} t Time value used to compute current value
1061 * @param {Number} b Starting value
1062 * @param {Number} c Delta between start and end values
1063 * @param {Number} d Total length of animation
1064 * @param {Number} s Overshoot (optional)
1065 * @return {Number} The computed value for the current animation frame
1067 backIn: function (t, b, c, d, s) {
1068 if (typeof s == 'undefined') {
1071 return c*(t/=d)*t*((s+1)*t - s) + b;
1075 * Overshoots end, then reverses and comes back to end.
1077 * @param {Number} t Time value used to compute current value
1078 * @param {Number} b Starting value
1079 * @param {Number} c Delta between start and end values
1080 * @param {Number} d Total length of animation
1081 * @param {Number} s Overshoot (optional)
1082 * @return {Number} The computed value for the current animation frame
1084 backOut: function (t, b, c, d, s) {
1085 if (typeof s == 'undefined') {
1088 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1092 * Backtracks slightly, then reverses direction, overshoots end,
1093 * then reverses and comes back to end.
1095 * @param {Number} t Time value used to compute current value
1096 * @param {Number} b Starting value
1097 * @param {Number} c Delta between start and end values
1098 * @param {Number} d Total length of animation
1099 * @param {Number} s Overshoot (optional)
1100 * @return {Number} The computed value for the current animation frame
1102 backBoth: function (t, b, c, d, s) {
1103 if (typeof s == 'undefined') {
1107 if ((t /= d/2 ) < 1) {
1108 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1110 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1114 * Bounce off of start.
1116 * @param {Number} t Time value used to compute current value
1117 * @param {Number} b Starting value
1118 * @param {Number} c Delta between start and end values
1119 * @param {Number} d Total length of animation
1120 * @return {Number} The computed value for the current animation frame
1122 bounceIn: function (t, b, c, d) {
1123 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1129 * @param {Number} t Time value used to compute current value
1130 * @param {Number} b Starting value
1131 * @param {Number} c Delta between start and end values
1132 * @param {Number} d Total length of animation
1133 * @return {Number} The computed value for the current animation frame
1135 bounceOut: function (t, b, c, d) {
1136 if ((t/=d) < (1/2.75)) {
1137 return c*(7.5625*t*t) + b;
1138 } else if (t < (2/2.75)) {
1139 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1140 } else if (t < (2.5/2.75)) {
1141 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1143 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1147 * Bounces off start and end.
1148 * @method bounceBoth
1149 * @param {Number} t Time value used to compute current value
1150 * @param {Number} b Starting value
1151 * @param {Number} c Delta between start and end values
1152 * @param {Number} d Total length of animation
1153 * @return {Number} The computed value for the current animation frame
1155 bounceBoth: function (t, b, c, d) {
1157 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1159 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1165 * Anim subclass for moving elements along a path defined by the "points"
1166 * member of "attributes". All "points" are arrays with x, y coordinates.
1167 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1169 * @namespace YAHOO.util
1170 * @requires YAHOO.util.Anim
1171 * @requires YAHOO.util.AnimMgr
1172 * @requires YAHOO.util.Easing
1173 * @requires YAHOO.util.Bezier
1174 * @requires YAHOO.util.Dom
1175 * @requires YAHOO.util.Event
1176 * @requires YAHOO.util.CustomEvent
1178 * @extends YAHOO.util.ColorAnim
1179 * @param {String | HTMLElement} el Reference to the element that will be animated
1180 * @param {Object} attributes The attribute(s) to be animated.
1181 * Each attribute is an object with at minimum a "to" or "by" member defined.
1182 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1183 * All attribute names use camelCase.
1184 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1185 * @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)
1187 var Motion = function(el, attributes, duration, method) {
1188 if (el) { // dont break existing subclasses not using YAHOO.extend
1189 Motion.superclass.constructor.call(this, el, attributes, duration, method);
1194 Motion.NAME = 'Motion';
1198 YAHOO.extend(Motion, Y.ColorAnim);
1200 var superclass = Motion.superclass;
1201 var proto = Motion.prototype;
1203 proto.patterns.points = /^points$/i;
1205 proto.setAttribute = function(attr, val, unit) {
1206 if ( this.patterns.points.test(attr) ) {
1207 unit = unit || 'px';
1208 superclass.setAttribute.call(this, 'left', val[0], unit);
1209 superclass.setAttribute.call(this, 'top', val[1], unit);
1211 superclass.setAttribute.call(this, attr, val, unit);
1215 proto.getAttribute = function(attr) {
1216 if ( this.patterns.points.test(attr) ) {
1218 superclass.getAttribute.call(this, 'left'),
1219 superclass.getAttribute.call(this, 'top')
1222 val = superclass.getAttribute.call(this, attr);
1228 proto.doMethod = function(attr, start, end) {
1231 if ( this.patterns.points.test(attr) ) {
1232 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1233 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1235 val = superclass.doMethod.call(this, attr, start, end);
1240 proto.setRuntimeAttribute = function(attr) {
1241 if ( this.patterns.points.test(attr) ) {
1242 var el = this.getEl();
1243 var attributes = this.attributes;
1245 var control = attributes['points']['control'] || [];
1249 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1250 control = [control];
1251 } else { // break reference to attributes.points.control
1253 for (i = 0, len = control.length; i< len; ++i) {
1254 tmp[i] = control[i];
1259 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1260 Y.Dom.setStyle(el, 'position', 'relative');
1263 if ( isset(attributes['points']['from']) ) {
1264 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1266 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1268 start = this.getAttribute('points'); // get actual top & left
1270 // TO beats BY, per SMIL 2.1 spec
1271 if ( isset(attributes['points']['to']) ) {
1272 end = translateValues.call(this, attributes['points']['to'], start);
1274 var pageXY = Y.Dom.getXY(this.getEl());
1275 for (i = 0, len = control.length; i < len; ++i) {
1276 control[i] = translateValues.call(this, control[i], start);
1280 } else if ( isset(attributes['points']['by']) ) {
1281 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1283 for (i = 0, len = control.length; i < len; ++i) {
1284 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1288 this.runtimeAttributes[attr] = [start];
1290 if (control.length > 0) {
1291 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1294 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1297 superclass.setRuntimeAttribute.call(this, attr);
1301 var translateValues = function(val, start) {
1302 var pageXY = Y.Dom.getXY(this.getEl());
1303 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1308 var isset = function(prop) {
1309 return (typeof prop !== 'undefined');
1316 * Anim subclass for scrolling elements to a position defined by the "scroll"
1317 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1318 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1320 * @namespace YAHOO.util
1321 * @requires YAHOO.util.Anim
1322 * @requires YAHOO.util.AnimMgr
1323 * @requires YAHOO.util.Easing
1324 * @requires YAHOO.util.Bezier
1325 * @requires YAHOO.util.Dom
1326 * @requires YAHOO.util.Event
1327 * @requires YAHOO.util.CustomEvent
1328 * @extends YAHOO.util.ColorAnim
1330 * @param {String or HTMLElement} el Reference to the element that will be animated
1331 * @param {Object} attributes The attribute(s) to be animated.
1332 * Each attribute is an object with at minimum a "to" or "by" member defined.
1333 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1334 * All attribute names use camelCase.
1335 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1336 * @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)
1338 var Scroll = function(el, attributes, duration, method) {
1339 if (el) { // dont break existing subclasses not using YAHOO.extend
1340 Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1344 Scroll.NAME = 'Scroll';
1348 YAHOO.extend(Scroll, Y.ColorAnim);
1350 var superclass = Scroll.superclass;
1351 var proto = Scroll.prototype;
1353 proto.doMethod = function(attr, start, end) {
1356 if (attr == 'scroll') {
1358 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1359 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1363 val = superclass.doMethod.call(this, attr, start, end);
1368 proto.getAttribute = function(attr) {
1370 var el = this.getEl();
1372 if (attr == 'scroll') {
1373 val = [ el.scrollLeft, el.scrollTop ];
1375 val = superclass.getAttribute.call(this, attr);
1381 proto.setAttribute = function(attr, val, unit) {
1382 var el = this.getEl();
1384 if (attr == 'scroll') {
1385 el.scrollLeft = val[0];
1386 el.scrollTop = val[1];
1388 superclass.setAttribute.call(this, attr, val, unit);
1394 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.7.0", build: "1799"});