PageRenderTime 81ms CodeModel.GetById 25ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/resources/org/apache/struts2/static/animation/animation.js

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