MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / lib / yui / animation / animation-debug.js
blob4980ffadb3b8f8b101fe6cac4e9a1b8f442dfb6d
1 /*
2 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 2.3.0
6 */
7 /*
8 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
9 Code licensed under the BSD License:
10 http://developer.yahoo.net/yui/license.txt
13 /**
14 * The animation module provides allows effects to be added to HTMLElements.
15 * @module animation
16 * @requires yahoo, event, dom
19 /**
21 * Base animation class that provides the interface for building animated effects.
22 * <p>Usage: var myAnim = new YAHOO.util.Anim(el, { width: { from: 10, to: 100 } }, 1, YAHOO.util.Easing.easeOut);</p>
23 * @class Anim
24 * @namespace YAHOO.util
25 * @requires YAHOO.util.AnimMgr
26 * @requires YAHOO.util.Easing
27 * @requires YAHOO.util.Dom
28 * @requires YAHOO.util.Event
29 * @requires YAHOO.util.CustomEvent
30 * @constructor
31 * @param {String | HTMLElement} el Reference to the element that will be animated
32 * @param {Object} attributes The attribute(s) to be animated.
33 * Each attribute is an object with at minimum a "to" or "by" member defined.
34 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
35 * All attribute names use camelCase.
36 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
37 * @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)
40 YAHOO.util.Anim = function(el, attributes, duration, method) {
41 if (!el) {
42 YAHOO.log('element required to create Anim instance', 'error', 'Anim');
44 this.init(el, attributes, duration, method);
47 YAHOO.util.Anim.prototype = {
48 /**
49 * Provides a readable name for the Anim instance.
50 * @method toString
51 * @return {String}
53 toString: function() {
54 var el = this.getEl();
55 var id = el.id || el.tagName || el;
56 return ("Anim " + id);
59 patterns: { // cached for performance
60 noNegatives: /width|height|opacity|padding/i, // keep at zero or above
61 offsetAttribute: /^((width|height)|(top|left))$/, // use offsetValue as default
62 defaultUnit: /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
63 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i // IE may return these, so convert these to offset
66 /**
67 * Returns the value computed by the animation's "method".
68 * @method doMethod
69 * @param {String} attr The name of the attribute.
70 * @param {Number} start The value this attribute should start from for this animation.
71 * @param {Number} end The value this attribute should end at for this animation.
72 * @return {Number} The Value to be applied to the attribute.
74 doMethod: function(attr, start, end) {
75 return this.method(this.currentFrame, start, end - start, this.totalFrames);
78 /**
79 * Applies a value to an attribute.
80 * @method setAttribute
81 * @param {String} attr The name of the attribute.
82 * @param {Number} val The value to be applied to the attribute.
83 * @param {String} unit The unit ('px', '%', etc.) of the value.
85 setAttribute: function(attr, val, unit) {
86 if ( this.patterns.noNegatives.test(attr) ) {
87 val = (val > 0) ? val : 0;
90 YAHOO.util.Dom.setStyle(this.getEl(), attr, val + unit);
91 },
93 /**
94 * Returns current value of the attribute.
95 * @method getAttribute
96 * @param {String} attr The name of the attribute.
97 * @return {Number} val The current value of the attribute.
99 getAttribute: function(attr) {
100 var el = this.getEl();
101 var val = YAHOO.util.Dom.getStyle(el, attr);
103 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
104 return parseFloat(val);
107 var a = this.patterns.offsetAttribute.exec(attr) || [];
108 var pos = !!( a[3] ); // top or left
109 var box = !!( a[2] ); // width or height
111 // use offsets for width/height and abs pos top/left
112 if ( box || (YAHOO.util.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
113 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
114 } else { // default to zero for other 'auto'
115 val = 0;
118 return val;
122 * Returns the unit to use when none is supplied.
123 * @method getDefaultUnit
124 * @param {attr} attr The name of the attribute.
125 * @return {String} The default unit to be used.
127 getDefaultUnit: function(attr) {
128 if ( this.patterns.defaultUnit.test(attr) ) {
129 return 'px';
132 return '';
136 * Sets the actual values to be used during the animation. Should only be needed for subclass use.
137 * @method setRuntimeAttribute
138 * @param {Object} attr The attribute object
139 * @private
141 setRuntimeAttribute: function(attr) {
142 var start;
143 var end;
144 var attributes = this.attributes;
146 this.runtimeAttributes[attr] = {};
148 var isset = function(prop) {
149 return (typeof prop !== 'undefined');
152 if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
153 return false; // note return; nothing to animate to
156 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
158 // To beats by, per SMIL 2.1 spec
159 if ( isset(attributes[attr]['to']) ) {
160 end = attributes[attr]['to'];
161 } else if ( isset(attributes[attr]['by']) ) {
162 if (start.constructor == Array) {
163 end = [];
164 for (var i = 0, len = start.length; i < len; ++i) {
165 end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by"
167 } else {
168 end = start + attributes[attr]['by'] * 1;
172 this.runtimeAttributes[attr].start = start;
173 this.runtimeAttributes[attr].end = end;
175 // set units if needed
176 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
177 attributes[attr]['unit'] : this.getDefaultUnit(attr);
178 return true;
182 * Constructor for Anim instance.
183 * @method init
184 * @param {String | HTMLElement} el Reference to the element that will be animated
185 * @param {Object} attributes The attribute(s) to be animated.
186 * Each attribute is an object with at minimum a "to" or "by" member defined.
187 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
188 * All attribute names use camelCase.
189 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
190 * @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)
192 init: function(el, attributes, duration, method) {
194 * Whether or not the animation is running.
195 * @property isAnimated
196 * @private
197 * @type Boolean
199 var isAnimated = false;
202 * A Date object that is created when the animation begins.
203 * @property startTime
204 * @private
205 * @type Date
207 var startTime = null;
210 * The number of frames this animation was able to execute.
211 * @property actualFrames
212 * @private
213 * @type Int
215 var actualFrames = 0;
218 * The element to be animated.
219 * @property el
220 * @private
221 * @type HTMLElement
223 el = YAHOO.util.Dom.get(el);
226 * The collection of attributes to be animated.
227 * Each attribute must have at least a "to" or "by" defined in order to animate.
228 * If "to" is supplied, the animation will end with the attribute at that value.
229 * If "by" is supplied, the animation will end at that value plus its starting value.
230 * If both are supplied, "to" is used, and "by" is ignored.
231 * 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).
232 * @property attributes
233 * @type Object
235 this.attributes = attributes || {};
238 * The length of the animation. Defaults to "1" (second).
239 * @property duration
240 * @type Number
242 this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
245 * The method that will provide values to the attribute(s) during the animation.
246 * Defaults to "YAHOO.util.Easing.easeNone".
247 * @property method
248 * @type Function
250 this.method = method || YAHOO.util.Easing.easeNone;
253 * Whether or not the duration should be treated as seconds.
254 * Defaults to true.
255 * @property useSeconds
256 * @type Boolean
258 this.useSeconds = true; // default to seconds
261 * The location of the current animation on the timeline.
262 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
263 * @property currentFrame
264 * @type Int
266 this.currentFrame = 0;
269 * The total number of frames to be executed.
270 * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
271 * @property totalFrames
272 * @type Int
274 this.totalFrames = YAHOO.util.AnimMgr.fps;
277 * Changes the animated element
278 * @method setEl
280 this.setEl = function(element) {
281 el = YAHOO.util.Dom.get(element);
285 * Returns a reference to the animated element.
286 * @method getEl
287 * @return {HTMLElement}
289 this.getEl = function() { return el; };
292 * Checks whether the element is currently animated.
293 * @method isAnimated
294 * @return {Boolean} current value of isAnimated.
296 this.isAnimated = function() {
297 return isAnimated;
301 * Returns the animation start time.
302 * @method getStartTime
303 * @return {Date} current value of startTime.
305 this.getStartTime = function() {
306 return startTime;
309 this.runtimeAttributes = {};
311 var logger = {};
312 logger.log = function() {YAHOO.log.apply(window, arguments)};
314 logger.log('creating new instance of ' + this);
317 * Starts the animation by registering it with the animation manager.
318 * @method animate
320 this.animate = function() {
321 if ( this.isAnimated() ) {
322 return false;
325 this.currentFrame = 0;
327 this.totalFrames = ( this.useSeconds ) ? Math.ceil(YAHOO.util.AnimMgr.fps * this.duration) : this.duration;
329 if (this.duration === 0 && this.useSeconds) {
330 this.totalFrames = 1; // jump to last frame if no duration
332 YAHOO.util.AnimMgr.registerElement(this);
333 return true;
337 * Stops the animation. Normally called by AnimMgr when animation completes.
338 * @method stop
339 * @param {Boolean} finish (optional) If true, animation will jump to final frame.
341 this.stop = function(finish) {
342 if (finish) {
343 this.currentFrame = this.totalFrames;
344 this._onTween.fire();
346 YAHOO.util.AnimMgr.stop(this);
349 var onStart = function() {
350 this.onStart.fire();
352 this.runtimeAttributes = {};
353 for (var attr in this.attributes) {
354 this.setRuntimeAttribute(attr);
357 isAnimated = true;
358 actualFrames = 0;
359 startTime = new Date();
363 * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
364 * @private
367 var onTween = function() {
368 var data = {
369 duration: new Date() - this.getStartTime(),
370 currentFrame: this.currentFrame
373 data.toString = function() {
374 return (
375 'duration: ' + data.duration +
376 ', currentFrame: ' + data.currentFrame
380 this.onTween.fire(data);
382 var runtimeAttributes = this.runtimeAttributes;
384 for (var attr in runtimeAttributes) {
385 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
388 actualFrames += 1;
391 var onComplete = function() {
392 var actual_duration = (new Date() - startTime) / 1000 ;
394 var data = {
395 duration: actual_duration,
396 frames: actualFrames,
397 fps: actualFrames / actual_duration
400 data.toString = function() {
401 return (
402 'duration: ' + data.duration +
403 ', frames: ' + data.frames +
404 ', fps: ' + data.fps
408 isAnimated = false;
409 actualFrames = 0;
410 this.onComplete.fire(data);
414 * Custom event that fires after onStart, useful in subclassing
415 * @private
417 this._onStart = new YAHOO.util.CustomEvent('_start', this, true);
420 * Custom event that fires when animation begins
421 * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
422 * @event onStart
424 this.onStart = new YAHOO.util.CustomEvent('start', this);
427 * Custom event that fires between each frame
428 * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
429 * @event onTween
431 this.onTween = new YAHOO.util.CustomEvent('tween', this);
434 * Custom event that fires after onTween
435 * @private
437 this._onTween = new YAHOO.util.CustomEvent('_tween', this, true);
440 * Custom event that fires when animation ends
441 * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
442 * @event onComplete
444 this.onComplete = new YAHOO.util.CustomEvent('complete', this);
446 * Custom event that fires after onComplete
447 * @private
449 this._onComplete = new YAHOO.util.CustomEvent('_complete', this, true);
451 this._onStart.subscribe(onStart);
452 this._onTween.subscribe(onTween);
453 this._onComplete.subscribe(onComplete);
458 * Handles animation queueing and threading.
459 * Used by Anim and subclasses.
460 * @class AnimMgr
461 * @namespace YAHOO.util
463 YAHOO.util.AnimMgr = new function() {
464 /**
465 * Reference to the animation Interval.
466 * @property thread
467 * @private
468 * @type Int
470 var thread = null;
472 /**
473 * The current queue of registered animation objects.
474 * @property queue
475 * @private
476 * @type Array
478 var queue = [];
480 /**
481 * The number of active animations.
482 * @property tweenCount
483 * @private
484 * @type Int
486 var tweenCount = 0;
488 /**
489 * Base frame rate (frames per second).
490 * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
491 * @property fps
492 * @type Int
495 this.fps = 1000;
497 /**
498 * Interval delay in milliseconds, defaults to fastest possible.
499 * @property delay
500 * @type Int
503 this.delay = 1;
506 * Adds an animation instance to the animation queue.
507 * All animation instances must be registered in order to animate.
508 * @method registerElement
509 * @param {object} tween The Anim instance to be be registered
511 this.registerElement = function(tween) {
512 queue[queue.length] = tween;
513 tweenCount += 1;
514 tween._onStart.fire();
515 this.start();
519 * removes an animation instance from the animation queue.
520 * All animation instances must be registered in order to animate.
521 * @method unRegister
522 * @param {object} tween The Anim instance to be be registered
523 * @param {Int} index The index of the Anim instance
524 * @private
526 this.unRegister = function(tween, index) {
527 tween._onComplete.fire();
528 index = index || getIndex(tween);
529 if (index == -1) {
530 return false;
533 queue.splice(index, 1);
535 tweenCount -= 1;
536 if (tweenCount <= 0) {
537 this.stop();
540 return true;
544 * Starts the animation thread.
545 * Only one thread can run at a time.
546 * @method start
548 this.start = function() {
549 if (thread === null) {
550 thread = setInterval(this.run, this.delay);
555 * Stops the animation thread or a specific animation instance.
556 * @method stop
557 * @param {object} tween A specific Anim instance to stop (optional)
558 * If no instance given, Manager stops thread and all animations.
560 this.stop = function(tween) {
561 if (!tween) {
562 clearInterval(thread);
564 for (var i = 0, len = queue.length; i < len; ++i) {
565 if ( queue[0].isAnimated() ) {
566 this.unRegister(queue[0], 0);
570 queue = [];
571 thread = null;
572 tweenCount = 0;
574 else {
575 this.unRegister(tween);
580 * Called per Interval to handle each animation frame.
581 * @method run
583 this.run = function() {
584 for (var i = 0, len = queue.length; i < len; ++i) {
585 var tween = queue[i];
586 if ( !tween || !tween.isAnimated() ) { continue; }
588 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
590 tween.currentFrame += 1;
592 if (tween.useSeconds) {
593 correctFrame(tween);
595 tween._onTween.fire();
597 else { YAHOO.util.AnimMgr.stop(tween, i); }
601 var getIndex = function(anim) {
602 for (var i = 0, len = queue.length; i < len; ++i) {
603 if (queue[i] == anim) {
604 return i; // note return;
607 return -1;
611 * On the fly frame correction to keep animation on time.
612 * @method correctFrame
613 * @private
614 * @param {Object} tween The Anim instance being corrected.
616 var correctFrame = function(tween) {
617 var frames = tween.totalFrames;
618 var frame = tween.currentFrame;
619 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
620 var elapsed = (new Date() - tween.getStartTime());
621 var tweak = 0;
623 if (elapsed < tween.duration * 1000) { // check if falling behind
624 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
625 } else { // went over duration, so jump to end
626 tweak = frames - (frame + 1);
628 if (tweak > 0 && isFinite(tweak)) { // adjust if needed
629 if (tween.currentFrame + tweak >= frames) {// dont go past last frame
630 tweak = frames - (frame + 1);
633 tween.currentFrame += tweak;
638 * Used to calculate Bezier splines for any number of control points.
639 * @class Bezier
640 * @namespace YAHOO.util
643 YAHOO.util.Bezier = new function() {
645 * Get the current position of the animated element based on t.
646 * Each point is an array of "x" and "y" values (0 = x, 1 = y)
647 * At least 2 points are required (start and end).
648 * First point is start. Last point is end.
649 * Additional control points are optional.
650 * @method getPosition
651 * @param {Array} points An array containing Bezier points
652 * @param {Number} t A number between 0 and 1 which is the basis for determining current position
653 * @return {Array} An array containing int x and y member data
655 this.getPosition = function(points, t) {
656 var n = points.length;
657 var tmp = [];
659 for (var i = 0; i < n; ++i){
660 tmp[i] = [points[i][0], points[i][1]]; // save input
663 for (var j = 1; j < n; ++j) {
664 for (i = 0; i < n - j; ++i) {
665 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
666 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
670 return [ tmp[0][0], tmp[0][1] ];
674 (function() {
676 * Anim subclass for color transitions.
677 * <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,
678 * [255,255,255], or rgb(255,255,255)</p>
679 * @class ColorAnim
680 * @namespace YAHOO.util
681 * @requires YAHOO.util.Anim
682 * @requires YAHOO.util.AnimMgr
683 * @requires YAHOO.util.Easing
684 * @requires YAHOO.util.Bezier
685 * @requires YAHOO.util.Dom
686 * @requires YAHOO.util.Event
687 * @constructor
688 * @extends YAHOO.util.Anim
689 * @param {HTMLElement | String} el Reference to the element that will be animated
690 * @param {Object} attributes The attribute(s) to be animated.
691 * Each attribute is an object with at minimum a "to" or "by" member defined.
692 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
693 * All attribute names use camelCase.
694 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
695 * @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)
697 YAHOO.util.ColorAnim = function(el, attributes, duration, method) {
698 YAHOO.util.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
701 YAHOO.extend(YAHOO.util.ColorAnim, YAHOO.util.Anim);
703 // shorthand
704 var Y = YAHOO.util;
705 var superclass = Y.ColorAnim.superclass;
706 var proto = Y.ColorAnim.prototype;
708 proto.toString = function() {
709 var el = this.getEl();
710 var id = el.id || el.tagName;
711 return ("ColorAnim " + id);
714 proto.patterns.color = /color$/i;
715 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
716 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
717 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
718 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
721 * Attempts to parse the given string and return a 3-tuple.
722 * @method parseColor
723 * @param {String} s The string to parse.
724 * @return {Array} The 3-tuple of rgb values.
726 proto.parseColor = function(s) {
727 if (s.length == 3) { return s; }
729 var c = this.patterns.hex.exec(s);
730 if (c && c.length == 4) {
731 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
734 c = this.patterns.rgb.exec(s);
735 if (c && c.length == 4) {
736 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
739 c = this.patterns.hex3.exec(s);
740 if (c && c.length == 4) {
741 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
744 return null;
747 proto.getAttribute = function(attr) {
748 var el = this.getEl();
749 if ( this.patterns.color.test(attr) ) {
750 var val = YAHOO.util.Dom.getStyle(el, attr);
752 if (this.patterns.transparent.test(val)) { // bgcolor default
753 var parent = el.parentNode; // try and get from an ancestor
754 val = Y.Dom.getStyle(parent, attr);
756 while (parent && this.patterns.transparent.test(val)) {
757 parent = parent.parentNode;
758 val = Y.Dom.getStyle(parent, attr);
759 if (parent.tagName.toUpperCase() == 'HTML') {
760 val = '#fff';
764 } else {
765 val = superclass.getAttribute.call(this, attr);
768 return val;
771 proto.doMethod = function(attr, start, end) {
772 var val;
774 if ( this.patterns.color.test(attr) ) {
775 val = [];
776 for (var i = 0, len = start.length; i < len; ++i) {
777 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
780 val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
782 else {
783 val = superclass.doMethod.call(this, attr, start, end);
786 return val;
789 proto.setRuntimeAttribute = function(attr) {
790 superclass.setRuntimeAttribute.call(this, attr);
792 if ( this.patterns.color.test(attr) ) {
793 var attributes = this.attributes;
794 var start = this.parseColor(this.runtimeAttributes[attr].start);
795 var end = this.parseColor(this.runtimeAttributes[attr].end);
796 // fix colors if going "by"
797 if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
798 end = this.parseColor(attributes[attr].by);
800 for (var i = 0, len = start.length; i < len; ++i) {
801 end[i] = start[i] + end[i];
805 this.runtimeAttributes[attr].start = start;
806 this.runtimeAttributes[attr].end = end;
809 })();
811 TERMS OF USE - EASING EQUATIONS
812 Open source under the BSD License.
813 Copyright 2001 Robert Penner All rights reserved.
815 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
817 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
818 * 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.
819 * 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.
821 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.
825 * Singleton that determines how an animation proceeds from start to end.
826 * @class Easing
827 * @namespace YAHOO.util
830 YAHOO.util.Easing = {
833 * Uniform speed between points.
834 * @method easeNone
835 * @param {Number} t Time value used to compute current value
836 * @param {Number} b Starting value
837 * @param {Number} c Delta between start and end values
838 * @param {Number} d Total length of animation
839 * @return {Number} The computed value for the current animation frame
841 easeNone: function (t, b, c, d) {
842 return c*t/d + b;
846 * Begins slowly and accelerates towards end. (quadratic)
847 * @method easeIn
848 * @param {Number} t Time value used to compute current value
849 * @param {Number} b Starting value
850 * @param {Number} c Delta between start and end values
851 * @param {Number} d Total length of animation
852 * @return {Number} The computed value for the current animation frame
854 easeIn: function (t, b, c, d) {
855 return c*(t/=d)*t + b;
859 * Begins quickly and decelerates towards end. (quadratic)
860 * @method easeOut
861 * @param {Number} t Time value used to compute current value
862 * @param {Number} b Starting value
863 * @param {Number} c Delta between start and end values
864 * @param {Number} d Total length of animation
865 * @return {Number} The computed value for the current animation frame
867 easeOut: function (t, b, c, d) {
868 return -c *(t/=d)*(t-2) + b;
872 * Begins slowly and decelerates towards end. (quadratic)
873 * @method easeBoth
874 * @param {Number} t Time value used to compute current value
875 * @param {Number} b Starting value
876 * @param {Number} c Delta between start and end values
877 * @param {Number} d Total length of animation
878 * @return {Number} The computed value for the current animation frame
880 easeBoth: function (t, b, c, d) {
881 if ((t/=d/2) < 1) {
882 return c/2*t*t + b;
885 return -c/2 * ((--t)*(t-2) - 1) + b;
889 * Begins slowly and accelerates towards end. (quartic)
890 * @method easeInStrong
891 * @param {Number} t Time value used to compute current value
892 * @param {Number} b Starting value
893 * @param {Number} c Delta between start and end values
894 * @param {Number} d Total length of animation
895 * @return {Number} The computed value for the current animation frame
897 easeInStrong: function (t, b, c, d) {
898 return c*(t/=d)*t*t*t + b;
902 * Begins quickly and decelerates towards end. (quartic)
903 * @method easeOutStrong
904 * @param {Number} t Time value used to compute current value
905 * @param {Number} b Starting value
906 * @param {Number} c Delta between start and end values
907 * @param {Number} d Total length of animation
908 * @return {Number} The computed value for the current animation frame
910 easeOutStrong: function (t, b, c, d) {
911 return -c * ((t=t/d-1)*t*t*t - 1) + b;
915 * Begins slowly and decelerates towards end. (quartic)
916 * @method easeBothStrong
917 * @param {Number} t Time value used to compute current value
918 * @param {Number} b Starting value
919 * @param {Number} c Delta between start and end values
920 * @param {Number} d Total length of animation
921 * @return {Number} The computed value for the current animation frame
923 easeBothStrong: function (t, b, c, d) {
924 if ((t/=d/2) < 1) {
925 return c/2*t*t*t*t + b;
928 return -c/2 * ((t-=2)*t*t*t - 2) + b;
932 * Snap in elastic effect.
933 * @method elasticIn
934 * @param {Number} t Time value used to compute current value
935 * @param {Number} b Starting value
936 * @param {Number} c Delta between start and end values
937 * @param {Number} d Total length of animation
938 * @param {Number} a Amplitude (optional)
939 * @param {Number} p Period (optional)
940 * @return {Number} The computed value for the current animation frame
943 elasticIn: function (t, b, c, d, a, p) {
944 if (t == 0) {
945 return b;
947 if ( (t /= d) == 1 ) {
948 return b+c;
950 if (!p) {
951 p=d*.3;
954 if (!a || a < Math.abs(c)) {
955 a = c;
956 var s = p/4;
958 else {
959 var s = p/(2*Math.PI) * Math.asin (c/a);
962 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
966 * Snap out elastic effect.
967 * @method elasticOut
968 * @param {Number} t Time value used to compute current value
969 * @param {Number} b Starting value
970 * @param {Number} c Delta between start and end values
971 * @param {Number} d Total length of animation
972 * @param {Number} a Amplitude (optional)
973 * @param {Number} p Period (optional)
974 * @return {Number} The computed value for the current animation frame
976 elasticOut: function (t, b, c, d, a, p) {
977 if (t == 0) {
978 return b;
980 if ( (t /= d) == 1 ) {
981 return b+c;
983 if (!p) {
984 p=d*.3;
987 if (!a || a < Math.abs(c)) {
988 a = c;
989 var s = p / 4;
991 else {
992 var s = p/(2*Math.PI) * Math.asin (c/a);
995 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
999 * Snap both elastic effect.
1000 * @method elasticBoth
1001 * @param {Number} t Time value used to compute current value
1002 * @param {Number} b Starting value
1003 * @param {Number} c Delta between start and end values
1004 * @param {Number} d Total length of animation
1005 * @param {Number} a Amplitude (optional)
1006 * @param {Number} p Period (optional)
1007 * @return {Number} The computed value for the current animation frame
1009 elasticBoth: function (t, b, c, d, a, p) {
1010 if (t == 0) {
1011 return b;
1014 if ( (t /= d/2) == 2 ) {
1015 return b+c;
1018 if (!p) {
1019 p = d*(.3*1.5);
1022 if ( !a || a < Math.abs(c) ) {
1023 a = c;
1024 var s = p/4;
1026 else {
1027 var s = p/(2*Math.PI) * Math.asin (c/a);
1030 if (t < 1) {
1031 return -.5*(a*Math.pow(2,10*(t-=1)) *
1032 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1034 return a*Math.pow(2,-10*(t-=1)) *
1035 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1040 * Backtracks slightly, then reverses direction and moves to end.
1041 * @method backIn
1042 * @param {Number} t Time value used to compute current value
1043 * @param {Number} b Starting value
1044 * @param {Number} c Delta between start and end values
1045 * @param {Number} d Total length of animation
1046 * @param {Number} s Overshoot (optional)
1047 * @return {Number} The computed value for the current animation frame
1049 backIn: function (t, b, c, d, s) {
1050 if (typeof s == 'undefined') {
1051 s = 1.70158;
1053 return c*(t/=d)*t*((s+1)*t - s) + b;
1057 * Overshoots end, then reverses and comes back to end.
1058 * @method backOut
1059 * @param {Number} t Time value used to compute current value
1060 * @param {Number} b Starting value
1061 * @param {Number} c Delta between start and end values
1062 * @param {Number} d Total length of animation
1063 * @param {Number} s Overshoot (optional)
1064 * @return {Number} The computed value for the current animation frame
1066 backOut: function (t, b, c, d, s) {
1067 if (typeof s == 'undefined') {
1068 s = 1.70158;
1070 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1074 * Backtracks slightly, then reverses direction, overshoots end,
1075 * then reverses and comes back to end.
1076 * @method backBoth
1077 * @param {Number} t Time value used to compute current value
1078 * @param {Number} b Starting value
1079 * @param {Number} c Delta between start and end values
1080 * @param {Number} d Total length of animation
1081 * @param {Number} s Overshoot (optional)
1082 * @return {Number} The computed value for the current animation frame
1084 backBoth: function (t, b, c, d, s) {
1085 if (typeof s == 'undefined') {
1086 s = 1.70158;
1089 if ((t /= d/2 ) < 1) {
1090 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1092 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1096 * Bounce off of start.
1097 * @method bounceIn
1098 * @param {Number} t Time value used to compute current value
1099 * @param {Number} b Starting value
1100 * @param {Number} c Delta between start and end values
1101 * @param {Number} d Total length of animation
1102 * @return {Number} The computed value for the current animation frame
1104 bounceIn: function (t, b, c, d) {
1105 return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1109 * Bounces off end.
1110 * @method bounceOut
1111 * @param {Number} t Time value used to compute current value
1112 * @param {Number} b Starting value
1113 * @param {Number} c Delta between start and end values
1114 * @param {Number} d Total length of animation
1115 * @return {Number} The computed value for the current animation frame
1117 bounceOut: function (t, b, c, d) {
1118 if ((t/=d) < (1/2.75)) {
1119 return c*(7.5625*t*t) + b;
1120 } else if (t < (2/2.75)) {
1121 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1122 } else if (t < (2.5/2.75)) {
1123 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1125 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1129 * Bounces off start and end.
1130 * @method bounceBoth
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 bounceBoth: function (t, b, c, d) {
1138 if (t < d/2) {
1139 return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1141 return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1145 (function() {
1147 * Anim subclass for moving elements along a path defined by the "points"
1148 * member of "attributes". All "points" are arrays with x, y coordinates.
1149 * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1150 * @class Motion
1151 * @namespace YAHOO.util
1152 * @requires YAHOO.util.Anim
1153 * @requires YAHOO.util.AnimMgr
1154 * @requires YAHOO.util.Easing
1155 * @requires YAHOO.util.Bezier
1156 * @requires YAHOO.util.Dom
1157 * @requires YAHOO.util.Event
1158 * @requires YAHOO.util.CustomEvent
1159 * @constructor
1160 * @extends YAHOO.util.Anim
1161 * @param {String | HTMLElement} el Reference to the element that will be animated
1162 * @param {Object} attributes The attribute(s) to be animated.
1163 * Each attribute is an object with at minimum a "to" or "by" member defined.
1164 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1165 * All attribute names use camelCase.
1166 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1167 * @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)
1169 YAHOO.util.Motion = function(el, attributes, duration, method) {
1170 if (el) { // dont break existing subclasses not using YAHOO.extend
1171 YAHOO.util.Motion.superclass.constructor.call(this, el, attributes, duration, method);
1175 YAHOO.extend(YAHOO.util.Motion, YAHOO.util.ColorAnim);
1177 // shorthand
1178 var Y = YAHOO.util;
1179 var superclass = Y.Motion.superclass;
1180 var proto = Y.Motion.prototype;
1182 proto.toString = function() {
1183 var el = this.getEl();
1184 var id = el.id || el.tagName;
1185 return ("Motion " + id);
1188 proto.patterns.points = /^points$/i;
1190 proto.setAttribute = function(attr, val, unit) {
1191 if ( this.patterns.points.test(attr) ) {
1192 unit = unit || 'px';
1193 superclass.setAttribute.call(this, 'left', val[0], unit);
1194 superclass.setAttribute.call(this, 'top', val[1], unit);
1195 } else {
1196 superclass.setAttribute.call(this, attr, val, unit);
1200 proto.getAttribute = function(attr) {
1201 if ( this.patterns.points.test(attr) ) {
1202 var val = [
1203 superclass.getAttribute.call(this, 'left'),
1204 superclass.getAttribute.call(this, 'top')
1206 } else {
1207 val = superclass.getAttribute.call(this, attr);
1210 return val;
1213 proto.doMethod = function(attr, start, end) {
1214 var val = null;
1216 if ( this.patterns.points.test(attr) ) {
1217 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
1218 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1219 } else {
1220 val = superclass.doMethod.call(this, attr, start, end);
1222 return val;
1225 proto.setRuntimeAttribute = function(attr) {
1226 if ( this.patterns.points.test(attr) ) {
1227 var el = this.getEl();
1228 var attributes = this.attributes;
1229 var start;
1230 var control = attributes['points']['control'] || [];
1231 var end;
1232 var i, len;
1234 if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1235 control = [control];
1236 } else { // break reference to attributes.points.control
1237 var tmp = [];
1238 for (i = 0, len = control.length; i< len; ++i) {
1239 tmp[i] = control[i];
1241 control = tmp;
1244 if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1245 Y.Dom.setStyle(el, 'position', 'relative');
1248 if ( isset(attributes['points']['from']) ) {
1249 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1251 else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1253 start = this.getAttribute('points'); // get actual top & left
1255 // TO beats BY, per SMIL 2.1 spec
1256 if ( isset(attributes['points']['to']) ) {
1257 end = translateValues.call(this, attributes['points']['to'], start);
1259 var pageXY = Y.Dom.getXY(this.getEl());
1260 for (i = 0, len = control.length; i < len; ++i) {
1261 control[i] = translateValues.call(this, control[i], start);
1265 } else if ( isset(attributes['points']['by']) ) {
1266 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1268 for (i = 0, len = control.length; i < len; ++i) {
1269 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1273 this.runtimeAttributes[attr] = [start];
1275 if (control.length > 0) {
1276 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
1279 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1281 else {
1282 superclass.setRuntimeAttribute.call(this, attr);
1286 var translateValues = function(val, start) {
1287 var pageXY = Y.Dom.getXY(this.getEl());
1288 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1290 return val;
1293 var isset = function(prop) {
1294 return (typeof prop !== 'undefined');
1296 })();
1297 (function() {
1299 * Anim subclass for scrolling elements to a position defined by the "scroll"
1300 * member of "attributes". All "scroll" members are arrays with x, y scroll positions.
1301 * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1302 * @class Scroll
1303 * @namespace YAHOO.util
1304 * @requires YAHOO.util.Anim
1305 * @requires YAHOO.util.AnimMgr
1306 * @requires YAHOO.util.Easing
1307 * @requires YAHOO.util.Bezier
1308 * @requires YAHOO.util.Dom
1309 * @requires YAHOO.util.Event
1310 * @requires YAHOO.util.CustomEvent
1311 * @extends YAHOO.util.Anim
1312 * @constructor
1313 * @param {String or HTMLElement} el Reference to the element that will be animated
1314 * @param {Object} attributes The attribute(s) to be animated.
1315 * Each attribute is an object with at minimum a "to" or "by" member defined.
1316 * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
1317 * All attribute names use camelCase.
1318 * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1319 * @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)
1321 YAHOO.util.Scroll = function(el, attributes, duration, method) {
1322 if (el) { // dont break existing subclasses not using YAHOO.extend
1323 YAHOO.util.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1327 YAHOO.extend(YAHOO.util.Scroll, YAHOO.util.ColorAnim);
1329 // shorthand
1330 var Y = YAHOO.util;
1331 var superclass = Y.Scroll.superclass;
1332 var proto = Y.Scroll.prototype;
1334 proto.toString = function() {
1335 var el = this.getEl();
1336 var id = el.id || el.tagName;
1337 return ("Scroll " + id);
1340 proto.doMethod = function(attr, start, end) {
1341 var val = null;
1343 if (attr == 'scroll') {
1344 val = [
1345 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1346 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1349 } else {
1350 val = superclass.doMethod.call(this, attr, start, end);
1352 return val;
1355 proto.getAttribute = function(attr) {
1356 var val = null;
1357 var el = this.getEl();
1359 if (attr == 'scroll') {
1360 val = [ el.scrollLeft, el.scrollTop ];
1361 } else {
1362 val = superclass.getAttribute.call(this, attr);
1365 return val;
1368 proto.setAttribute = function(attr, val, unit) {
1369 var el = this.getEl();
1371 if (attr == 'scroll') {
1372 el.scrollLeft = val[0];
1373 el.scrollTop = val[1];
1374 } else {
1375 superclass.setAttribute.call(this, attr, val, unit);
1378 })();
1379 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.3.0", build: "442"});