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) {
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 var el = this.getEl();
92 if ( this.patterns.noNegatives.test(attr) ) {
93 val = (val > 0) ? val : 0;
96 if (attr in el && !('style' in el && attr in el.style)) {
99 Y.Dom.setStyle(el, attr, val + unit);
104 * Returns current value of the attribute.
105 * @method getAttribute
106 * @param {String} attr The name of the attribute.
107 * @return {Number} val The current value of the attribute.
109 getAttribute: function(attr) {
110 var el = this.getEl();
111 var val = Y.Dom.getStyle(el, attr);
113 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
114 return parseFloat(val);
117 var a = this.patterns.offsetAttribute.exec(attr) || [];
118 var pos = !!( a[3] ); // top or left
119 var box = !!( a[2] ); // width or height
122 // use offsets for width/height and abs pos top/left
123 if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
124 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
125 } else { // default to zero for other 'auto'
128 } else if (attr in el) {
136 * Returns the unit to use when none is supplied.
137 * @method getDefaultUnit
138 * @param {attr} attr The name of the attribute.
139 * @return {String} The default unit to be used.
141 getDefaultUnit: function(attr) {
142 if ( this.patterns.defaultUnit.test(attr) ) {
150 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
151 * @method setRuntimeAttribute
152 * @param {Object} attr The attribute object
155 setRuntimeAttribute: function(attr) {
158 var attributes = this.attributes;
160 this.runtimeAttributes[attr] = {};
162 var isset = function(prop) {
163 return (typeof prop !== 'undefined');
166 if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
167 return false; // note return; nothing to animate to
170 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
172 // To beats by, per SMIL 2.1 spec
173 if ( isset(attributes[attr]['to']) ) {
174 end = attributes[attr]['to'];
175 } else if ( isset(attributes[attr]['by']) ) {
176 if (start.constructor == Array) {
178 for (var i = 0, len = start.length; i < len; ++i) {
179 end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by"
182 end = start + attributes[attr]['by'] * 1;
186 this.runtimeAttributes[attr].start = start;
187 this.runtimeAttributes[attr].end = end;
189 // set units if needed
190 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
191 attributes[attr]['unit'] : this.getDefaultUnit(attr);
196 * Constructor for Anim instance.
198 * @param {String | HTMLElement} el Reference to the element that will be animated
199 * @param {Object} attributes The attribute(s) to be animated.
200 * Each attribute is an object with at minimum a "to" or "by" member defined.
201 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
202 * All attribute names use camelCase.
203 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
204 * @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)
206 init: function(el, attributes, duration, method) {
208 * Whether or not the animation is running.
209 * @property isAnimated
213 var isAnimated = false;
216 * A Date object that is created when the animation begins.
217 * @property startTime
221 var startTime = null;
224 * The number of frames this animation was able to execute.
225 * @property actualFrames
229 var actualFrames = 0;
232 * The element to be animated.
240 * The collection of attributes to be animated.
241 * Each attribute must have at least a "to" or "by" defined in order to animate.
242 * If "to" is supplied, the animation will end with the attribute at that value.
243 * If "by" is supplied, the animation will end at that value plus its starting value.
244 * If both are supplied, "to" is used, and "by" is ignored.
245 * 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).
246 * @property attributes
249 this.attributes = attributes || {};
252 * The length of the animation. Defaults to "1" (second).
256 this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
259 * The method that will provide values to the attribute(s) during the animation.
260 * Defaults to "YAHOO.util.Easing.easeNone".
264 this.method = method || Y.Easing.easeNone;
267 * Whether or not the duration should be treated as seconds.
269 * @property useSeconds
272 this.useSeconds = true; // default to seconds
275 * The location of the current animation on the timeline.
276 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
277 * @property currentFrame
280 this.currentFrame = 0;
283 * The total number of frames to be executed.
284 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
285 * @property totalFrames
288 this.totalFrames = Y.AnimMgr.fps;
291 * Changes the animated element
294 this.setEl = function(element) {
295 el = Y.Dom.get(element);
299 * Returns a reference to the animated element.
301 * @return {HTMLElement}
303 this.getEl = function() { return el; };
306 * Checks whether the element is currently animated.
308 * @return {Boolean} current value of isAnimated.
310 this.isAnimated = function() {
315 * Returns the animation start time.
316 * @method getStartTime
317 * @return {Date} current value of startTime.
319 this.getStartTime = function() {
323 this.runtimeAttributes = {};
328 * Starts the animation by registering it with the animation manager.
331 this.animate = function() {
332 if ( this.isAnimated() ) {
336 this.currentFrame = 0;
338 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
340 if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration
341 this.totalFrames = 1;
343 Y.AnimMgr.registerElement(this);
348 * Stops the animation. Normally called by AnimMgr when animation completes.
350 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
352 this.stop = function(finish) {
353 if (!this.isAnimated()) { // nothing to stop
358 this.currentFrame = this.totalFrames;
359 this._onTween.fire();
361 Y.AnimMgr.stop(this);
364 var onStart = function() {
367 this.runtimeAttributes = {};
368 for (var attr in this.attributes) {
369 this.setRuntimeAttribute(attr);
374 startTime = new Date();
378 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
382 var onTween = function() {
384 duration: new Date() - this.getStartTime(),
385 currentFrame: this.currentFrame
388 data.toString = function() {
390 'duration: ' + data.duration +
391 ', currentFrame: ' + data.currentFrame
395 this.onTween.fire(data);
397 var runtimeAttributes = this.runtimeAttributes;
399 for (var attr in runtimeAttributes) {
400 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
406 var onComplete = function() {
407 var actual_duration = (new Date() - startTime) / 1000 ;
410 duration: actual_duration,
411 frames: actualFrames,
412 fps: actualFrames / actual_duration
415 data.toString = function() {
417 'duration: ' + data.duration +
418 ', frames: ' + data.frames +
425 this.onComplete.fire(data);
429 * Custom event that fires after onStart, useful in subclassing
432 this._onStart = new Y.CustomEvent('_start', this, true);
435 * Custom event that fires when animation begins
436 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
439 this.onStart = new Y.CustomEvent('start', this);
442 * Custom event that fires between each frame
443 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
446 this.onTween = new Y.CustomEvent('tween', this);
449 * Custom event that fires after onTween
452 this._onTween = new Y.CustomEvent('_tween', this, true);
455 * Custom event that fires when animation ends
456 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
459 this.onComplete = new Y.CustomEvent('complete', this);
461 * Custom event that fires after onComplete
464 this._onComplete = new Y.CustomEvent('_complete', this, true);
466 this._onStart.subscribe(onStart);
467 this._onTween.subscribe(onTween);
468 this._onComplete.subscribe(onComplete);
475 * Handles animation queueing and threading.
476 * Used by Anim and subclasses.
478 * @namespace YAHOO.util
480 YAHOO.util.AnimMgr = new function() {
482 * Reference to the animation Interval.
490 * The current queue of registered animation objects.
498 * The number of active animations.
499 * @property tweenCount
506 * Base frame rate (frames per second).
507 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
515 * Interval delay in milliseconds, defaults to fastest possible.
523 * Adds an animation instance to the animation queue.
524 * All animation instances must be registered in order to animate.
525 * @method registerElement
526 * @param {object} tween The Anim instance to be be registered
528 this.registerElement = function(tween) {
529 queue[queue.length] = tween;
531 tween._onStart.fire();
536 * removes an animation instance from the animation queue.
537 * All animation instances must be registered in order to animate.
539 * @param {object} tween The Anim instance to be be registered
540 * @param {Int} index The index of the Anim instance
543 this.unRegister = function(tween, index) {
544 index = index || getIndex(tween);
545 if (!tween.isAnimated() || index === -1) {
549 tween._onComplete.fire();
550 queue.splice(index, 1);
553 if (tweenCount <= 0) {
561 * Starts the animation thread.
562 * Only one thread can run at a time.
565 this.start = function() {
566 if (thread === null) {
567 thread = setInterval(this.run, this.delay);
572 * Stops the animation thread or a specific animation instance.
574 * @param {object} tween A specific Anim instance to stop (optional)
575 * If no instance given, Manager stops thread and all animations.
577 this.stop = function(tween) {
579 clearInterval(thread);
581 for (var i = 0, len = queue.length; i < len; ++i) {
582 this.unRegister(queue[0], 0);
590 this.unRegister(tween);
595 * Called per Interval to handle each animation frame.
598 this.run = function() {
599 for (var i = 0, len = queue.length; i < len; ++i) {
600 var tween = queue[i];
601 if ( !tween || !tween.isAnimated() ) { continue; }
603 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
605 tween.currentFrame += 1;
607 if (tween.useSeconds) {
610 tween._onTween.fire();
612 else { YAHOO.util.AnimMgr.stop(tween, i); }
616 var getIndex = function(anim) {
617 for (var i = 0, len = queue.length; i < len; ++i) {
618 if (queue[i] === anim) {
619 return i; // note return;
626 * On the fly frame correction to keep animation on time.
627 * @method correctFrame
629 * @param {Object} tween The Anim instance being corrected.
631 var correctFrame = function(tween) {
632 var frames = tween.totalFrames;
633 var frame = tween.currentFrame;
634 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
635 var elapsed = (new Date() - tween.getStartTime());
638 if (elapsed < tween.duration * 1000) { // check if falling behind
639 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
640 } else { // went over duration, so jump to end
641 tweak = frames - (frame + 1);
643 if (tweak > 0 && isFinite(tweak)) { // adjust if needed
644 if (tween.currentFrame + tweak >= frames) {// dont go past last frame
645 tweak = frames - (frame + 1);
648 tween.currentFrame += tweak;
652 this._getIndex = getIndex;
655 * Used to calculate Bezier splines for any number of control points.
657 * @namespace YAHOO.util
660 YAHOO.util.Bezier = new function() {
662 * Get the current position of the animated element based on t.
663 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
664 * At least 2 points are required (start and end).
665 * First point is start. Last point is end.
666 * Additional control points are optional.
667 * @method getPosition
668 * @param {Array} points An array containing Bezier points
669 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
670 * @return {Array} An array containing int x and y member data
672 this.getPosition = function(points, t) {
673 var n = points.length;
676 for (var i = 0; i < n; ++i){
677 tmp[i] = [points[i][0], points[i][1]]; // save input
680 for (var j = 1; j < n; ++j) {
681 for (i = 0; i < n - j; ++i) {
682 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
683 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
687 return [ tmp[0][0], tmp[0][1] ];
693 * Anim subclass for color transitions.
694 * <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,
695 * [255,255,255], or rgb(255,255,255)</p>
697 * @namespace YAHOO.util
698 * @requires YAHOO.util.Anim
699 * @requires YAHOO.util.AnimMgr
700 * @requires YAHOO.util.Easing
701 * @requires YAHOO.util.Bezier
702 * @requires YAHOO.util.Dom
703 * @requires YAHOO.util.Event
705 * @extends YAHOO.util.Anim
706 * @param {HTMLElement | String} el Reference to the element that will be animated
707 * @param {Object} attributes The attribute(s) to be animated.
708 * Each attribute is an object with at minimum a "to" or "by" member defined.
709 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
710 * All attribute names use camelCase.
711 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
712 * @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)
714 var ColorAnim = function(el, attributes, duration, method) {
715 ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
718 ColorAnim.NAME = 'ColorAnim';
720 ColorAnim.DEFAULT_BGCOLOR = '#fff';
723 YAHOO.extend(ColorAnim, Y.Anim);
725 var superclass = ColorAnim.superclass;
726 var proto = ColorAnim.prototype;
728 proto.patterns.color = /color$/i;
729 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
730 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
731 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
732 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
735 * Attempts to parse the given string and return a 3-tuple.
737 * @param {String} s The string to parse.
738 * @return {Array} The 3-tuple of rgb values.
740 proto.parseColor = function(s) {
741 if (s.length == 3) { return s; }
743 var c = this.patterns.hex.exec(s);
744 if (c && c.length == 4) {
745 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
748 c = this.patterns.rgb.exec(s);
749 if (c && c.length == 4) {
750 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
753 c = this.patterns.hex3.exec(s);
754 if (c && c.length == 4) {
755 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
761 proto.getAttribute = function(attr) {
762 var el = this.getEl();
763 if (this.patterns.color.test(attr) ) {
764 var val = YAHOO.util.Dom.getStyle(el, attr);
767 if (this.patterns.transparent.test(val)) { // bgcolor default
768 var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
769 return !that.patterns.transparent.test(val);
773 val = Y.Dom.getStyle(parent, attr);
775 val = ColorAnim.DEFAULT_BGCOLOR;
779 val = superclass.getAttribute.call(this, attr);
785 proto.doMethod = function(attr, start, end) {
788 if ( this.patterns.color.test(attr) ) {
790 for (var i = 0, len = start.length; i < len; ++i) {
791 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
794 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
797 val = superclass.doMethod.call(this, attr, start, end);
803 proto.setRuntimeAttribute = function(attr) {
804 superclass.setRuntimeAttribute.call(this, attr);
806 if ( this.patterns.color.test(attr) ) {
807 var attributes = this.attributes;
808 var start = this.parseColor(this.runtimeAttributes[attr].start);
809 var end = this.parseColor(this.runtimeAttributes[attr].end);
810 // fix colors if going "by"
811 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
812 end = this.parseColor(attributes[attr].by);
814 for (var i = 0, len = start.length; i < len; ++i) {
815 end[i] = start[i] + end[i];
819 this.runtimeAttributes[attr].start = start;
820 this.runtimeAttributes[attr].end = end;
824 Y.ColorAnim = ColorAnim;
827 TERMS OF USE - EASING EQUATIONS
828 Open source under the BSD License.
829 Copyright 2001 Robert Penner All rights reserved.
831 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
833 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
834 * 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.
835 * 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.
837 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.
841 * Singleton that determines how an animation proceeds from start to end.
843 * @namespace YAHOO.util
846 YAHOO.util.Easing = {
849 * Uniform speed between points.
851 * @param {Number} t Time value used to compute current value
852 * @param {Number} b Starting value
853 * @param {Number} c Delta between start and end values
854 * @param {Number} d Total length of animation
855 * @return {Number} The computed value for the current animation frame
857 easeNone: function (t, b, c, d) {
862 * Begins slowly and accelerates towards end.
864 * @param {Number} t Time value used to compute current value
865 * @param {Number} b Starting value
866 * @param {Number} c Delta between start and end values
867 * @param {Number} d Total length of animation
868 * @return {Number} The computed value for the current animation frame
870 easeIn: function (t, b, c, d) {
871 return c*(t/=d)*t + b;
875 * Begins quickly and decelerates towards end.
877 * @param {Number} t Time value used to compute current value
878 * @param {Number} b Starting value
879 * @param {Number} c Delta between start and end values
880 * @param {Number} d Total length of animation
881 * @return {Number} The computed value for the current animation frame
883 easeOut: function (t, b, c, d) {
884 return -c *(t/=d)*(t-2) + b;
888 * Begins slowly and decelerates towards end.
890 * @param {Number} t Time value used to compute current value
891 * @param {Number} b Starting value
892 * @param {Number} c Delta between start and end values
893 * @param {Number} d Total length of animation
894 * @return {Number} The computed value for the current animation frame
896 easeBoth: function (t, b, c, d) {
901 return -c/2 * ((--t)*(t-2) - 1) + b;
905 * Begins slowly and accelerates towards end.
906 * @method easeInStrong
907 * @param {Number} t Time value used to compute current value
908 * @param {Number} b Starting value
909 * @param {Number} c Delta between start and end values
910 * @param {Number} d Total length of animation
911 * @return {Number} The computed value for the current animation frame
913 easeInStrong: function (t, b, c, d) {
914 return c*(t/=d)*t*t*t + b;
918 * Begins quickly and decelerates towards end.
919 * @method easeOutStrong
920 * @param {Number} t Time value used to compute current value
921 * @param {Number} b Starting value
922 * @param {Number} c Delta between start and end values
923 * @param {Number} d Total length of animation
924 * @return {Number} The computed value for the current animation frame
926 easeOutStrong: function (t, b, c, d) {
927 return -c * ((t=t/d-1)*t*t*t - 1) + b;
931 * Begins slowly and decelerates towards end.
932 * @method easeBothStrong
933 * @param {Number} t Time value used to compute current value
934 * @param {Number} b Starting value
935 * @param {Number} c Delta between start and end values
936 * @param {Number} d Total length of animation
937 * @return {Number} The computed value for the current animation frame
939 easeBothStrong: function (t, b, c, d) {
941 return c/2*t*t*t*t + b;
944 return -c/2 * ((t-=2)*t*t*t - 2) + b;
948 * Snap in elastic effect.
950 * @param {Number} t Time value used to compute current value
951 * @param {Number} b Starting value
952 * @param {Number} c Delta between start and end values
953 * @param {Number} d Total length of animation
954 * @param {Number} a Amplitude (optional)
955 * @param {Number} p Period (optional)
956 * @return {Number} The computed value for the current animation frame
959 elasticIn: function (t, b, c, d, a, p) {
963 if ( (t /= d) == 1 ) {
970 if (!a || a < Math.abs(c)) {
975 var s = p/(2*Math.PI) * Math.asin (c/a);
978 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
982 * Snap out elastic effect.
984 * @param {Number} t Time value used to compute current value
985 * @param {Number} b Starting value
986 * @param {Number} c Delta between start and end values
987 * @param {Number} d Total length of animation
988 * @param {Number} a Amplitude (optional)
989 * @param {Number} p Period (optional)
990 * @return {Number} The computed value for the current animation frame
992 elasticOut: function (t, b, c, d, a, p) {
996 if ( (t /= d) == 1 ) {
1003 if (!a || a < Math.abs(c)) {
1008 var s = p/(2*Math.PI) * Math.asin (c/a);
1011 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1015 * Snap both elastic effect.
1016 * @method elasticBoth
1017 * @param {Number} t Time value used to compute current value
1018 * @param {Number} b Starting value
1019 * @param {Number} c Delta between start and end values
1020 * @param {Number} d Total length of animation
1021 * @param {Number} a Amplitude (optional)
1022 * @param {Number} p Period (optional)
1023 * @return {Number} The computed value for the current animation frame
1025 elasticBoth: function (t, b, c, d, a, p) {
1030 if ( (t /= d/2) == 2 ) {
1038 if ( !a || a < Math.abs(c) ) {
1043 var s = p/(2*Math.PI) * Math.asin (c/a);
1047 return -.5*(a*Math.pow(2,10*(t-=1)) *
1048 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1050 return a*Math.pow(2,-10*(t-=1)) *
1051 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1056 * Backtracks slightly, then reverses direction and moves to end.
1058 * @param {Number} t Time value used to compute current value
1059 * @param {Number} b Starting value
1060 * @param {Number} c Delta between start and end values
1061 * @param {Number} d Total length of animation
1062 * @param {Number} s Overshoot (optional)
1063 * @return {Number} The computed value for the current animation frame
1065 backIn: function (t, b, c, d, s) {
1066 if (typeof s == 'undefined') {
1069 return c*(t/=d)*t*((s+1)*t - s) + b;
1073 * Overshoots end, then reverses and comes back to end.
1075 * @param {Number} t Time value used to compute current value
1076 * @param {Number} b Starting value
1077 * @param {Number} c Delta between start and end values
1078 * @param {Number} d Total length of animation
1079 * @param {Number} s Overshoot (optional)
1080 * @return {Number} The computed value for the current animation frame
1082 backOut: function (t, b, c, d, s) {
1083 if (typeof s == 'undefined') {
1086 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1090 * Backtracks slightly, then reverses direction, overshoots end,
1091 * then reverses and comes back to end.
1093 * @param {Number} t Time value used to compute current value
1094 * @param {Number} b Starting value
1095 * @param {Number} c Delta between start and end values
1096 * @param {Number} d Total length of animation
1097 * @param {Number} s Overshoot (optional)
1098 * @return {Number} The computed value for the current animation frame
1100 backBoth: function (t, b, c, d, s) {
1101 if (typeof s == 'undefined') {
1105 if ((t /= d/2 ) < 1) {
1106 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1108 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1112 * Bounce off of start.
1114 * @param {Number} t Time value used to compute current value
1115 * @param {Number} b Starting value
1116 * @param {Number} c Delta between start and end values
1117 * @param {Number} d Total length of animation
1118 * @return {Number} The computed value for the current animation frame
1120 bounceIn: function (t, b, c, d) {
1121 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1127 * @param {Number} t Time value used to compute current value
1128 * @param {Number} b Starting value
1129 * @param {Number} c Delta between start and end values
1130 * @param {Number} d Total length of animation
1131 * @return {Number} The computed value for the current animation frame
1133 bounceOut: function (t, b, c, d) {
1134 if ((t/=d) < (1/2.75)) {
1135 return c*(7.5625*t*t) + b;
1136 } else if (t < (2/2.75)) {
1137 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1138 } else if (t < (2.5/2.75)) {
1139 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1141 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1145 * Bounces off start and end.
1146 * @method bounceBoth
1147 * @param {Number} t Time value used to compute current value
1148 * @param {Number} b Starting value
1149 * @param {Number} c Delta between start and end values
1150 * @param {Number} d Total length of animation
1151 * @return {Number} The computed value for the current animation frame
1153 bounceBoth: function (t, b, c, d) {
1155 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1157 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1163 * Anim subclass for moving elements along a path defined by the "points"
1164 * member of "attributes". All "points" are arrays with x, y coordinates.
1165 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1167 * @namespace YAHOO.util
1168 * @requires YAHOO.util.Anim
1169 * @requires YAHOO.util.AnimMgr
1170 * @requires YAHOO.util.Easing
1171 * @requires YAHOO.util.Bezier
1172 * @requires YAHOO.util.Dom
1173 * @requires YAHOO.util.Event
1174 * @requires YAHOO.util.CustomEvent
1176 * @extends YAHOO.util.ColorAnim
1177 * @param {String | HTMLElement} el Reference to the element that will be animated
1178 * @param {Object} attributes The attribute(s) to be animated.
1179 * Each attribute is an object with at minimum a "to" or "by" member defined.
1180 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1181 * All attribute names use camelCase.
1182 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1183 * @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)
1185 var Motion = function(el, attributes, duration, method) {
1186 if (el) { // dont break existing subclasses not using YAHOO.extend
1187 Motion.superclass.constructor.call(this, el, attributes, duration, method);
1192 Motion.NAME = 'Motion';
1196 YAHOO.extend(Motion, Y.ColorAnim);
1198 var superclass = Motion.superclass;
1199 var proto = Motion.prototype;
1201 proto.patterns.points = /^points$/i;
1203 proto.setAttribute = function(attr, val, unit) {
1204 if ( this.patterns.points.test(attr) ) {
1205 unit = unit || 'px';
1206 superclass.setAttribute.call(this, 'left', val[0], unit);
1207 superclass.setAttribute.call(this, 'top', val[1], unit);
1209 superclass.setAttribute.call(this, attr, val, unit);
1213 proto.getAttribute = function(attr) {
1214 if ( this.patterns.points.test(attr) ) {
1216 superclass.getAttribute.call(this, 'left'),
1217 superclass.getAttribute.call(this, 'top')
1220 val = superclass.getAttribute.call(this, attr);
1226 proto.doMethod = function(attr, start, end) {
1229 if ( this.patterns.points.test(attr) ) {
1230 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1231 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1233 val = superclass.doMethod.call(this, attr, start, end);
1238 proto.setRuntimeAttribute = function(attr) {
1239 if ( this.patterns.points.test(attr) ) {
1240 var el = this.getEl();
1241 var attributes = this.attributes;
1243 var control = attributes['points']['control'] || [];
1247 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1248 control = [control];
1249 } else { // break reference to attributes.points.control
1251 for (i = 0, len = control.length; i< len; ++i) {
1252 tmp[i] = control[i];
1257 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1258 Y.Dom.setStyle(el, 'position', 'relative');
1261 if ( isset(attributes['points']['from']) ) {
1262 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1264 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1266 start = this.getAttribute('points'); // get actual top & left
1268 // TO beats BY, per SMIL 2.1 spec
1269 if ( isset(attributes['points']['to']) ) {
1270 end = translateValues.call(this, attributes['points']['to'], start);
1272 var pageXY = Y.Dom.getXY(this.getEl());
1273 for (i = 0, len = control.length; i < len; ++i) {
1274 control[i] = translateValues.call(this, control[i], start);
1278 } else if ( isset(attributes['points']['by']) ) {
1279 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1281 for (i = 0, len = control.length; i < len; ++i) {
1282 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1286 this.runtimeAttributes[attr] = [start];
1288 if (control.length > 0) {
1289 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1292 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1295 superclass.setRuntimeAttribute.call(this, attr);
1299 var translateValues = function(val, start) {
1300 var pageXY = Y.Dom.getXY(this.getEl());
1301 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1306 var isset = function(prop) {
1307 return (typeof prop !== 'undefined');
1314 * Anim subclass for scrolling elements to a position defined by the "scroll"
1315 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1316 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1318 * @namespace YAHOO.util
1319 * @requires YAHOO.util.Anim
1320 * @requires YAHOO.util.AnimMgr
1321 * @requires YAHOO.util.Easing
1322 * @requires YAHOO.util.Bezier
1323 * @requires YAHOO.util.Dom
1324 * @requires YAHOO.util.Event
1325 * @requires YAHOO.util.CustomEvent
1326 * @extends YAHOO.util.ColorAnim
1328 * @param {String or HTMLElement} el Reference to the element that will be animated
1329 * @param {Object} attributes The attribute(s) to be animated.
1330 * Each attribute is an object with at minimum a "to" or "by" member defined.
1331 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1332 * All attribute names use camelCase.
1333 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1334 * @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)
1336 var Scroll = function(el, attributes, duration, method) {
1337 if (el) { // dont break existing subclasses not using YAHOO.extend
1338 Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1342 Scroll.NAME = 'Scroll';
1346 YAHOO.extend(Scroll, Y.ColorAnim);
1348 var superclass = Scroll.superclass;
1349 var proto = Scroll.prototype;
1351 proto.doMethod = function(attr, start, end) {
1354 if (attr == 'scroll') {
1356 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1357 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1361 val = superclass.doMethod.call(this, attr, start, end);
1366 proto.getAttribute = function(attr) {
1368 var el = this.getEl();
1370 if (attr == 'scroll') {
1371 val = [ el.scrollLeft, el.scrollTop ];
1373 val = superclass.getAttribute.call(this, attr);
1379 proto.setAttribute = function(attr, val, unit) {
1380 var el = this.getEl();
1382 if (attr == 'scroll') {
1383 el.scrollLeft = val[0];
1384 el.scrollTop = val[1];
1386 superclass.setAttribute.call(this, attr, val, unit);
1392 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.8.0r4", build: "2449"});