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