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) {
47 this.init(el, attributes, duration, method);
54 * Provides a readable name for the Anim instance.
58 toString: function() {
59 var el = this.getEl() || {};
60 var id = el.id || el.tagName;
61 return (this.constructor.NAME + ': ' + id);
64 patterns: { // cached for performance
65 noNegatives: /width|height|opacity|padding/i, // keep at zero or above
66 offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default
67 defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
68 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
72 * Returns the value computed by the animation's "method".
74 * @param {String} attr The name of the attribute.
75 * @param {Number} start The value this attribute should start from for this animation.
76 * @param {Number} end The value this attribute should end at for this animation.
77 * @return {Number} The Value to be applied to the attribute.
79 doMethod: function(attr, start, end) {
80 return this.method(this.currentFrame, start, end - start, this.totalFrames);
84 * Applies a value to an attribute.
85 * @method setAttribute
86 * @param {String} attr The name of the attribute.
87 * @param {Number} val The value to be applied to the attribute.
88 * @param {String} unit The unit ('px', '%', etc.) of the value.
90 setAttribute: function(attr, val, unit) {
91 if ( this.patterns.noNegatives.test(attr) ) {
92 val = (val > 0) ? val : 0;
95 Y.Dom.setStyle(this.getEl(), attr, val + unit);
99 * Returns current value of the attribute.
100 * @method getAttribute
101 * @param {String} attr The name of the attribute.
102 * @return {Number} val The current value of the attribute.
104 getAttribute: function(attr) {
105 var el = this.getEl();
106 var val = Y.Dom.getStyle(el, attr);
108 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
109 return parseFloat(val);
112 var a = this.patterns.offsetAttribute.exec(attr) || [];
113 var pos = !!( a[3] ); // top or left
114 var box = !!( a[2] ); // width or height
116 // use offsets for width/height and abs pos top/left
117 if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
118 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
119 } else { // default to zero for other 'auto'
127 * Returns the unit to use when none is supplied.
128 * @method getDefaultUnit
129 * @param {attr} attr The name of the attribute.
130 * @return {String} The default unit to be used.
132 getDefaultUnit: function(attr) {
133 if ( this.patterns.defaultUnit.test(attr) ) {
141 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
142 * @method setRuntimeAttribute
143 * @param {Object} attr The attribute object
146 setRuntimeAttribute: function(attr) {
149 var attributes = this.attributes;
151 this.runtimeAttributes[attr] = {};
153 var isset = function(prop) {
154 return (typeof prop !== 'undefined');
157 if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
158 return false; // note return; nothing to animate to
161 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
163 // To beats by, per SMIL 2.1 spec
164 if ( isset(attributes[attr]['to']) ) {
165 end = attributes[attr]['to'];
166 } else if ( isset(attributes[attr]['by']) ) {
167 if (start.constructor == Array) {
169 for (var i = 0, len = start.length; i < len; ++i) {
170 end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by"
173 end = start + attributes[attr]['by'] * 1;
177 this.runtimeAttributes[attr].start = start;
178 this.runtimeAttributes[attr].end = end;
180 // set units if needed
181 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
182 attributes[attr]['unit'] : this.getDefaultUnit(attr);
187 * Constructor for Anim instance.
189 * @param {String | HTMLElement} el Reference to the element that will be animated
190 * @param {Object} attributes The attribute(s) to be animated.
191 * Each attribute is an object with at minimum a "to" or "by" member defined.
192 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
193 * All attribute names use camelCase.
194 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
195 * @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)
197 init: function(el, attributes, duration, method) {
199 * Whether or not the animation is running.
200 * @property isAnimated
204 var isAnimated = false;
207 * A Date object that is created when the animation begins.
208 * @property startTime
212 var startTime = null;
215 * The number of frames this animation was able to execute.
216 * @property actualFrames
220 var actualFrames = 0;
223 * The element to be animated.
231 * The collection of attributes to be animated.
232 * Each attribute must have at least a "to" or "by" defined in order to animate.
233 * If "to" is supplied, the animation will end with the attribute at that value.
234 * If "by" is supplied, the animation will end at that value plus its starting value.
235 * If both are supplied, "to" is used, and "by" is ignored.
236 * 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).
237 * @property attributes
240 this.attributes = attributes || {};
243 * The length of the animation. Defaults to "1" (second).
247 this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
250 * The method that will provide values to the attribute(s) during the animation.
251 * Defaults to "YAHOO.util.Easing.easeNone".
255 this.method = method || Y.Easing.easeNone;
258 * Whether or not the duration should be treated as seconds.
260 * @property useSeconds
263 this.useSeconds = true; // default to seconds
266 * The location of the current animation on the timeline.
267 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
268 * @property currentFrame
271 this.currentFrame = 0;
274 * The total number of frames to be executed.
275 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
276 * @property totalFrames
279 this.totalFrames = Y.AnimMgr.fps;
282 * Changes the animated element
285 this.setEl = function(element) {
286 el = Y.Dom.get(element);
290 * Returns a reference to the animated element.
292 * @return {HTMLElement}
294 this.getEl = function() { return el; };
297 * Checks whether the element is currently animated.
299 * @return {Boolean} current value of isAnimated.
301 this.isAnimated = function() {
306 * Returns the animation start time.
307 * @method getStartTime
308 * @return {Date} current value of startTime.
310 this.getStartTime = function() {
314 this.runtimeAttributes = {};
319 * Starts the animation by registering it with the animation manager.
322 this.animate = function() {
323 if ( this.isAnimated() ) {
327 this.currentFrame = 0;
329 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
331 if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration
332 this.totalFrames = 1;
334 Y.AnimMgr.registerElement(this);
339 * Stops the animation. Normally called by AnimMgr when animation completes.
341 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
343 this.stop = function(finish) {
344 if (!this.isAnimated()) { // nothing to stop
349 this.currentFrame = this.totalFrames;
350 this._onTween.fire();
352 Y.AnimMgr.stop(this);
355 var onStart = function() {
358 this.runtimeAttributes = {};
359 for (var attr in this.attributes) {
360 this.setRuntimeAttribute(attr);
365 startTime = new Date();
369 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
373 var onTween = function() {
375 duration: new Date() - this.getStartTime(),
376 currentFrame: this.currentFrame
379 data.toString = function() {
381 'duration: ' + data.duration +
382 ', currentFrame: ' + data.currentFrame
386 this.onTween.fire(data);
388 var runtimeAttributes = this.runtimeAttributes;
390 for (var attr in runtimeAttributes) {
391 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
397 var onComplete = function() {
398 var actual_duration = (new Date() - startTime) / 1000 ;
401 duration: actual_duration,
402 frames: actualFrames,
403 fps: actualFrames / actual_duration
406 data.toString = function() {
408 'duration: ' + data.duration +
409 ', frames: ' + data.frames +
416 this.onComplete.fire(data);
420 * Custom event that fires after onStart, useful in subclassing
423 this._onStart = new Y.CustomEvent('_start', this, true);
426 * Custom event that fires when animation begins
427 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
430 this.onStart = new Y.CustomEvent('start', this);
433 * Custom event that fires between each frame
434 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
437 this.onTween = new Y.CustomEvent('tween', this);
440 * Custom event that fires after onTween
443 this._onTween = new Y.CustomEvent('_tween', this, true);
446 * Custom event that fires when animation ends
447 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
450 this.onComplete = new Y.CustomEvent('complete', this);
452 * Custom event that fires after onComplete
455 this._onComplete = new Y.CustomEvent('_complete', this, true);
457 this._onStart.subscribe(onStart);
458 this._onTween.subscribe(onTween);
459 this._onComplete.subscribe(onComplete);
466 * Handles animation queueing and threading.
467 * Used by Anim and subclasses.
469 * @namespace YAHOO.util
471 YAHOO.util.AnimMgr = new function() {
473 * Reference to the animation Interval.
481 * The current queue of registered animation objects.
489 * The number of active animations.
490 * @property tweenCount
497 * Base frame rate (frames per second).
498 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
506 * Interval delay in milliseconds, defaults to fastest possible.
514 * Adds an animation instance to the animation queue.
515 * All animation instances must be registered in order to animate.
516 * @method registerElement
517 * @param {object} tween The Anim instance to be be registered
519 this.registerElement = function(tween) {
520 queue[queue.length] = tween;
522 tween._onStart.fire();
527 * removes an animation instance from the animation queue.
528 * All animation instances must be registered in order to animate.
530 * @param {object} tween The Anim instance to be be registered
531 * @param {Int} index The index of the Anim instance
534 this.unRegister = function(tween, index) {
535 index = index || getIndex(tween);
536 if (!tween.isAnimated() || index == -1) {
540 tween._onComplete.fire();
541 queue.splice(index, 1);
544 if (tweenCount <= 0) {
552 * Starts the animation thread.
553 * Only one thread can run at a time.
556 this.start = function() {
557 if (thread === null) {
558 thread = setInterval(this.run, this.delay);
563 * Stops the animation thread or a specific animation instance.
565 * @param {object} tween A specific Anim instance to stop (optional)
566 * If no instance given, Manager stops thread and all animations.
568 this.stop = function(tween) {
570 clearInterval(thread);
572 for (var i = 0, len = queue.length; i < len; ++i) {
573 this.unRegister(queue[0], 0);
581 this.unRegister(tween);
586 * Called per Interval to handle each animation frame.
589 this.run = function() {
590 for (var i = 0, len = queue.length; i < len; ++i) {
591 var tween = queue[i];
592 if ( !tween || !tween.isAnimated() ) { continue; }
594 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
596 tween.currentFrame += 1;
598 if (tween.useSeconds) {
601 tween._onTween.fire();
603 else { YAHOO.util.AnimMgr.stop(tween, i); }
607 var getIndex = function(anim) {
608 for (var i = 0, len = queue.length; i < len; ++i) {
609 if (queue[i] == anim) {
610 return i; // note return;
617 * On the fly frame correction to keep animation on time.
618 * @method correctFrame
620 * @param {Object} tween The Anim instance being corrected.
622 var correctFrame = function(tween) {
623 var frames = tween.totalFrames;
624 var frame = tween.currentFrame;
625 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
626 var elapsed = (new Date() - tween.getStartTime());
629 if (elapsed < tween.duration * 1000) { // check if falling behind
630 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
631 } else { // went over duration, so jump to end
632 tweak = frames - (frame + 1);
634 if (tweak > 0 && isFinite(tweak)) { // adjust if needed
635 if (tween.currentFrame + tweak >= frames) {// dont go past last frame
636 tweak = frames - (frame + 1);
639 tween.currentFrame += tweak;
644 * Used to calculate Bezier splines for any number of control points.
646 * @namespace YAHOO.util
649 YAHOO.util.Bezier = new function() {
651 * Get the current position of the animated element based on t.
652 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
653 * At least 2 points are required (start and end).
654 * First point is start. Last point is end.
655 * Additional control points are optional.
656 * @method getPosition
657 * @param {Array} points An array containing Bezier points
658 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
659 * @return {Array} An array containing int x and y member data
661 this.getPosition = function(points, t) {
662 var n = points.length;
665 for (var i = 0; i < n; ++i){
666 tmp[i] = [points[i][0], points[i][1]]; // save input
669 for (var j = 1; j < n; ++j) {
670 for (i = 0; i < n - j; ++i) {
671 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
672 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
676 return [ tmp[0][0], tmp[0][1] ];
682 * Anim subclass for color transitions.
683 * <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,
684 * [255,255,255], or rgb(255,255,255)</p>
686 * @namespace YAHOO.util
687 * @requires YAHOO.util.Anim
688 * @requires YAHOO.util.AnimMgr
689 * @requires YAHOO.util.Easing
690 * @requires YAHOO.util.Bezier
691 * @requires YAHOO.util.Dom
692 * @requires YAHOO.util.Event
694 * @extends YAHOO.util.Anim
695 * @param {HTMLElement | String} el Reference to the element that will be animated
696 * @param {Object} attributes The attribute(s) to be animated.
697 * Each attribute is an object with at minimum a "to" or "by" member defined.
698 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
699 * All attribute names use camelCase.
700 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
701 * @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)
703 var ColorAnim = function(el, attributes, duration, method) {
704 ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
707 ColorAnim.NAME = 'ColorAnim';
709 ColorAnim.DEFAULT_BGCOLOR = '#fff';
712 YAHOO.extend(ColorAnim, Y.Anim);
714 var superclass = ColorAnim.superclass;
715 var proto = ColorAnim.prototype;
717 proto.patterns.color = /color$/i;
718 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
719 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
720 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
721 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
724 * Attempts to parse the given string and return a 3-tuple.
726 * @param {String} s The string to parse.
727 * @return {Array} The 3-tuple of rgb values.
729 proto.parseColor = function(s) {
730 if (s.length == 3) { return s; }
732 var c = this.patterns.hex.exec(s);
733 if (c && c.length == 4) {
734 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
737 c = this.patterns.rgb.exec(s);
738 if (c && c.length == 4) {
739 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
742 c = this.patterns.hex3.exec(s);
743 if (c && c.length == 4) {
744 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
750 proto.getAttribute = function(attr) {
751 var el = this.getEl();
752 if (this.patterns.color.test(attr) ) {
753 var val = YAHOO.util.Dom.getStyle(el, attr);
756 if (this.patterns.transparent.test(val)) { // bgcolor default
757 var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
758 return !that.patterns.transparent.test(val);
762 val = Y.Dom.getStyle(parent, attr);
764 val = ColorAnim.DEFAULT_BGCOLOR;
768 val = superclass.getAttribute.call(this, attr);
774 proto.doMethod = function(attr, start, end) {
777 if ( this.patterns.color.test(attr) ) {
779 for (var i = 0, len = start.length; i < len; ++i) {
780 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
783 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
786 val = superclass.doMethod.call(this, attr, start, end);
792 proto.setRuntimeAttribute = function(attr) {
793 superclass.setRuntimeAttribute.call(this, attr);
795 if ( this.patterns.color.test(attr) ) {
796 var attributes = this.attributes;
797 var start = this.parseColor(this.runtimeAttributes[attr].start);
798 var end = this.parseColor(this.runtimeAttributes[attr].end);
799 // fix colors if going "by"
800 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
801 end = this.parseColor(attributes[attr].by);
803 for (var i = 0, len = start.length; i < len; ++i) {
804 end[i] = start[i] + end[i];
808 this.runtimeAttributes[attr].start = start;
809 this.runtimeAttributes[attr].end = end;
813 Y.ColorAnim = ColorAnim;
816 TERMS OF USE - EASING EQUATIONS
817 Open source under the BSD License.
818 Copyright 2001 Robert Penner All rights reserved.
820 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
822 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
823 * 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.
824 * 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.
826 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.
830 * Singleton that determines how an animation proceeds from start to end.
832 * @namespace YAHOO.util
835 YAHOO.util.Easing = {
838 * Uniform speed between points.
840 * @param {Number} t Time value used to compute current value
841 * @param {Number} b Starting value
842 * @param {Number} c Delta between start and end values
843 * @param {Number} d Total length of animation
844 * @return {Number} The computed value for the current animation frame
846 easeNone: function (t, b, c, d) {
851 * Begins slowly and accelerates towards end.
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 easeIn: function (t, b, c, d) {
860 return c*(t/=d)*t + b;
864 * Begins quickly and decelerates 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 easeOut: function (t, b, c, d) {
873 return -c *(t/=d)*(t-2) + b;
877 * Begins slowly 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 easeBoth: function (t, b, c, d) {
890 return -c/2 * ((--t)*(t-2) - 1) + b;
894 * Begins slowly and accelerates towards end.
895 * @method easeInStrong
896 * @param {Number} t Time value used to compute current value
897 * @param {Number} b Starting value
898 * @param {Number} c Delta between start and end values
899 * @param {Number} d Total length of animation
900 * @return {Number} The computed value for the current animation frame
902 easeInStrong: function (t, b, c, d) {
903 return c*(t/=d)*t*t*t + b;
907 * Begins quickly and decelerates towards end.
908 * @method easeOutStrong
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 easeOutStrong: function (t, b, c, d) {
916 return -c * ((t=t/d-1)*t*t*t - 1) + b;
920 * Begins slowly and decelerates towards end.
921 * @method easeBothStrong
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 easeBothStrong: function (t, b, c, d) {
930 return c/2*t*t*t*t + b;
933 return -c/2 * ((t-=2)*t*t*t - 2) + b;
937 * Snap in elastic effect.
939 * @param {Number} t Time value used to compute current value
940 * @param {Number} b Starting value
941 * @param {Number} c Delta between start and end values
942 * @param {Number} d Total length of animation
943 * @param {Number} a Amplitude (optional)
944 * @param {Number} p Period (optional)
945 * @return {Number} The computed value for the current animation frame
948 elasticIn: function (t, b, c, d, a, p) {
952 if ( (t /= d) == 1 ) {
959 if (!a || a < Math.abs(c)) {
964 var s = p/(2*Math.PI) * Math.asin (c/a);
967 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
971 * Snap out elastic effect.
973 * @param {Number} t Time value used to compute current value
974 * @param {Number} b Starting value
975 * @param {Number} c Delta between start and end values
976 * @param {Number} d Total length of animation
977 * @param {Number} a Amplitude (optional)
978 * @param {Number} p Period (optional)
979 * @return {Number} The computed value for the current animation frame
981 elasticOut: function (t, b, c, d, a, p) {
985 if ( (t /= d) == 1 ) {
992 if (!a || a < Math.abs(c)) {
997 var s = p/(2*Math.PI) * Math.asin (c/a);
1000 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1004 * Snap both elastic effect.
1005 * @method elasticBoth
1006 * @param {Number} t Time value used to compute current value
1007 * @param {Number} b Starting value
1008 * @param {Number} c Delta between start and end values
1009 * @param {Number} d Total length of animation
1010 * @param {Number} a Amplitude (optional)
1011 * @param {Number} p Period (optional)
1012 * @return {Number} The computed value for the current animation frame
1014 elasticBoth: function (t, b, c, d, a, p) {
1019 if ( (t /= d/2) == 2 ) {
1027 if ( !a || a < Math.abs(c) ) {
1032 var s = p/(2*Math.PI) * Math.asin (c/a);
1036 return -.5*(a*Math.pow(2,10*(t-=1)) *
1037 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1039 return a*Math.pow(2,-10*(t-=1)) *
1040 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1045 * Backtracks slightly, then reverses direction and moves to end.
1047 * @param {Number} t Time value used to compute current value
1048 * @param {Number} b Starting value
1049 * @param {Number} c Delta between start and end values
1050 * @param {Number} d Total length of animation
1051 * @param {Number} s Overshoot (optional)
1052 * @return {Number} The computed value for the current animation frame
1054 backIn: function (t, b, c, d, s) {
1055 if (typeof s == 'undefined') {
1058 return c*(t/=d)*t*((s+1)*t - s) + b;
1062 * Overshoots end, then reverses and comes back to end.
1064 * @param {Number} t Time value used to compute current value
1065 * @param {Number} b Starting value
1066 * @param {Number} c Delta between start and end values
1067 * @param {Number} d Total length of animation
1068 * @param {Number} s Overshoot (optional)
1069 * @return {Number} The computed value for the current animation frame
1071 backOut: function (t, b, c, d, s) {
1072 if (typeof s == 'undefined') {
1075 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1079 * Backtracks slightly, then reverses direction, overshoots end,
1080 * then reverses and comes back to end.
1082 * @param {Number} t Time value used to compute current value
1083 * @param {Number} b Starting value
1084 * @param {Number} c Delta between start and end values
1085 * @param {Number} d Total length of animation
1086 * @param {Number} s Overshoot (optional)
1087 * @return {Number} The computed value for the current animation frame
1089 backBoth: function (t, b, c, d, s) {
1090 if (typeof s == 'undefined') {
1094 if ((t /= d/2 ) < 1) {
1095 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1097 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1101 * Bounce off of start.
1103 * @param {Number} t Time value used to compute current value
1104 * @param {Number} b Starting value
1105 * @param {Number} c Delta between start and end values
1106 * @param {Number} d Total length of animation
1107 * @return {Number} The computed value for the current animation frame
1109 bounceIn: function (t, b, c, d) {
1110 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
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 bounceOut: function (t, b, c, d) {
1123 if ((t/=d) < (1/2.75)) {
1124 return c*(7.5625*t*t) + b;
1125 } else if (t < (2/2.75)) {
1126 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1127 } else if (t < (2.5/2.75)) {
1128 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1130 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1134 * Bounces off start and end.
1135 * @method bounceBoth
1136 * @param {Number} t Time value used to compute current value
1137 * @param {Number} b Starting value
1138 * @param {Number} c Delta between start and end values
1139 * @param {Number} d Total length of animation
1140 * @return {Number} The computed value for the current animation frame
1142 bounceBoth: function (t, b, c, d) {
1144 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1146 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1152 * Anim subclass for moving elements along a path defined by the "points"
1153 * member of "attributes". All "points" are arrays with x, y coordinates.
1154 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1156 * @namespace YAHOO.util
1157 * @requires YAHOO.util.Anim
1158 * @requires YAHOO.util.AnimMgr
1159 * @requires YAHOO.util.Easing
1160 * @requires YAHOO.util.Bezier
1161 * @requires YAHOO.util.Dom
1162 * @requires YAHOO.util.Event
1163 * @requires YAHOO.util.CustomEvent
1165 * @extends YAHOO.util.ColorAnim
1166 * @param {String | HTMLElement} el Reference to the element that will be animated
1167 * @param {Object} attributes The attribute(s) to be animated.
1168 * Each attribute is an object with at minimum a "to" or "by" member defined.
1169 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1170 * All attribute names use camelCase.
1171 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1172 * @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)
1174 var Motion = function(el, attributes, duration, method) {
1175 if (el) { // dont break existing subclasses not using YAHOO.extend
1176 Motion.superclass.constructor.call(this, el, attributes, duration, method);
1181 Motion.NAME = 'Motion';
1185 YAHOO.extend(Motion, Y.ColorAnim);
1187 var superclass = Motion.superclass;
1188 var proto = Motion.prototype;
1190 proto.patterns.points = /^points$/i;
1192 proto.setAttribute = function(attr, val, unit) {
1193 if ( this.patterns.points.test(attr) ) {
1194 unit = unit || 'px';
1195 superclass.setAttribute.call(this, 'left', val[0], unit);
1196 superclass.setAttribute.call(this, 'top', val[1], unit);
1198 superclass.setAttribute.call(this, attr, val, unit);
1202 proto.getAttribute = function(attr) {
1203 if ( this.patterns.points.test(attr) ) {
1205 superclass.getAttribute.call(this, 'left'),
1206 superclass.getAttribute.call(this, 'top')
1209 val = superclass.getAttribute.call(this, attr);
1215 proto.doMethod = function(attr, start, end) {
1218 if ( this.patterns.points.test(attr) ) {
1219 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1220 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1222 val = superclass.doMethod.call(this, attr, start, end);
1227 proto.setRuntimeAttribute = function(attr) {
1228 if ( this.patterns.points.test(attr) ) {
1229 var el = this.getEl();
1230 var attributes = this.attributes;
1232 var control = attributes['points']['control'] || [];
1236 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1237 control = [control];
1238 } else { // break reference to attributes.points.control
1240 for (i = 0, len = control.length; i< len; ++i) {
1241 tmp[i] = control[i];
1246 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1247 Y.Dom.setStyle(el, 'position', 'relative');
1250 if ( isset(attributes['points']['from']) ) {
1251 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1253 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1255 start = this.getAttribute('points'); // get actual top & left
1257 // TO beats BY, per SMIL 2.1 spec
1258 if ( isset(attributes['points']['to']) ) {
1259 end = translateValues.call(this, attributes['points']['to'], start);
1261 var pageXY = Y.Dom.getXY(this.getEl());
1262 for (i = 0, len = control.length; i < len; ++i) {
1263 control[i] = translateValues.call(this, control[i], start);
1267 } else if ( isset(attributes['points']['by']) ) {
1268 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1270 for (i = 0, len = control.length; i < len; ++i) {
1271 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1275 this.runtimeAttributes[attr] = [start];
1277 if (control.length > 0) {
1278 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1281 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1284 superclass.setRuntimeAttribute.call(this, attr);
1288 var translateValues = function(val, start) {
1289 var pageXY = Y.Dom.getXY(this.getEl());
1290 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1295 var isset = function(prop) {
1296 return (typeof prop !== 'undefined');
1303 * Anim subclass for scrolling elements to a position defined by the "scroll"
1304 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1305 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1307 * @namespace YAHOO.util
1308 * @requires YAHOO.util.Anim
1309 * @requires YAHOO.util.AnimMgr
1310 * @requires YAHOO.util.Easing
1311 * @requires YAHOO.util.Bezier
1312 * @requires YAHOO.util.Dom
1313 * @requires YAHOO.util.Event
1314 * @requires YAHOO.util.CustomEvent
1315 * @extends YAHOO.util.ColorAnim
1317 * @param {String or HTMLElement} el Reference to the element that will be animated
1318 * @param {Object} attributes The attribute(s) to be animated.
1319 * Each attribute is an object with at minimum a "to" or "by" member defined.
1320 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1321 * All attribute names use camelCase.
1322 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1323 * @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)
1325 var Scroll = function(el, attributes, duration, method) {
1326 if (el) { // dont break existing subclasses not using YAHOO.extend
1327 Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1331 Scroll.NAME = 'Scroll';
1335 YAHOO.extend(Scroll, Y.ColorAnim);
1337 var superclass = Scroll.superclass;
1338 var proto = Scroll.prototype;
1340 proto.doMethod = function(attr, start, end) {
1343 if (attr == 'scroll') {
1345 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1346 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1350 val = superclass.doMethod.call(this, attr, start, end);
1355 proto.getAttribute = function(attr) {
1357 var el = this.getEl();
1359 if (attr == 'scroll') {
1360 val = [ el.scrollLeft, el.scrollTop ];
1362 val = superclass.getAttribute.call(this, attr);
1368 proto.setAttribute = function(attr, val, unit) {
1369 var el = this.getEl();
1371 if (attr == 'scroll') {
1372 el.scrollLeft = val[0];
1373 el.scrollTop = val[1];
1375 superclass.setAttribute.call(this, attr, val, unit);
1381 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.6.0", build: "1321"});