OSDN Git Service

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