Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / lib / yui / animation / animation-debug.js
blobff5c4f90c405aaa9b866a04dfc26ac365b4b0a0c
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
21  */
23 /**
24  *
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)
42  */
44 var Anim = function(el, attributes, duration, method) {
45     if (!el) {
46         YAHOO.log('element required to create Anim instance', 'error', 'Anim');
47     }
48     this.init(el, attributes, duration, method); 
51 Anim.NAME = 'Anim';
53 Anim.prototype = {
54     /**
55      * Provides a readable name for the Anim instance.
56      * @method toString
57      * @return {String}
58      */
59     toString: function() {
60         var el = this.getEl() || {};
61         var id = el.id || el.tagName;
62         return (this.constructor.NAME + ': ' + id);
63     },
64     
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
70     },
71     
72     /**
73      * Returns the value computed by the animation's "method".
74      * @method doMethod
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.
79      */
80     doMethod: function(attr, start, end) {
81         return this.method(this.currentFrame, start, end - start, this.totalFrames);
82     },
83     
84     /**
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.
90      */
91     setAttribute: function(attr, val, unit) {
92         if ( this.patterns.noNegatives.test(attr) ) {
93             val = (val > 0) ? val : 0;
94         }
96         Y.Dom.setStyle(this.getEl(), attr, val + unit);
97     },                        
98     
99     /**
100      * Returns current value of the attribute.
101      * @method getAttribute
102      * @param {String} attr The name of the attribute.
103      * @return {Number} val The current value of the attribute.
104      */
105     getAttribute: function(attr) {
106         var el = this.getEl();
107         var val = Y.Dom.getStyle(el, attr);
109         if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
110             return parseFloat(val);
111         }
112         
113         var a = this.patterns.offsetAttribute.exec(attr) || [];
114         var pos = !!( a[3] ); // top or left
115         var box = !!( a[2] ); // width or height
116         
117         // use offsets for width/height and abs pos top/left
118         if ( box || (Y.Dom.getStyle(el, 'position') == 'absolute' && pos) ) {
119             val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
120         } else { // default to zero for other 'auto'
121             val = 0;
122         }
124         return val;
125     },
126     
127     /**
128      * Returns the unit to use when none is supplied.
129      * @method getDefaultUnit
130      * @param {attr} attr The name of the attribute.
131      * @return {String} The default unit to be used.
132      */
133     getDefaultUnit: function(attr) {
134          if ( this.patterns.defaultUnit.test(attr) ) {
135             return 'px';
136          }
137          
138          return '';
139     },
140         
141     /**
142      * Sets the actual values to be used during the animation.  Should only be needed for subclass use.
143      * @method setRuntimeAttribute
144      * @param {Object} attr The attribute object
145      * @private 
146      */
147     setRuntimeAttribute: function(attr) {
148         var start;
149         var end;
150         var attributes = this.attributes;
152         this.runtimeAttributes[attr] = {};
153         
154         var isset = function(prop) {
155             return (typeof prop !== 'undefined');
156         };
157         
158         if ( !isset(attributes[attr]['to']) && !isset(attributes[attr]['by']) ) {
159             return false; // note return; nothing to animate to
160         }
161         
162         start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
164         // To beats by, per SMIL 2.1 spec
165         if ( isset(attributes[attr]['to']) ) {
166             end = attributes[attr]['to'];
167         } else if ( isset(attributes[attr]['by']) ) {
168             if (start.constructor == Array) {
169                 end = [];
170                 for (var i = 0, len = start.length; i < len; ++i) {
171                     end[i] = start[i] + attributes[attr]['by'][i] * 1; // times 1 to cast "by" 
172                 }
173             } else {
174                 end = start + attributes[attr]['by'] * 1;
175             }
176         }
177         
178         this.runtimeAttributes[attr].start = start;
179         this.runtimeAttributes[attr].end = end;
181         // set units if needed
182         this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ?
183                 attributes[attr]['unit'] : this.getDefaultUnit(attr);
184         return true;
185     },
187     /**
188      * Constructor for Anim instance.
189      * @method init
190      * @param {String | HTMLElement} el Reference to the element that will be animated
191      * @param {Object} attributes The attribute(s) to be animated.  
192      * Each attribute is an object with at minimum a "to" or "by" member defined.  
193      * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
194      * All attribute names use camelCase.
195      * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
196      * @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      */ 
198     init: function(el, attributes, duration, method) {
199         /**
200          * Whether or not the animation is running.
201          * @property isAnimated
202          * @private
203          * @type Boolean
204          */
205         var isAnimated = false;
206         
207         /**
208          * A Date object that is created when the animation begins.
209          * @property startTime
210          * @private
211          * @type Date
212          */
213         var startTime = null;
214         
215         /**
216          * The number of frames this animation was able to execute.
217          * @property actualFrames
218          * @private
219          * @type Int
220          */
221         var actualFrames = 0; 
223         /**
224          * The element to be animated.
225          * @property el
226          * @private
227          * @type HTMLElement
228          */
229         el = Y.Dom.get(el);
230         
231         /**
232          * The collection of attributes to be animated.  
233          * Each attribute must have at least a "to" or "by" defined in order to animate.  
234          * If "to" is supplied, the animation will end with the attribute at that value.  
235          * If "by" is supplied, the animation will end at that value plus its starting value. 
236          * If both are supplied, "to" is used, and "by" is ignored. 
237          * 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).
238          * @property attributes
239          * @type Object
240          */
241         this.attributes = attributes || {};
242         
243         /**
244          * The length of the animation.  Defaults to "1" (second).
245          * @property duration
246          * @type Number
247          */
248         this.duration = !YAHOO.lang.isUndefined(duration) ? duration : 1;
249         
250         /**
251          * The method that will provide values to the attribute(s) during the animation. 
252          * Defaults to "YAHOO.util.Easing.easeNone".
253          * @property method
254          * @type Function
255          */
256         this.method = method || Y.Easing.easeNone;
258         /**
259          * Whether or not the duration should be treated as seconds.
260          * Defaults to true.
261          * @property useSeconds
262          * @type Boolean
263          */
264         this.useSeconds = true; // default to seconds
265         
266         /**
267          * The location of the current animation on the timeline.
268          * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
269          * @property currentFrame
270          * @type Int
271          */
272         this.currentFrame = 0;
273         
274         /**
275          * The total number of frames to be executed.
276          * In time-based animations, this is used by AnimMgr to ensure the animation finishes on time.
277          * @property totalFrames
278          * @type Int
279          */
280         this.totalFrames = Y.AnimMgr.fps;
281         
282         /**
283          * Changes the animated element
284          * @method setEl
285          */
286         this.setEl = function(element) {
287             el = Y.Dom.get(element);
288         };
289         
290         /**
291          * Returns a reference to the animated element.
292          * @method getEl
293          * @return {HTMLElement}
294          */
295         this.getEl = function() { return el; };
296         
297         /**
298          * Checks whether the element is currently animated.
299          * @method isAnimated
300          * @return {Boolean} current value of isAnimated.     
301          */
302         this.isAnimated = function() {
303             return isAnimated;
304         };
305         
306         /**
307          * Returns the animation start time.
308          * @method getStartTime
309          * @return {Date} current value of startTime.      
310          */
311         this.getStartTime = function() {
312             return startTime;
313         };        
314         
315         this.runtimeAttributes = {};
316         
317         var logger = {};
318         logger.log = function() {YAHOO.log.apply(window, arguments)};
319         
320         logger.log('creating new instance of ' + this);
321         
322         /**
323          * Starts the animation by registering it with the animation manager. 
324          * @method animate  
325          */
326         this.animate = function() {
327             if ( this.isAnimated() ) {
328                 return false;
329             }
330             
331             this.currentFrame = 0;
332             
333             this.totalFrames = ( this.useSeconds ) ? Math.ceil(Y.AnimMgr.fps * this.duration) : this.duration;
334     
335             if (this.duration === 0 && this.useSeconds) { // jump to last frame if zero second duration 
336                 this.totalFrames = 1; 
337             }
338             Y.AnimMgr.registerElement(this);
339             return true;
340         };
341           
342         /**
343          * Stops the animation.  Normally called by AnimMgr when animation completes.
344          * @method stop
345          * @param {Boolean} finish (optional) If true, animation will jump to final frame.
346          */ 
347         this.stop = function(finish) {
348             if (!this.isAnimated()) { // nothing to stop
349                 return false;
350             }
352             if (finish) {
353                  this.currentFrame = this.totalFrames;
354                  this._onTween.fire();
355             }
356             Y.AnimMgr.stop(this);
357         };
358         
359         var onStart = function() {            
360             this.onStart.fire();
361             
362             this.runtimeAttributes = {};
363             for (var attr in this.attributes) {
364                 this.setRuntimeAttribute(attr);
365             }
366             
367             isAnimated = true;
368             actualFrames = 0;
369             startTime = new Date(); 
370         };
371         
372         /**
373          * Feeds the starting and ending values for each animated attribute to doMethod once per frame, then applies the resulting value to the attribute(s).
374          * @private
375          */
376          
377         var onTween = function() {
378             var data = {
379                 duration: new Date() - this.getStartTime(),
380                 currentFrame: this.currentFrame
381             };
382             
383             data.toString = function() {
384                 return (
385                     'duration: ' + data.duration +
386                     ', currentFrame: ' + data.currentFrame
387                 );
388             };
389             
390             this.onTween.fire(data);
391             
392             var runtimeAttributes = this.runtimeAttributes;
393             
394             for (var attr in runtimeAttributes) {
395                 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit); 
396             }
397             
398             actualFrames += 1;
399         };
400         
401         var onComplete = function() {
402             var actual_duration = (new Date() - startTime) / 1000 ;
403             
404             var data = {
405                 duration: actual_duration,
406                 frames: actualFrames,
407                 fps: actualFrames / actual_duration
408             };
409             
410             data.toString = function() {
411                 return (
412                     'duration: ' + data.duration +
413                     ', frames: ' + data.frames +
414                     ', fps: ' + data.fps
415                 );
416             };
417             
418             isAnimated = false;
419             actualFrames = 0;
420             this.onComplete.fire(data);
421         };
422         
423         /**
424          * Custom event that fires after onStart, useful in subclassing
425          * @private
426          */    
427         this._onStart = new Y.CustomEvent('_start', this, true);
429         /**
430          * Custom event that fires when animation begins
431          * Listen via subscribe method (e.g. myAnim.onStart.subscribe(someFunction)
432          * @event onStart
433          */    
434         this.onStart = new Y.CustomEvent('start', this);
435         
436         /**
437          * Custom event that fires between each frame
438          * Listen via subscribe method (e.g. myAnim.onTween.subscribe(someFunction)
439          * @event onTween
440          */
441         this.onTween = new Y.CustomEvent('tween', this);
442         
443         /**
444          * Custom event that fires after onTween
445          * @private
446          */
447         this._onTween = new Y.CustomEvent('_tween', this, true);
448         
449         /**
450          * Custom event that fires when animation ends
451          * Listen via subscribe method (e.g. myAnim.onComplete.subscribe(someFunction)
452          * @event onComplete
453          */
454         this.onComplete = new Y.CustomEvent('complete', this);
455         /**
456          * Custom event that fires after onComplete
457          * @private
458          */
459         this._onComplete = new Y.CustomEvent('_complete', this, true);
461         this._onStart.subscribe(onStart);
462         this._onTween.subscribe(onTween);
463         this._onComplete.subscribe(onComplete);
464     }
467     Y.Anim = Anim;
468 })();
470  * Handles animation queueing and threading.
471  * Used by Anim and subclasses.
472  * @class AnimMgr
473  * @namespace YAHOO.util
474  */
475 YAHOO.util.AnimMgr = new function() {
476     /** 
477      * Reference to the animation Interval.
478      * @property thread
479      * @private
480      * @type Int
481      */
482     var thread = null;
483     
484     /** 
485      * The current queue of registered animation objects.
486      * @property queue
487      * @private
488      * @type Array
489      */    
490     var queue = [];
492     /** 
493      * The number of active animations.
494      * @property tweenCount
495      * @private
496      * @type Int
497      */        
498     var tweenCount = 0;
500     /** 
501      * Base frame rate (frames per second). 
502      * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
503      * @property fps
504      * @type Int
505      * 
506      */
507     this.fps = 1000;
509     /** 
510      * Interval delay in milliseconds, defaults to fastest possible.
511      * @property delay
512      * @type Int
513      * 
514      */
515     this.delay = 1;
517     /**
518      * Adds an animation instance to the animation queue.
519      * All animation instances must be registered in order to animate.
520      * @method registerElement
521      * @param {object} tween The Anim instance to be be registered
522      */
523     this.registerElement = function(tween) {
524         queue[queue.length] = tween;
525         tweenCount += 1;
526         tween._onStart.fire();
527         this.start();
528     };
529     
530     /**
531      * removes an animation instance from the animation queue.
532      * All animation instances must be registered in order to animate.
533      * @method unRegister
534      * @param {object} tween The Anim instance to be be registered
535      * @param {Int} index The index of the Anim instance
536      * @private
537      */
538     this.unRegister = function(tween, index) {
539         index = index || getIndex(tween);
540         if (!tween.isAnimated() || index == -1) {
541             return false;
542         }
543         
544         tween._onComplete.fire();
545         queue.splice(index, 1);
547         tweenCount -= 1;
548         if (tweenCount <= 0) {
549             this.stop();
550         }
552         return true;
553     };
554     
555     /**
556      * Starts the animation thread.
557         * Only one thread can run at a time.
558      * @method start
559      */    
560     this.start = function() {
561         if (thread === null) {
562             thread = setInterval(this.run, this.delay);
563         }
564     };
566     /**
567      * Stops the animation thread or a specific animation instance.
568      * @method stop
569      * @param {object} tween A specific Anim instance to stop (optional)
570      * If no instance given, Manager stops thread and all animations.
571      */    
572     this.stop = function(tween) {
573         if (!tween) {
574             clearInterval(thread);
575             
576             for (var i = 0, len = queue.length; i < len; ++i) {
577                 this.unRegister(queue[0], 0);  
578             }
580             queue = [];
581             thread = null;
582             tweenCount = 0;
583         }
584         else {
585             this.unRegister(tween);
586         }
587     };
588     
589     /**
590      * Called per Interval to handle each animation frame.
591      * @method run
592      */    
593     this.run = function() {
594         for (var i = 0, len = queue.length; i < len; ++i) {
595             var tween = queue[i];
596             if ( !tween || !tween.isAnimated() ) { continue; }
598             if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
599             {
600                 tween.currentFrame += 1;
601                 
602                 if (tween.useSeconds) {
603                     correctFrame(tween);
604                 }
605                 tween._onTween.fire();          
606             }
607             else { YAHOO.util.AnimMgr.stop(tween, i); }
608         }
609     };
610     
611     var getIndex = function(anim) {
612         for (var i = 0, len = queue.length; i < len; ++i) {
613             if (queue[i] == anim) {
614                 return i; // note return;
615             }
616         }
617         return -1;
618     };
619     
620     /**
621      * On the fly frame correction to keep animation on time.
622      * @method correctFrame
623      * @private
624      * @param {Object} tween The Anim instance being corrected.
625      */
626     var correctFrame = function(tween) {
627         var frames = tween.totalFrames;
628         var frame = tween.currentFrame;
629         var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
630         var elapsed = (new Date() - tween.getStartTime());
631         var tweak = 0;
632         
633         if (elapsed < tween.duration * 1000) { // check if falling behind
634             tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
635         } else { // went over duration, so jump to end
636             tweak = frames - (frame + 1); 
637         }
638         if (tweak > 0 && isFinite(tweak)) { // adjust if needed
639             if (tween.currentFrame + tweak >= frames) {// dont go past last frame
640                 tweak = frames - (frame + 1);
641             }
642             
643             tween.currentFrame += tweak;      
644         }
645     };
648  * Used to calculate Bezier splines for any number of control points.
649  * @class Bezier
650  * @namespace YAHOO.util
652  */
653 YAHOO.util.Bezier = new function() {
654     /**
655      * Get the current position of the animated element based on t.
656      * Each point is an array of "x" and "y" values (0 = x, 1 = y)
657      * At least 2 points are required (start and end).
658      * First point is start. Last point is end.
659      * Additional control points are optional.     
660      * @method getPosition
661      * @param {Array} points An array containing Bezier points
662      * @param {Number} t A number between 0 and 1 which is the basis for determining current position
663      * @return {Array} An array containing int x and y member data
664      */
665     this.getPosition = function(points, t) {  
666         var n = points.length;
667         var tmp = [];
669         for (var i = 0; i < n; ++i){
670             tmp[i] = [points[i][0], points[i][1]]; // save input
671         }
672         
673         for (var j = 1; j < n; ++j) {
674             for (i = 0; i < n - j; ++i) {
675                 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
676                 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; 
677             }
678         }
679     
680         return [ tmp[0][0], tmp[0][1] ]; 
681     
682     };
684 (function() {
686  * Anim subclass for color transitions.
687  * <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, 
688  * [255,255,255], or rgb(255,255,255)</p>
689  * @class ColorAnim
690  * @namespace YAHOO.util
691  * @requires YAHOO.util.Anim
692  * @requires YAHOO.util.AnimMgr
693  * @requires YAHOO.util.Easing
694  * @requires YAHOO.util.Bezier
695  * @requires YAHOO.util.Dom
696  * @requires YAHOO.util.Event
697  * @constructor
698  * @extends YAHOO.util.Anim
699  * @param {HTMLElement | String} el Reference to the element that will be animated
700  * @param {Object} attributes The attribute(s) to be animated.
701  * Each attribute is an object with at minimum a "to" or "by" member defined.
702  * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").
703  * All attribute names use camelCase.
704  * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
705  * @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)
706  */
707     var ColorAnim = function(el, attributes, duration,  method) {
708         ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
709     };
710     
711     ColorAnim.NAME = 'ColorAnim';
713     // shorthand
714     var Y = YAHOO.util;
715     YAHOO.extend(ColorAnim, Y.Anim);
717     var superclass = ColorAnim.superclass;
718     var proto = ColorAnim.prototype;
719     
720     proto.patterns.color = /color$/i;
721     proto.patterns.rgb            = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
722     proto.patterns.hex            = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
723     proto.patterns.hex3          = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
724     proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/; // need rgba for safari
725     
726     /**
727      * Attempts to parse the given string and return a 3-tuple.
728      * @method parseColor
729      * @param {String} s The string to parse.
730      * @return {Array} The 3-tuple of rgb values.
731      */
732     proto.parseColor = function(s) {
733         if (s.length == 3) { return s; }
734     
735         var c = this.patterns.hex.exec(s);
736         if (c && c.length == 4) {
737             return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
738         }
739     
740         c = this.patterns.rgb.exec(s);
741         if (c && c.length == 4) {
742             return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
743         }
744     
745         c = this.patterns.hex3.exec(s);
746         if (c && c.length == 4) {
747             return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
748         }
749         
750         return null;
751     };
753     proto.getAttribute = function(attr) {
754         var el = this.getEl();
755         if (  this.patterns.color.test(attr) ) {
756             var val = YAHOO.util.Dom.getStyle(el, attr);
757             
758             if (this.patterns.transparent.test(val)) { // bgcolor default
759                 var parent = el.parentNode; // try and get from an ancestor
760                 val = Y.Dom.getStyle(parent, attr);
761             
762                 while (parent && this.patterns.transparent.test(val)) {
763                     parent = parent.parentNode;
764                     val = Y.Dom.getStyle(parent, attr);
765                     if (parent.tagName.toUpperCase() == 'HTML') {
766                         val = '#fff';
767                     }
768                 }
769             }
770         } else {
771             val = superclass.getAttribute.call(this, attr);
772         }
774         return val;
775     };
776     
777     proto.doMethod = function(attr, start, end) {
778         var val;
779     
780         if ( this.patterns.color.test(attr) ) {
781             val = [];
782             for (var i = 0, len = start.length; i < len; ++i) {
783                 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
784             }
785             
786             val = 'rgb('+Math.floor(val[0])+','+Math.floor(val[1])+','+Math.floor(val[2])+')';
787         }
788         else {
789             val = superclass.doMethod.call(this, attr, start, end);
790         }
792         return val;
793     };
795     proto.setRuntimeAttribute = function(attr) {
796         superclass.setRuntimeAttribute.call(this, attr);
797         
798         if ( this.patterns.color.test(attr) ) {
799             var attributes = this.attributes;
800             var start = this.parseColor(this.runtimeAttributes[attr].start);
801             var end = this.parseColor(this.runtimeAttributes[attr].end);
802             // fix colors if going "by"
803             if ( typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined' ) {
804                 end = this.parseColor(attributes[attr].by);
805             
806                 for (var i = 0, len = start.length; i < len; ++i) {
807                     end[i] = start[i] + end[i];
808                 }
809             }
810             
811             this.runtimeAttributes[attr].start = start;
812             this.runtimeAttributes[attr].end = end;
813         }
814     };
816     Y.ColorAnim = ColorAnim;
817 })();
819 TERMS OF USE - EASING EQUATIONS
820 Open source under the BSD License.
821 Copyright 2001 Robert Penner All rights reserved.
823 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
825  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
826  * 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.
827  * 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.
829 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.
833  * Singleton that determines how an animation proceeds from start to end.
834  * @class Easing
835  * @namespace YAHOO.util
838 YAHOO.util.Easing = {
840     /**
841      * Uniform speed between points.
842      * @method easeNone
843      * @param {Number} t Time value used to compute current value
844      * @param {Number} b Starting value
845      * @param {Number} c Delta between start and end values
846      * @param {Number} d Total length of animation
847      * @return {Number} The computed value for the current animation frame
848      */
849     easeNone: function (t, b, c, d) {
850         return c*t/d + b;
851     },
852     
853     /**
854      * Begins slowly and accelerates towards end. (quadratic)
855      * @method easeIn
856      * @param {Number} t Time value used to compute current value
857      * @param {Number} b Starting value
858      * @param {Number} c Delta between start and end values
859      * @param {Number} d Total length of animation
860      * @return {Number} The computed value for the current animation frame
861      */
862     easeIn: function (t, b, c, d) {
863         return c*(t/=d)*t + b;
864     },
866     /**
867      * Begins quickly and decelerates towards end.  (quadratic)
868      * @method easeOut
869      * @param {Number} t Time value used to compute current value
870      * @param {Number} b Starting value
871      * @param {Number} c Delta between start and end values
872      * @param {Number} d Total length of animation
873      * @return {Number} The computed value for the current animation frame
874      */
875     easeOut: function (t, b, c, d) {
876         return -c *(t/=d)*(t-2) + b;
877     },
878     
879     /**
880      * Begins slowly and decelerates towards end. (quadratic)
881      * @method easeBoth
882      * @param {Number} t Time value used to compute current value
883      * @param {Number} b Starting value
884      * @param {Number} c Delta between start and end values
885      * @param {Number} d Total length of animation
886      * @return {Number} The computed value for the current animation frame
887      */
888     easeBoth: function (t, b, c, d) {
889         if ((t/=d/2) < 1) {
890             return c/2*t*t + b;
891         }
892         
893         return -c/2 * ((--t)*(t-2) - 1) + b;
894     },
895     
896     /**
897      * Begins slowly and accelerates towards end. (quartic)
898      * @method easeInStrong
899      * @param {Number} t Time value used to compute current value
900      * @param {Number} b Starting value
901      * @param {Number} c Delta between start and end values
902      * @param {Number} d Total length of animation
903      * @return {Number} The computed value for the current animation frame
904      */
905     easeInStrong: function (t, b, c, d) {
906         return c*(t/=d)*t*t*t + b;
907     },
908     
909     /**
910      * Begins quickly and decelerates towards end.  (quartic)
911      * @method easeOutStrong
912      * @param {Number} t Time value used to compute current value
913      * @param {Number} b Starting value
914      * @param {Number} c Delta between start and end values
915      * @param {Number} d Total length of animation
916      * @return {Number} The computed value for the current animation frame
917      */
918     easeOutStrong: function (t, b, c, d) {
919         return -c * ((t=t/d-1)*t*t*t - 1) + b;
920     },
921     
922     /**
923      * Begins slowly and decelerates towards end. (quartic)
924      * @method easeBothStrong
925      * @param {Number} t Time value used to compute current value
926      * @param {Number} b Starting value
927      * @param {Number} c Delta between start and end values
928      * @param {Number} d Total length of animation
929      * @return {Number} The computed value for the current animation frame
930      */
931     easeBothStrong: function (t, b, c, d) {
932         if ((t/=d/2) < 1) {
933             return c/2*t*t*t*t + b;
934         }
935         
936         return -c/2 * ((t-=2)*t*t*t - 2) + b;
937     },
939     /**
940      * Snap in elastic effect.
941      * @method elasticIn
942      * @param {Number} t Time value used to compute current value
943      * @param {Number} b Starting value
944      * @param {Number} c Delta between start and end values
945      * @param {Number} d Total length of animation
946      * @param {Number} a Amplitude (optional)
947      * @param {Number} p Period (optional)
948      * @return {Number} The computed value for the current animation frame
949      */
951     elasticIn: function (t, b, c, d, a, p) {
952         if (t == 0) {
953             return b;
954         }
955         if ( (t /= d) == 1 ) {
956             return b+c;
957         }
958         if (!p) {
959             p=d*.3;
960         }
961         
962         if (!a || a < Math.abs(c)) {
963             a = c; 
964             var s = p/4;
965         }
966         else {
967             var s = p/(2*Math.PI) * Math.asin (c/a);
968         }
969         
970         return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
971     },
973     /**
974      * Snap out elastic effect.
975      * @method elasticOut
976      * @param {Number} t Time value used to compute current value
977      * @param {Number} b Starting value
978      * @param {Number} c Delta between start and end values
979      * @param {Number} d Total length of animation
980      * @param {Number} a Amplitude (optional)
981      * @param {Number} p Period (optional)
982      * @return {Number} The computed value for the current animation frame
983      */
984     elasticOut: function (t, b, c, d, a, p) {
985         if (t == 0) {
986             return b;
987         }
988         if ( (t /= d) == 1 ) {
989             return b+c;
990         }
991         if (!p) {
992             p=d*.3;
993         }
994         
995         if (!a || a < Math.abs(c)) {
996             a = c;
997             var s = p / 4;
998         }
999         else {
1000             var s = p/(2*Math.PI) * Math.asin (c/a);
1001         }
1002         
1003         return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
1004     },
1005     
1006     /**
1007      * Snap both elastic effect.
1008      * @method elasticBoth
1009      * @param {Number} t Time value used to compute current value
1010      * @param {Number} b Starting value
1011      * @param {Number} c Delta between start and end values
1012      * @param {Number} d Total length of animation
1013      * @param {Number} a Amplitude (optional)
1014      * @param {Number} p Period (optional)
1015      * @return {Number} The computed value for the current animation frame
1016      */
1017     elasticBoth: function (t, b, c, d, a, p) {
1018         if (t == 0) {
1019             return b;
1020         }
1021         
1022         if ( (t /= d/2) == 2 ) {
1023             return b+c;
1024         }
1025         
1026         if (!p) {
1027             p = d*(.3*1.5);
1028         }
1029         
1030         if ( !a || a < Math.abs(c) ) {
1031             a = c; 
1032             var s = p/4;
1033         }
1034         else {
1035             var s = p/(2*Math.PI) * Math.asin (c/a);
1036         }
1037         
1038         if (t < 1) {
1039             return -.5*(a*Math.pow(2,10*(t-=1)) * 
1040                     Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
1041         }
1042         return a*Math.pow(2,-10*(t-=1)) * 
1043                 Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
1044     },
1047     /**
1048      * Backtracks slightly, then reverses direction and moves to end.
1049      * @method backIn
1050      * @param {Number} t Time value used to compute current value
1051      * @param {Number} b Starting value
1052      * @param {Number} c Delta between start and end values
1053      * @param {Number} d Total length of animation
1054      * @param {Number} s Overshoot (optional)
1055      * @return {Number} The computed value for the current animation frame
1056      */
1057     backIn: function (t, b, c, d, s) {
1058         if (typeof s == 'undefined') {
1059             s = 1.70158;
1060         }
1061         return c*(t/=d)*t*((s+1)*t - s) + b;
1062     },
1064     /**
1065      * Overshoots end, then reverses and comes back to end.
1066      * @method backOut
1067      * @param {Number} t Time value used to compute current value
1068      * @param {Number} b Starting value
1069      * @param {Number} c Delta between start and end values
1070      * @param {Number} d Total length of animation
1071      * @param {Number} s Overshoot (optional)
1072      * @return {Number} The computed value for the current animation frame
1073      */
1074     backOut: function (t, b, c, d, s) {
1075         if (typeof s == 'undefined') {
1076             s = 1.70158;
1077         }
1078         return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
1079     },
1080     
1081     /**
1082      * Backtracks slightly, then reverses direction, overshoots end, 
1083      * then reverses and comes back to end.
1084      * @method backBoth
1085      * @param {Number} t Time value used to compute current value
1086      * @param {Number} b Starting value
1087      * @param {Number} c Delta between start and end values
1088      * @param {Number} d Total length of animation
1089      * @param {Number} s Overshoot (optional)
1090      * @return {Number} The computed value for the current animation frame
1091      */
1092     backBoth: function (t, b, c, d, s) {
1093         if (typeof s == 'undefined') {
1094             s = 1.70158; 
1095         }
1096         
1097         if ((t /= d/2 ) < 1) {
1098             return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
1099         }
1100         return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
1101     },
1103     /**
1104      * Bounce off of start.
1105      * @method bounceIn
1106      * @param {Number} t Time value used to compute current value
1107      * @param {Number} b Starting value
1108      * @param {Number} c Delta between start and end values
1109      * @param {Number} d Total length of animation
1110      * @return {Number} The computed value for the current animation frame
1111      */
1112     bounceIn: function (t, b, c, d) {
1113         return c - YAHOO.util.Easing.bounceOut(d-t, 0, c, d) + b;
1114     },
1115     
1116     /**
1117      * Bounces off end.
1118      * @method bounceOut
1119      * @param {Number} t Time value used to compute current value
1120      * @param {Number} b Starting value
1121      * @param {Number} c Delta between start and end values
1122      * @param {Number} d Total length of animation
1123      * @return {Number} The computed value for the current animation frame
1124      */
1125     bounceOut: function (t, b, c, d) {
1126         if ((t/=d) < (1/2.75)) {
1127                 return c*(7.5625*t*t) + b;
1128         } else if (t < (2/2.75)) {
1129                 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
1130         } else if (t < (2.5/2.75)) {
1131                 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
1132         }
1133         return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
1134     },
1135     
1136     /**
1137      * Bounces off start and end.
1138      * @method bounceBoth
1139      * @param {Number} t Time value used to compute current value
1140      * @param {Number} b Starting value
1141      * @param {Number} c Delta between start and end values
1142      * @param {Number} d Total length of animation
1143      * @return {Number} The computed value for the current animation frame
1144      */
1145     bounceBoth: function (t, b, c, d) {
1146         if (t < d/2) {
1147             return YAHOO.util.Easing.bounceIn(t*2, 0, c, d) * .5 + b;
1148         }
1149         return YAHOO.util.Easing.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
1150     }
1153 (function() {
1155  * Anim subclass for moving elements along a path defined by the "points" 
1156  * member of "attributes".  All "points" are arrays with x, y coordinates.
1157  * <p>Usage: <code>var myAnim = new YAHOO.util.Motion(el, { points: { to: [800, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1158  * @class Motion
1159  * @namespace YAHOO.util
1160  * @requires YAHOO.util.Anim
1161  * @requires YAHOO.util.AnimMgr
1162  * @requires YAHOO.util.Easing
1163  * @requires YAHOO.util.Bezier
1164  * @requires YAHOO.util.Dom
1165  * @requires YAHOO.util.Event
1166  * @requires YAHOO.util.CustomEvent 
1167  * @constructor
1168  * @extends YAHOO.util.ColorAnim
1169  * @param {String | HTMLElement} el Reference to the element that will be animated
1170  * @param {Object} attributes The attribute(s) to be animated.  
1171  * Each attribute is an object with at minimum a "to" or "by" member defined.  
1172  * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
1173  * All attribute names use camelCase.
1174  * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1175  * @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)
1176  */
1177     var Motion = function(el, attributes, duration,  method) {
1178         if (el) { // dont break existing subclasses not using YAHOO.extend
1179             Motion.superclass.constructor.call(this, el, attributes, duration, method);
1180         }
1181     };
1184     Motion.NAME = 'Motion';
1186     // shorthand
1187     var Y = YAHOO.util;
1188     YAHOO.extend(Motion, Y.ColorAnim);
1189     
1190     var superclass = Motion.superclass;
1191     var proto = Motion.prototype;
1193     proto.patterns.points = /^points$/i;
1194     
1195     proto.setAttribute = function(attr, val, unit) {
1196         if (  this.patterns.points.test(attr) ) {
1197             unit = unit || 'px';
1198             superclass.setAttribute.call(this, 'left', val[0], unit);
1199             superclass.setAttribute.call(this, 'top', val[1], unit);
1200         } else {
1201             superclass.setAttribute.call(this, attr, val, unit);
1202         }
1203     };
1205     proto.getAttribute = function(attr) {
1206         if (  this.patterns.points.test(attr) ) {
1207             var val = [
1208                 superclass.getAttribute.call(this, 'left'),
1209                 superclass.getAttribute.call(this, 'top')
1210             ];
1211         } else {
1212             val = superclass.getAttribute.call(this, attr);
1213         }
1215         return val;
1216     };
1218     proto.doMethod = function(attr, start, end) {
1219         var val = null;
1221         if ( this.patterns.points.test(attr) ) {
1222             var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;                             
1223             val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
1224         } else {
1225             val = superclass.doMethod.call(this, attr, start, end);
1226         }
1227         return val;
1228     };
1230     proto.setRuntimeAttribute = function(attr) {
1231         if ( this.patterns.points.test(attr) ) {
1232             var el = this.getEl();
1233             var attributes = this.attributes;
1234             var start;
1235             var control = attributes['points']['control'] || [];
1236             var end;
1237             var i, len;
1238             
1239             if (control.length > 0 && !(control[0] instanceof Array) ) { // could be single point or array of points
1240                 control = [control];
1241             } else { // break reference to attributes.points.control
1242                 var tmp = []; 
1243                 for (i = 0, len = control.length; i< len; ++i) {
1244                     tmp[i] = control[i];
1245                 }
1246                 control = tmp;
1247             }
1249             if (Y.Dom.getStyle(el, 'position') == 'static') { // default to relative
1250                 Y.Dom.setStyle(el, 'position', 'relative');
1251             }
1252     
1253             if ( isset(attributes['points']['from']) ) {
1254                 Y.Dom.setXY(el, attributes['points']['from']); // set position to from point
1255             } 
1256             else { Y.Dom.setXY( el, Y.Dom.getXY(el) ); } // set it to current position
1257             
1258             start = this.getAttribute('points'); // get actual top & left
1259             
1260             // TO beats BY, per SMIL 2.1 spec
1261             if ( isset(attributes['points']['to']) ) {
1262                 end = translateValues.call(this, attributes['points']['to'], start);
1263                 
1264                 var pageXY = Y.Dom.getXY(this.getEl());
1265                 for (i = 0, len = control.length; i < len; ++i) {
1266                     control[i] = translateValues.call(this, control[i], start);
1267                 }
1269                 
1270             } else if ( isset(attributes['points']['by']) ) {
1271                 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
1272                 
1273                 for (i = 0, len = control.length; i < len; ++i) {
1274                     control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
1275                 }
1276             }
1278             this.runtimeAttributes[attr] = [start];
1279             
1280             if (control.length > 0) {
1281                 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control); 
1282             }
1284             this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
1285         }
1286         else {
1287             superclass.setRuntimeAttribute.call(this, attr);
1288         }
1289     };
1290     
1291     var translateValues = function(val, start) {
1292         var pageXY = Y.Dom.getXY(this.getEl());
1293         val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
1295         return val; 
1296     };
1297     
1298     var isset = function(prop) {
1299         return (typeof prop !== 'undefined');
1300     };
1302     Y.Motion = Motion;
1303 })();
1304 (function() {
1306  * Anim subclass for scrolling elements to a position defined by the "scroll"
1307  * member of "attributes".  All "scroll" members are arrays with x, y scroll positions.
1308  * <p>Usage: <code>var myAnim = new YAHOO.util.Scroll(el, { scroll: { to: [0, 800] } }, 1, YAHOO.util.Easing.easeOut);</code></p>
1309  * @class Scroll
1310  * @namespace YAHOO.util
1311  * @requires YAHOO.util.Anim
1312  * @requires YAHOO.util.AnimMgr
1313  * @requires YAHOO.util.Easing
1314  * @requires YAHOO.util.Bezier
1315  * @requires YAHOO.util.Dom
1316  * @requires YAHOO.util.Event
1317  * @requires YAHOO.util.CustomEvent 
1318  * @extends YAHOO.util.ColorAnim
1319  * @constructor
1320  * @param {String or HTMLElement} el Reference to the element that will be animated
1321  * @param {Object} attributes The attribute(s) to be animated.  
1322  * Each attribute is an object with at minimum a "to" or "by" member defined.  
1323  * Additional optional members are "from" (defaults to current value), "units" (defaults to "px").  
1324  * All attribute names use camelCase.
1325  * @param {Number} duration (optional, defaults to 1 second) Length of animation (frames or seconds), defaults to time-based
1326  * @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)
1327  */
1328     var Scroll = function(el, attributes, duration,  method) {
1329         if (el) { // dont break existing subclasses not using YAHOO.extend
1330             Scroll.superclass.constructor.call(this, el, attributes, duration, method);
1331         }
1332     };
1334     Scroll.NAME = 'Scroll';
1336     // shorthand
1337     var Y = YAHOO.util;
1338     YAHOO.extend(Scroll, Y.ColorAnim);
1339     
1340     var superclass = Scroll.superclass;
1341     var proto = Scroll.prototype;
1343     proto.doMethod = function(attr, start, end) {
1344         var val = null;
1345     
1346         if (attr == 'scroll') {
1347             val = [
1348                 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
1349                 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
1350             ];
1351             
1352         } else {
1353             val = superclass.doMethod.call(this, attr, start, end);
1354         }
1355         return val;
1356     };
1358     proto.getAttribute = function(attr) {
1359         var val = null;
1360         var el = this.getEl();
1361         
1362         if (attr == 'scroll') {
1363             val = [ el.scrollLeft, el.scrollTop ];
1364         } else {
1365             val = superclass.getAttribute.call(this, attr);
1366         }
1367         
1368         return val;
1369     };
1371     proto.setAttribute = function(attr, val, unit) {
1372         var el = this.getEl();
1373         
1374         if (attr == 'scroll') {
1375             el.scrollLeft = val[0];
1376             el.scrollTop = val[1];
1377         } else {
1378             superclass.setAttribute.call(this, attr, val, unit);
1379         }
1380     };
1382     Y.Scroll = Scroll;
1383 })();
1384 YAHOO.register("animation", YAHOO.util.Anim, {version: "2.5.2", build: "1076"});