2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
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;
97 if (attr in el && !('style' in el && attr in el.style)) {
100 Y.Dom.setStyle(el, attr, val + unit);
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;
656 this._getIndex = getIndex;
659 * Used to calculate Bezier splines for any number of control points.
661 * @namespace YAHOO.util
664 YAHOO.util.Bezier = new function() {
666 * Get the current position of the animated element based on t.
667 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
668 * At least 2 points are required (start and end).
669 * First point is start. Last point is end.
670 * Additional control points are optional.
671 * @method getPosition
672 * @param {Array} points An array containing Bezier points
673 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
674 * @return {Array} An array containing int x and y member data
676 this.getPosition = function(points, t) {
677 var n = points.length;
680 for (var i = 0; i < n; ++i){
681 tmp[i] = [points[i][0], points[i][1]]; // save input
684 for (var j = 1; j < n; ++j) {
685 for (i = 0; i < n - j; ++i) {
686 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
687 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
691 return [ tmp[0][0], tmp[0][1] ];
697 * Anim subclass for color transitions.
698 * <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,
699 * [255,255,255], or rgb(255,255,255)</p>
701 * @namespace YAHOO.util
702 * @requires YAHOO.util.Anim
703 * @requires YAHOO.util.AnimMgr
704 * @requires YAHOO.util.Easing
705 * @requires YAHOO.util.Bezier
706 * @requires YAHOO.util.Dom
707 * @requires YAHOO.util.Event
709 * @extends YAHOO.util.Anim
710 * @param {HTMLElement | String} el Reference to the element that will be animated
711 * @param {Object} attributes The attribute(s) to be animated.
712 * Each attribute is an object with at minimum a "to" or "by" member defined.
713 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
714 * All attribute names use camelCase.
715 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
716 * @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)
718 var ColorAnim = function(el, attributes, duration, method) {
719 ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
722 ColorAnim.NAME = 'ColorAnim';
724 ColorAnim.DEFAULT_BGCOLOR = '#fff';
727 YAHOO.extend(ColorAnim, Y.Anim);
729 var superclass = ColorAnim.superclass;
730 var proto = ColorAnim.prototype;
732 proto.patterns.color = /color$/i;
733 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
734 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
735 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
736 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
739 * Attempts to parse the given string and return a 3-tuple.
741 * @param {String} s The string to parse.
742 * @return {Array} The 3-tuple of rgb values.
744 proto.parseColor = function(s) {
745 if (s.length == 3) { return s; }
747 var c = this.patterns.hex.exec(s);
748 if (c && c.length == 4) {
749 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
752 c = this.patterns.rgb.exec(s);
753 if (c && c.length == 4) {
754 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
757 c = this.patterns.hex3.exec(s);
758 if (c && c.length == 4) {
759 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
765 proto.getAttribute = function(attr) {
766 var el = this.getEl();
767 if (this.patterns.color.test(attr) ) {
768 var val = YAHOO.util.Dom.getStyle(el, attr);
771 if (this.patterns.transparent.test(val)) { // bgcolor default
772 var parent = YAHOO.util.Dom.getAncestorBy(el, function(node) {
773 return !that.patterns.transparent.test(val);
777 val = Y.Dom.getStyle(parent, attr);
779 val = ColorAnim.DEFAULT_BGCOLOR;
783 val = superclass.getAttribute.call(this, attr);
789 proto.doMethod = function(attr, start, end) {
792 if ( this.patterns.color.test(attr) ) {
794 for (var i = 0, len = start.length; i < len; ++i) {
795 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
798 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
801 val = superclass.doMethod.call(this, attr, start, end);
807 proto.setRuntimeAttribute = function(attr) {
808 superclass.setRuntimeAttribute.call(this, attr);
810 if ( this.patterns.color.test(attr) ) {
811 var attributes = this.attributes;
812 var start = this.parseColor(this.runtimeAttributes[attr].start);
813 var end = this.parseColor(this.runtimeAttributes[attr].end);
814 // fix colors if going "by"
815 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
816 end = this.parseColor(attributes[attr].by);
818 for (var i = 0, len = start.length; i < len; ++i) {
819 end[i] = start[i] + end[i];
823 this.runtimeAttributes[attr].start = start;
824 this.runtimeAttributes[attr].end = end;
828 Y.ColorAnim = ColorAnim;
831 TERMS OF USE - EASING EQUATIONS
832 Open source under the BSD License.
833 Copyright 2001 Robert Penner All rights reserved.
835 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
837 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
838 * 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.
839 * 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.
841 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.
845 * Singleton that determines how an animation proceeds from start to end.
847 * @namespace YAHOO.util
850 YAHOO.util.Easing = {
853 * Uniform speed between points.
855 * @param {Number} t Time value used to compute current value
856 * @param {Number} b Starting value
857 * @param {Number} c Delta between start and end values
858 * @param {Number} d Total length of animation
859 * @return {Number} The computed value for the current animation frame
861 easeNone: function (t, b, c, d) {
866 * Begins slowly and accelerates towards end.
868 * @param {Number} t Time value used to compute current value
869 * @param {Number} b Starting value
870 * @param {Number} c Delta between start and end values
871 * @param {Number} d Total length of animation
872 * @return {Number} The computed value for the current animation frame
874 easeIn: function (t, b, c, d) {
875 return c*(t/=d)*t + b;
879 * Begins quickly and decelerates towards end.
881 * @param {Number} t Time value used to compute current value
882 * @param {Number} b Starting value
883 * @param {Number} c Delta between start and end values
884 * @param {Number} d Total length of animation
885 * @return {Number} The computed value for the current animation frame
887 easeOut: function (t, b, c, d) {
888 return -c *(t/=d)*(t-2) + b;
892 * Begins slowly and decelerates towards end.
894 * @param {Number} t Time value used to compute current value
895 * @param {Number} b Starting value
896 * @param {Number} c Delta between start and end values
897 * @param {Number} d Total length of animation
898 * @return {Number} The computed value for the current animation frame
900 easeBoth: function (t, b, c, d) {
905 return -c/2 * ((--t)*(t-2) - 1) + b;
909 * Begins slowly and accelerates towards end.
910 * @method easeInStrong
911 * @param {Number} t Time value used to compute current value
912 * @param {Number} b Starting value
913 * @param {Number} c Delta between start and end values
914 * @param {Number} d Total length of animation
915 * @return {Number} The computed value for the current animation frame
917 easeInStrong: function (t, b, c, d) {
918 return c*(t/=d)*t*t*t + b;
922 * Begins quickly and decelerates towards end.
923 * @method easeOutStrong
924 * @param {Number} t Time value used to compute current value
925 * @param {Number} b Starting value
926 * @param {Number} c Delta between start and end values
927 * @param {Number} d Total length of animation
928 * @return {Number} The computed value for the current animation frame
930 easeOutStrong: function (t, b, c, d) {
931 return -c * ((t=t/d-1)*t*t*t - 1) + b;
935 * Begins slowly and decelerates towards end.
936 * @method easeBothStrong
937 * @param {Number} t Time value used to compute current value
938 * @param {Number} b Starting value
939 * @param {Number} c Delta between start and end values
940 * @param {Number} d Total length of animation
941 * @return {Number} The computed value for the current animation frame
943 easeBothStrong: function (t, b, c, d) {
945 return c/2*t*t*t*t + b;
948 return -c/2 * ((t-=2)*t*t*t - 2) + b;
952 * Snap in elastic effect.
954 * @param {Number} t Time value used to compute current value
955 * @param {Number} b Starting value
956 * @param {Number} c Delta between start and end values
957 * @param {Number} d Total length of animation
958 * @param {Number} a Amplitude (optional)
959 * @param {Number} p Period (optional)
960 * @return {Number} The computed value for the current animation frame
963 elasticIn: function (t, b, c, d, a, p) {
967 if ( (t /= d) == 1 ) {
974 if (!a || a < Math.abs(c)) {
979 var s = p/(2*Math.PI) * Math.asin (c/a);
982 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
986 * Snap out elastic effect.
988 * @param {Number} t Time value used to compute current value
989 * @param {Number} b Starting value
990 * @param {Number} c Delta between start and end values
991 * @param {Number} d Total length of animation
992 * @param {Number} a Amplitude (optional)
993 * @param {Number} p Period (optional)
994 * @return {Number} The computed value for the current animation frame
996 elasticOut: function (t, b, c, d, a, p) {
1000 if ( (t /= d) == 1 ) {
1007 if (!a || a < Math.abs(c)) {
1012 var s = p/(2*Math.PI) * Math.asin (c/a);
1015 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1019 * Snap both elastic effect.
1020 * @method elasticBoth
1021 * @param {Number} t Time value used to compute current value
1022 * @param {Number} b Starting value
1023 * @param {Number} c Delta between start and end values
1024 * @param {Number} d Total length of animation
1025 * @param {Number} a Amplitude (optional)
1026 * @param {Number} p Period (optional)
1027 * @return {Number} The computed value for the current animation frame
1029 elasticBoth: function (t, b, c, d, a, p) {
1034 if ( (t /= d/2) == 2 ) {
1042 if ( !a || a < Math.abs(c) ) {
1047 var s = p/(2*Math.PI) * Math.asin (c/a);
1051 return -.5*(a*Math.pow(2,10*(t-=1)) *
1052 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1054 return a*Math.pow(2,-10*(t-=1)) *
1055 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1060 * Backtracks slightly, then reverses direction and moves to end.
1062 * @param {Number} t Time value used to compute current value
1063 * @param {Number} b Starting value
1064 * @param {Number} c Delta between start and end values
1065 * @param {Number} d Total length of animation
1066 * @param {Number} s Overshoot (optional)
1067 * @return {Number} The computed value for the current animation frame
1069 backIn: function (t, b, c, d, s) {
1070 if (typeof s == 'undefined') {
1073 return c*(t/=d)*t*((s+1)*t - s) + b;
1077 * Overshoots end, then reverses and comes back to end.
1079 * @param {Number} t Time value used to compute current value
1080 * @param {Number} b Starting value
1081 * @param {Number} c Delta between start and end values
1082 * @param {Number} d Total length of animation
1083 * @param {Number} s Overshoot (optional)
1084 * @return {Number} The computed value for the current animation frame
1086 backOut: function (t, b, c, d, s) {
1087 if (typeof s == 'undefined') {
1090 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1094 * Backtracks slightly, then reverses direction, overshoots end,
1095 * then reverses and comes back to end.
1097 * @param {Number} t Time value used to compute current value
1098 * @param {Number} b Starting value
1099 * @param {Number} c Delta between start and end values
1100 * @param {Number} d Total length of animation
1101 * @param {Number} s Overshoot (optional)
1102 * @return {Number} The computed value for the current animation frame
1104 backBoth: function (t, b, c, d, s) {
1105 if (typeof s == 'undefined') {
1109 if ((t /= d/2 ) < 1) {
1110 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1112 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1116 * Bounce off of start.
1118 * @param {Number} t Time value used to compute current value
1119 * @param {Number} b Starting value
1120 * @param {Number} c Delta between start and end values
1121 * @param {Number} d Total length of animation
1122 * @return {Number} The computed value for the current animation frame
1124 bounceIn: function (t, b, c, d) {
1125 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1131 * @param {Number} t Time value used to compute current value
1132 * @param {Number} b Starting value
1133 * @param {Number} c Delta between start and end values
1134 * @param {Number} d Total length of animation
1135 * @return {Number} The computed value for the current animation frame
1137 bounceOut: function (t, b, c, d) {
1138 if ((t/=d) < (1/2.75)) {
1139 return c*(7.5625*t*t) + b;
1140 } else if (t < (2/2.75)) {
1141 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1142 } else if (t < (2.5/2.75)) {
1143 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1145 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1149 * Bounces off start and end.
1150 * @method bounceBoth
1151 * @param {Number} t Time value used to compute current value
1152 * @param {Number} b Starting value
1153 * @param {Number} c Delta between start and end values
1154 * @param {Number} d Total length of animation
1155 * @return {Number} The computed value for the current animation frame
1157 bounceBoth: function (t, b, c, d) {
1159 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1161 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1167 * Anim subclass for moving elements along a path defined by the "points"
1168 * member of "attributes". All "points" are arrays with x, y coordinates.
1169 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1171 * @namespace YAHOO.util
1172 * @requires YAHOO.util.Anim
1173 * @requires YAHOO.util.AnimMgr
1174 * @requires YAHOO.util.Easing
1175 * @requires YAHOO.util.Bezier
1176 * @requires YAHOO.util.Dom
1177 * @requires YAHOO.util.Event
1178 * @requires YAHOO.util.CustomEvent
1180 * @extends YAHOO.util.ColorAnim
1181 * @param {String | HTMLElement} el Reference to the element that will be animated
1182 * @param {Object} attributes The attribute(s) to be animated.
1183 * Each attribute is an object with at minimum a "to" or "by" member defined.
1184 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1185 * All attribute names use camelCase.
1186 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1187 * @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)
1189 var Motion = function(el, attributes, duration, method) {
1190 if (el) { // dont break existing subclasses not using YAHOO.extend
1191 Motion.superclass.constructor.call(this, el, attributes, duration, method);
1196 Motion.NAME = 'Motion';
1200 YAHOO.extend(Motion, Y.ColorAnim);
1202 var superclass = Motion.superclass;
1203 var proto = Motion.prototype;
1205 proto.patterns.points = /^points$/i;
1207 proto.setAttribute = function(attr, val, unit) {
1208 if ( this.patterns.points.test(attr) ) {
1209 unit = unit || 'px';
1210 superclass.setAttribute.call(this, 'left', val[0], unit);
1211 superclass.setAttribute.call(this, 'top', val[1], unit);
1213 superclass.setAttribute.call(this, attr, val, unit);
1217 proto.getAttribute = function(attr) {
1218 if ( this.patterns.points.test(attr) ) {
1220 superclass.getAttribute.call(this, 'left'),
1221 superclass.getAttribute.call(this, 'top')
1224 val = superclass.getAttribute.call(this, attr);
1230 proto.doMethod = function(attr, start, end) {
1233 if ( this.patterns.points.test(attr) ) {
1234 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1235 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1237 val = superclass.doMethod.call(this, attr, start, end);
1242 proto.setRuntimeAttribute = function(attr) {
1243 if ( this.patterns.points.test(attr) ) {
1244 var el = this.getEl();
1245 var attributes = this.attributes;
1247 var control = attributes['points']['control'] || [];
1251 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1252 control = [control];
1253 } else { // break reference to attributes.points.control
1255 for (i = 0, len = control.length; i< len; ++i) {
1256 tmp[i] = control[i];
1261 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1262 Y.Dom.setStyle(el, 'position', 'relative');
1265 if ( isset(attributes['points']['from']) ) {
1266 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1268 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1270 start = this.getAttribute('points'); // get actual top & left
1272 // TO beats BY, per SMIL 2.1 spec
1273 if ( isset(attributes['points']['to']) ) {
1274 end = translateValues.call(this, attributes['points']['to'], start);
1276 var pageXY = Y.Dom.getXY(this.getEl());
1277 for (i = 0, len = control.length; i < len; ++i) {
1278 control[i] = translateValues.call(this, control[i], start);
1282 } else if ( isset(attributes['points']['by']) ) {
1283 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1285 for (i = 0, len = control.length; i < len; ++i) {
1286 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1290 this.runtimeAttributes[attr] = [start];
1292 if (control.length > 0) {
1293 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1296 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1299 superclass.setRuntimeAttribute.call(this, attr);
1303 var translateValues = function(val, start) {
1304 var pageXY = Y.Dom.getXY(this.getEl());
1305 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1310 var isset = function(prop) {
1311 return (typeof prop !== 'undefined');
1318 * Anim subclass for scrolling elements to a position defined by the "scroll"
1319 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1320 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1322 * @namespace YAHOO.util
1323 * @requires YAHOO.util.Anim
1324 * @requires YAHOO.util.AnimMgr
1325 * @requires YAHOO.util.Easing
1326 * @requires YAHOO.util.Bezier
1327 * @requires YAHOO.util.Dom
1328 * @requires YAHOO.util.Event
1329 * @requires YAHOO.util.CustomEvent
1330 * @extends YAHOO.util.ColorAnim
1332 * @param {String or HTMLElement} el Reference to the element that will be animated
1333 * @param {Object} attributes The attribute(s) to be animated.
1334 * Each attribute is an object with at minimum a "to" or "by" member defined.
1335 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1336 * All attribute names use camelCase.
1337 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1338 * @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)
1340 var Scroll = function(el, attributes, duration, method) {
1341 if (el) { // dont break existing subclasses not using YAHOO.extend
1342 Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1346 Scroll.NAME = 'Scroll';
1350 YAHOO.extend(Scroll, Y.ColorAnim);
1352 var superclass = Scroll.superclass;
1353 var proto = Scroll.prototype;
1355 proto.doMethod = function(attr, start, end) {
1358 if (attr == 'scroll') {
1360 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1361 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1365 val = superclass.doMethod.call(this, attr, start, end);
1370 proto.getAttribute = function(attr) {
1372 var el = this.getEl();
1374 if (attr == 'scroll') {
1375 val = [ el.scrollLeft, el.scrollTop ];
1377 val = superclass.getAttribute.call(this, attr);
1383 proto.setAttribute = function(attr, val, unit) {
1384 var el = this.getEl();
1386 if (attr == 'scroll') {
1387 el.scrollLeft = val[0];
1388 el.scrollTop = val[1];
1390 superclass.setAttribute.call(this, attr, val, unit);
1396 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.8.1", build: "19"});