Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / lib / yui / animation / animation.js
blobf764bfc982b5bcc4c5673d1aa8379043837e9fa6
1 /*
2 Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.5.2
6 */
7 (function() {
9 var Y = YAHOO.util;
12 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
13 Code licensed under the BSD License:
14 http://developer.yahoo.net/yui/license.txt
17 /**
18 * The animation module provides allows effects to be added to HTMLElements.
19 * @module animation
20 * @requires yahoo, event, dom
23 /**
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>
27 * @class Anim
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
34 * @constructor
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) {
45 if (!el) {
47 this.init(el, attributes, duration, method);
50 Anim.NAME = 'Anim';
52 Anim.prototype = {
53 /**
54 * Provides a readable name for the Anim instance.
55 * @method toString
56 * @return {String}
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
71 /**
72 * Returns the value computed by the animation's "method".
73 * @method doMethod
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);
83 /**
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);
96 },
98 /**
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'
120 val = 0;
123 return val;
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) ) {
134 return 'px';
137 return '';
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
144 * @private
146 setRuntimeAttribute: function(attr) {
147 var start;
148 var end;
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) {
168 end = [];
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"
172 } else {
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);
183 return true;
187 * Constructor for Anim instance.
188 * @method init
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
201 * @private
202 * @type Boolean
204 var isAnimated = false;
207 * A Date object that is created when the animation begins.
208 * @property startTime
209 * @private
210 * @type Date
212 var startTime = null;
215 * The number of frames this animation was able to execute.
216 * @property actualFrames
217 * @private
218 * @type Int
220 var actualFrames = 0;
223 * The element to be animated.
224 * @property el
225 * @private
226 * @type HTMLElement
228 el = Y.Dom.get(el);
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
238 * @type Object
240 this.attributes = attributes || {};
243 * The length of the animation. Defaults to "1" (second).
244 * @property duration
245 * @type Number
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".
252 * @property method
253 * @type Function
255 this.method = method || Y.Easing.easeNone;
258 * Whether or not the duration should be treated as seconds.
259 * Defaults to true.
260 * @property useSeconds
261 * @type Boolean
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
269 * @type Int
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
277 * @type Int
279 this.totalFrames = Y.AnimMgr.fps;
282 * Changes the animated element
283 * @method setEl
285 this.setEl = function(element) {
286 el = Y.Dom.get(element);
290 * Returns a reference to the animated element.
291 * @method getEl
292 * @return {HTMLElement}
294 this.getEl = function() { return el; };
297 * Checks whether the element is currently animated.
298 * @method isAnimated
299 * @return {Boolean} current value of isAnimated.
301 this.isAnimated = function() {
302 return isAnimated;
306 * Returns the animation start time.
307 * @method getStartTime
308 * @return {Date} current value of startTime.
310 this.getStartTime = function() {
311 return startTime;
314 this.runtimeAttributes = {};
319 * Starts the animation by registering it with the animation manager.
320 * @method animate
322 this.animate = function() {
323 if ( this.isAnimated() ) {
324 return false;
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);
335 return true;
339 * Stops the animation. Normally called by AnimMgr when animation completes.
340 * @method stop
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
345 return false;
348 if (finish) {
349 this.currentFrame = this.totalFrames;
350 this._onTween.fire();
352 Y.AnimMgr.stop(this);
355 var onStart = function() {
356 this.onStart.fire();
358 this.runtimeAttributes = {};
359 for (var attr in this.attributes) {
360 this.setRuntimeAttribute(attr);
363 isAnimated = true;
364 actualFrames = 0;
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).
370 * @private
373 var onTween = function() {
374 var data = {
375 duration: new Date() - this.getStartTime(),
376 currentFrame: this.currentFrame
379 data.toString = function() {
380 return (
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);
394 actualFrames += 1;
397 var onComplete = function() {
398 var actual_duration = (new Date() - startTime) / 1000 ;
400 var data = {
401 duration: actual_duration,
402 frames: actualFrames,
403 fps: actualFrames / actual_duration
406 data.toString = function() {
407 return (
408 'duration: ' + data.duration +
409 ', frames: ' + data.frames +
410 ', fps: ' + data.fps
414 isAnimated = false;
415 actualFrames = 0;
416 this.onComplete.fire(data);
420 * Custom event that fires after onStart, useful in subclassing
421 * @private
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)
428 * @event onStart
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)
435 * @event onTween
437 this.onTween = new Y.CustomEvent('tween', this);
440 * Custom event that fires after onTween
441 * @private
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)
448 * @event onComplete
450 this.onComplete = new Y.CustomEvent('complete', this);
452 * Custom event that fires after onComplete
453 * @private
455 this._onComplete = new Y.CustomEvent('_complete', this, true);
457 this._onStart.subscribe(onStart);
458 this._onTween.subscribe(onTween);
459 this._onComplete.subscribe(onComplete);
463 Y.Anim = Anim;
464 })();
466 * Handles animation queueing and threading.
467 * Used by Anim and subclasses.
468 * @class AnimMgr
469 * @namespace YAHOO.util
471 YAHOO.util.AnimMgr = new function() {
472 /**
473 * Reference to the animation Interval.
474 * @property thread
475 * @private
476 * @type Int
478 var thread = null;
480 /**
481 * The current queue of registered animation objects.
482 * @property queue
483 * @private
484 * @type Array
486 var queue = [];
488 /**
489 * The number of active animations.
490 * @property tweenCount
491 * @private
492 * @type Int
494 var tweenCount = 0;
496 /**
497 * Base frame rate (frames per second).
498 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
499 * @property fps
500 * @type Int
503 this.fps = 1000;
505 /**
506 * Interval delay in milliseconds, defaults to fastest possible.
507 * @property delay
508 * @type Int
511 this.delay = 1;
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;
521 tweenCount += 1;
522 tween._onStart.fire();
523 this.start();
527 * removes an animation instance from the animation queue.
528 * All animation instances must be registered in order to animate.
529 * @method unRegister
530 * @param {object} tween The Anim instance to be be registered
531 * @param {Int} index The index of the Anim instance
532 * @private
534 this.unRegister = function(tween, index) {
535 index = index || getIndex(tween);
536 if (!tween.isAnimated() || index == -1) {
537 return false;
540 tween._onComplete.fire();
541 queue.splice(index, 1);
543 tweenCount -= 1;
544 if (tweenCount <= 0) {
545 this.stop();
548 return true;
552 * Starts the animation thread.
553 * Only one thread can run at a time.
554 * @method start
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.
564 * @method stop
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) {
569 if (!tween) {
570 clearInterval(thread);
572 for (var i = 0, len = queue.length; i < len; ++i) {
573 this.unRegister(queue[0], 0);
576 queue = [];
577 thread = null;
578 tweenCount = 0;
580 else {
581 this.unRegister(tween);
586 * Called per Interval to handle each animation frame.
587 * @method run
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) {
599 correctFrame(tween);
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;
613 return -1;
617 * On the fly frame correction to keep animation on time.
618 * @method correctFrame
619 * @private
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());
627 var tweak = 0;
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.
645 * @class Bezier
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;
663 var tmp = [];
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] ];
680 (function() {
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>
685 * @class ColorAnim
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
693 * @constructor
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 // shorthand
710 var Y = YAHOO.util;
711 YAHOO.extend(ColorAnim, Y.Anim);
713 var superclass = ColorAnim.superclass;
714 var proto = ColorAnim.prototype;
716 proto.patterns.color = /color$/i;
717 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
718 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
719 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
720 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
723 * Attempts to parse the given string and return a 3-tuple.
724 * @method parseColor
725 * @param {String} s The string to parse.
726 * @return {Array} The 3-tuple of rgb values.
728 proto.parseColor = function(s) {
729 if (s.length == 3) { return s; }
731 var c = this.patterns.hex.exec(s);
732 if (c && c.length == 4) {
733 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
736 c = this.patterns.rgb.exec(s);
737 if (c && c.length == 4) {
738 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
741 c = this.patterns.hex3.exec(s);
742 if (c && c.length == 4) {
743 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
746 return null;
749 proto.getAttribute = function(attr) {
750 var el = this.getEl();
751 if ( this.patterns.color.test(attr) ) {
752 var val = YAHOO.util.Dom.getStyle(el, attr);
754 if (this.patterns.transparent.test(val)) { // bgcolor default
755 var parent = el.parentNode; // try and get from an ancestor
756 val = Y.Dom.getStyle(parent, attr);
758 while (parent && this.patterns.transparent.test(val)) {
759 parent = parent.parentNode;
760 val = Y.Dom.getStyle(parent, attr);
761 if (parent.tagName.toUpperCase() == 'HTML') {
762 val = '#fff';
766 } else {
767 val = superclass.getAttribute.call(this, attr);
770 return val;
773 proto.doMethod = function(attr, start, end) {
774 var val;
776 if ( this.patterns.color.test(attr) ) {
777 val = [];
778 for (var i = 0, len = start.length; i < len; ++i) {
779 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
782 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
784 else {
785 val = superclass.doMethod.call(this, attr, start, end);
788 return val;
791 proto.setRuntimeAttribute = function(attr) {
792 superclass.setRuntimeAttribute.call(this, attr);
794 if ( this.patterns.color.test(attr) ) {
795 var attributes = this.attributes;
796 var start = this.parseColor(this.runtimeAttributes[attr].start);
797 var end = this.parseColor(this.runtimeAttributes[attr].end);
798 // fix colors if going "by"
799 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
800 end = this.parseColor(attributes[attr].by);
802 for (var i = 0, len = start.length; i < len; ++i) {
803 end[i] = start[i] + end[i];
807 this.runtimeAttributes[attr].start = start;
808 this.runtimeAttributes[attr].end = end;
812 Y.ColorAnim = ColorAnim;
813 })();
815 TERMS OF USE - EASING EQUATIONS
816 Open source under the BSD License.
817 Copyright 2001 Robert Penner All rights reserved.
819 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
821 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
822 * 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.
823 * 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.
825 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.
829 * Singleton that determines how an animation proceeds from start to end.
830 * @class Easing
831 * @namespace YAHOO.util
834 YAHOO.util.Easing = {
837 * Uniform speed between points.
838 * @method easeNone
839 * @param {Number} t Time value used to compute current value
840 * @param {Number} b Starting value
841 * @param {Number} c Delta between start and end values
842 * @param {Number} d Total length of animation
843 * @return {Number} The computed value for the current animation frame
845 easeNone: function (t, b, c, d) {
846 return c*t/d + b;
850 * Begins slowly and accelerates towards end. (quadratic)
851 * @method easeIn
852 * @param {Number} t Time value used to compute current value
853 * @param {Number} b Starting value
854 * @param {Number} c Delta between start and end values
855 * @param {Number} d Total length of animation
856 * @return {Number} The computed value for the current animation frame
858 easeIn: function (t, b, c, d) {
859 return c*(t/=d)*t + b;
863 * Begins quickly and decelerates towards end. (quadratic)
864 * @method easeOut
865 * @param {Number} t Time value used to compute current value
866 * @param {Number} b Starting value
867 * @param {Number} c Delta between start and end values
868 * @param {Number} d Total length of animation
869 * @return {Number} The computed value for the current animation frame
871 easeOut: function (t, b, c, d) {
872 return -c *(t/=d)*(t-2) + b;
876 * Begins slowly and decelerates towards end. (quadratic)
877 * @method easeBoth
878 * @param {Number} t Time value used to compute current value
879 * @param {Number} b Starting value
880 * @param {Number} c Delta between start and end values
881 * @param {Number} d Total length of animation
882 * @return {Number} The computed value for the current animation frame
884 easeBoth: function (t, b, c, d) {
885 if ((t/=d/2) < 1) {
886 return c/2*t*t + b;
889 return -c/2 * ((--t)*(t-2) - 1) + b;
893 * Begins slowly and accelerates towards end. (quartic)
894 * @method easeInStrong
895 * @param {Number} t Time value used to compute current value
896 * @param {Number} b Starting value
897 * @param {Number} c Delta between start and end values
898 * @param {Number} d Total length of animation
899 * @return {Number} The computed value for the current animation frame
901 easeInStrong: function (t, b, c, d) {
902 return c*(t/=d)*t*t*t + b;
906 * Begins quickly and decelerates towards end. (quartic)
907 * @method easeOutStrong
908 * @param {Number} t Time value used to compute current value
909 * @param {Number} b Starting value
910 * @param {Number} c Delta between start and end values
911 * @param {Number} d Total length of animation
912 * @return {Number} The computed value for the current animation frame
914 easeOutStrong: function (t, b, c, d) {
915 return -c * ((t=t/d-1)*t*t*t - 1) + b;
919 * Begins slowly and decelerates towards end. (quartic)
920 * @method easeBothStrong
921 * @param {Number} t Time value used to compute current value
922 * @param {Number} b Starting value
923 * @param {Number} c Delta between start and end values
924 * @param {Number} d Total length of animation
925 * @return {Number} The computed value for the current animation frame
927 easeBothStrong: function (t, b, c, d) {
928 if ((t/=d/2) < 1) {
929 return c/2*t*t*t*t + b;
932 return -c/2 * ((t-=2)*t*t*t - 2) + b;
936 * Snap in elastic effect.
937 * @method elasticIn
938 * @param {Number} t Time value used to compute current value
939 * @param {Number} b Starting value
940 * @param {Number} c Delta between start and end values
941 * @param {Number} d Total length of animation
942 * @param {Number} a Amplitude (optional)
943 * @param {Number} p Period (optional)
944 * @return {Number} The computed value for the current animation frame
947 elasticIn: function (t, b, c, d, a, p) {
948 if (t == 0) {
949 return b;
951 if ( (t /= d) == 1 ) {
952 return b+c;
954 if (!p) {
955 p=d*.3;
958 if (!a || a < Math.abs(c)) {
959 a = c;
960 var s = p/4;
962 else {
963 var s = p/(2*Math.PI) * Math.asin (c/a);
966 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
970 * Snap out elastic effect.
971 * @method elasticOut
972 * @param {Number} t Time value used to compute current value
973 * @param {Number} b Starting value
974 * @param {Number} c Delta between start and end values
975 * @param {Number} d Total length of animation
976 * @param {Number} a Amplitude (optional)
977 * @param {Number} p Period (optional)
978 * @return {Number} The computed value for the current animation frame
980 elasticOut: function (t, b, c, d, a, p) {
981 if (t == 0) {
982 return b;
984 if ( (t /= d) == 1 ) {
985 return b+c;
987 if (!p) {
988 p=d*.3;
991 if (!a || a < Math.abs(c)) {
992 a = c;
993 var s = p / 4;
995 else {
996 var s = p/(2*Math.PI) * Math.asin (c/a);
999 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1003 * Snap both elastic effect.
1004 * @method elasticBoth
1005 * @param {Number} t Time value used to compute current value
1006 * @param {Number} b Starting value
1007 * @param {Number} c Delta between start and end values
1008 * @param {Number} d Total length of animation
1009 * @param {Number} a Amplitude (optional)
1010 * @param {Number} p Period (optional)
1011 * @return {Number} The computed value for the current animation frame
1013 elasticBoth: function (t, b, c, d, a, p) {
1014 if (t == 0) {
1015 return b;
1018 if ( (t /= d/2) == 2 ) {
1019 return b+c;
1022 if (!p) {
1023 p = d*(.3*1.5);
1026 if ( !a || a < Math.abs(c) ) {
1027 a = c;
1028 var s = p/4;
1030 else {
1031 var s = p/(2*Math.PI) * Math.asin (c/a);
1034 if (t < 1) {
1035 return -.5*(a*Math.pow(2,10*(t-=1)) *
1036 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1038 return a*Math.pow(2,-10*(t-=1)) *
1039 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1044 * Backtracks slightly, then reverses direction and moves to end.
1045 * @method backIn
1046 * @param {Number} t Time value used to compute current value
1047 * @param {Number} b Starting value
1048 * @param {Number} c Delta between start and end values
1049 * @param {Number} d Total length of animation
1050 * @param {Number} s Overshoot (optional)
1051 * @return {Number} The computed value for the current animation frame
1053 backIn: function (t, b, c, d, s) {
1054 if (typeof s == 'undefined') {
1055 s = 1.70158;
1057 return c*(t/=d)*t*((s+1)*t - s) + b;
1061 * Overshoots end, then reverses and comes back to end.
1062 * @method backOut
1063 * @param {Number} t Time value used to compute current value
1064 * @param {Number} b Starting value
1065 * @param {Number} c Delta between start and end values
1066 * @param {Number} d Total length of animation
1067 * @param {Number} s Overshoot (optional)
1068 * @return {Number} The computed value for the current animation frame
1070 backOut: function (t, b, c, d, s) {
1071 if (typeof s == 'undefined') {
1072 s = 1.70158;
1074 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1078 * Backtracks slightly, then reverses direction, overshoots end,
1079 * then reverses and comes back to end.
1080 * @method backBoth
1081 * @param {Number} t Time value used to compute current value
1082 * @param {Number} b Starting value
1083 * @param {Number} c Delta between start and end values
1084 * @param {Number} d Total length of animation
1085 * @param {Number} s Overshoot (optional)
1086 * @return {Number} The computed value for the current animation frame
1088 backBoth: function (t, b, c, d, s) {
1089 if (typeof s == 'undefined') {
1090 s = 1.70158;
1093 if ((t /= d/2 ) < 1) {
1094 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1096 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1100 * Bounce off of start.
1101 * @method bounceIn
1102 * @param {Number} t Time value used to compute current value
1103 * @param {Number} b Starting value
1104 * @param {Number} c Delta between start and end values
1105 * @param {Number} d Total length of animation
1106 * @return {Number} The computed value for the current animation frame
1108 bounceIn: function (t, b, c, d) {
1109 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1113 * Bounces off end.
1114 * @method bounceOut
1115 * @param {Number} t Time value used to compute current value
1116 * @param {Number} b Starting value
1117 * @param {Number} c Delta between start and end values
1118 * @param {Number} d Total length of animation
1119 * @return {Number} The computed value for the current animation frame
1121 bounceOut: function (t, b, c, d) {
1122 if ((t/=d) < (1/2.75)) {
1123 return c*(7.5625*t*t) + b;
1124 } else if (t < (2/2.75)) {
1125 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1126 } else if (t < (2.5/2.75)) {
1127 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1129 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1133 * Bounces off start and end.
1134 * @method bounceBoth
1135 * @param {Number} t Time value used to compute current value
1136 * @param {Number} b Starting value
1137 * @param {Number} c Delta between start and end values
1138 * @param {Number} d Total length of animation
1139 * @return {Number} The computed value for the current animation frame
1141 bounceBoth: function (t, b, c, d) {
1142 if (t < d/2) {
1143 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1145 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1149 (function() {
1151 * Anim subclass for moving elements along a path defined by the "points"
1152 * member of "attributes". All "points" are arrays with x, y coordinates.
1153 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1154 * @class Motion
1155 * @namespace YAHOO.util
1156 * @requires YAHOO.util.Anim
1157 * @requires YAHOO.util.AnimMgr
1158 * @requires YAHOO.util.Easing
1159 * @requires YAHOO.util.Bezier
1160 * @requires YAHOO.util.Dom
1161 * @requires YAHOO.util.Event
1162 * @requires YAHOO.util.CustomEvent
1163 * @constructor
1164 * @extends YAHOO.util.ColorAnim
1165 * @param {String | HTMLElement} el Reference to the element that will be animated
1166 * @param {Object} attributes The attribute(s) to be animated.
1167 * Each attribute is an object with at minimum a "to" or "by" member defined.
1168 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1169 * All attribute names use camelCase.
1170 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1171 * @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)
1173 var Motion = function(el, attributes, duration, method) {
1174 if (el) { // dont break existing subclasses not using YAHOO.extend
1175 Motion.superclass.constructor.call(this, el, attributes, duration, method);
1180 Motion.NAME = 'Motion';
1182 // shorthand
1183 var Y = YAHOO.util;
1184 YAHOO.extend(Motion, Y.ColorAnim);
1186 var superclass = Motion.superclass;
1187 var proto = Motion.prototype;
1189 proto.patterns.points = /^points$/i;
1191 proto.setAttribute = function(attr, val, unit) {
1192 if ( this.patterns.points.test(attr) ) {
1193 unit = unit || 'px';
1194 superclass.setAttribute.call(this, 'left', val[0], unit);
1195 superclass.setAttribute.call(this, 'top', val[1], unit);
1196 } else {
1197 superclass.setAttribute.call(this, attr, val, unit);
1201 proto.getAttribute = function(attr) {
1202 if ( this.patterns.points.test(attr) ) {
1203 var val = [
1204 superclass.getAttribute.call(this, 'left'),
1205 superclass.getAttribute.call(this, 'top')
1207 } else {
1208 val = superclass.getAttribute.call(this, attr);
1211 return val;
1214 proto.doMethod = function(attr, start, end) {
1215 var val = null;
1217 if ( this.patterns.points.test(attr) ) {
1218 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1219 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1220 } else {
1221 val = superclass.doMethod.call(this, attr, start, end);
1223 return val;
1226 proto.setRuntimeAttribute = function(attr) {
1227 if ( this.patterns.points.test(attr) ) {
1228 var el = this.getEl();
1229 var attributes = this.attributes;
1230 var start;
1231 var control = attributes['points']['control'] || [];
1232 var end;
1233 var i, len;
1235 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1236 control = [control];
1237 } else { // break reference to attributes.points.control
1238 var tmp = [];
1239 for (i = 0, len = control.length; i< len; ++i) {
1240 tmp[i] = control[i];
1242 control = tmp;
1245 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1246 Y.Dom.setStyle(el, 'position', 'relative');
1249 if ( isset(attributes['points']['from']) ) {
1250 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1252 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1254 start = this.getAttribute('points'); // get actual top & left
1256 // TO beats BY, per SMIL 2.1 spec
1257 if ( isset(attributes['points']['to']) ) {
1258 end = translateValues.call(this, attributes['points']['to'], start);
1260 var pageXY = Y.Dom.getXY(this.getEl());
1261 for (i = 0, len = control.length; i < len; ++i) {
1262 control[i] = translateValues.call(this, control[i], start);
1266 } else if ( isset(attributes['points']['by']) ) {
1267 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1269 for (i = 0, len = control.length; i < len; ++i) {
1270 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1274 this.runtimeAttributes[attr] = [start];
1276 if (control.length > 0) {
1277 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1280 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1282 else {
1283 superclass.setRuntimeAttribute.call(this, attr);
1287 var translateValues = function(val, start) {
1288 var pageXY = Y.Dom.getXY(this.getEl());
1289 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1291 return val;
1294 var isset = function(prop) {
1295 return (typeof prop !== 'undefined');
1298 Y.Motion = Motion;
1299 })();
1300 (function() {
1302 * Anim subclass for scrolling elements to a position defined by the "scroll"
1303 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1304 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1305 * @class Scroll
1306 * @namespace YAHOO.util
1307 * @requires YAHOO.util.Anim
1308 * @requires YAHOO.util.AnimMgr
1309 * @requires YAHOO.util.Easing
1310 * @requires YAHOO.util.Bezier
1311 * @requires YAHOO.util.Dom
1312 * @requires YAHOO.util.Event
1313 * @requires YAHOO.util.CustomEvent
1314 * @extends YAHOO.util.ColorAnim
1315 * @constructor
1316 * @param {String or HTMLElement} el Reference to the element that will be animated
1317 * @param {Object} attributes The attribute(s) to be animated.
1318 * Each attribute is an object with at minimum a "to" or "by" member defined.
1319 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1320 * All attribute names use camelCase.
1321 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1322 * @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)
1324 var Scroll = function(el, attributes, duration, method) {
1325 if (el) { // dont break existing subclasses not using YAHOO.extend
1326 Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1330 Scroll.NAME = 'Scroll';
1332 // shorthand
1333 var Y = YAHOO.util;
1334 YAHOO.extend(Scroll, Y.ColorAnim);
1336 var superclass = Scroll.superclass;
1337 var proto = Scroll.prototype;
1339 proto.doMethod = function(attr, start, end) {
1340 var val = null;
1342 if (attr == 'scroll') {
1343 val = [
1344 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1345 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1348 } else {
1349 val = superclass.doMethod.call(this, attr, start, end);
1351 return val;
1354 proto.getAttribute = function(attr) {
1355 var val = null;
1356 var el = this.getEl();
1358 if (attr == 'scroll') {
1359 val = [ el.scrollLeft, el.scrollTop ];
1360 } else {
1361 val = superclass.getAttribute.call(this, attr);
1364 return val;
1367 proto.setAttribute = function(attr, val, unit) {
1368 var el = this.getEl();
1370 if (attr == 'scroll') {
1371 el.scrollLeft = val[0];
1372 el.scrollTop = val[1];
1373 } else {
1374 superclass.setAttribute.call(this, attr, val, unit);
1378 Y.Scroll = Scroll;
1379 })();
1380 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.5.2", build: "1076"});