Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / docs / source / ext-base-anim.html
index d721fdd..4780d9b 100644 (file)
-<html>\r
-<head>\r
-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    \r
-  <title>The source code</title>\r
-    <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
-    <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
-</head>\r
-<body  onload="prettyPrint();">\r
-    <pre class="prettyprint lang-js">(function(){    \r
-    var EXTLIB = Ext.lib,\r
-        noNegatives = /width|height|opacity|padding/i,\r
-        offsetAttribute = /^((width|height)|(top|left))$/,\r
-        defaultUnit = /width|height|top$|bottom$|left$|right$/i,\r
-        offsetUnit =  /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,\r
-        isset = function(v){\r
-            return typeof v !== 'undefined';\r
-        },\r
-        now = function(){\r
-            return new Date();    \r
-        };\r
-        \r
-    EXTLIB.Anim = {\r
-        motion : function(el, args, duration, easing, cb, scope) {\r
-            return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion);\r
-        },\r
-\r
-        run : function(el, args, duration, easing, cb, scope, type) {\r
-            type = type || Ext.lib.AnimBase;\r
-            if (typeof easing == "string") {\r
-                easing = Ext.lib.Easing[easing];\r
-            }\r
-            var anim = new type(el, args, duration, easing);\r
-            anim.animateX(function() {\r
-                if(Ext.isFunction(cb)){\r
-                    cb.call(scope);\r
-                }\r
-            });\r
-            return anim;\r
-        }\r
-    };\r
-    \r
-    EXTLIB.AnimBase = function(el, attributes, duration, method) {\r
-        if (el) {\r
-            this.init(el, attributes, duration, method);\r
-        }\r
-    };\r
-\r
-    EXTLIB.AnimBase.prototype = {\r
-        doMethod: function(attr, start, end) {\r
-            var me = this;\r
-            return me.method(me.curFrame, start, end - start, me.totalFrames);\r
-        },\r
-\r
-\r
-        setAttr: function(attr, val, unit) {\r
-            if (noNegatives.test(attr) && val < 0) {\r
-                val = 0;\r
-            }\r
-            Ext.fly(this.el, '_anim').setStyle(attr, val + unit);\r
-        },\r
-\r
-\r
-        getAttr: function(attr) {\r
-            var el = Ext.fly(this.el),\r
-                val = el.getStyle(attr),\r
-                a = offsetAttribute.exec(attr) || []\r
-\r
-            if (val !== 'auto' && !offsetUnit.test(val)) {\r
-                return parseFloat(val);\r
-            }\r
-\r
-            return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0;\r
-        },\r
-\r
-\r
-        getDefaultUnit: function(attr) {\r
-            return defaultUnit.test(attr) ? 'px' : '';\r
-        },\r
-\r
-        animateX : function(callback, scope) {\r
-            var me = this,\r
-                f = function() {\r
-                me.onComplete.removeListener(f);\r
-                if (Ext.isFunction(callback)) {\r
-                    callback.call(scope || me, me);\r
-                }\r
-            };\r
-            me.onComplete.addListener(f, me);\r
-            me.animate();\r
-        },\r
-\r
-\r
-        setRunAttr: function(attr) {            \r
-            var me = this,\r
-                a = this.attributes[attr],\r
-                to = a.to,\r
-                by = a.by,\r
-                from = a.from,\r
-                unit = a.unit,\r
-                ra = (this.runAttrs[attr] = {}),\r
-                end;\r
-\r
-            if (!isset(to) && !isset(by)){\r
-                return false;\r
-            }\r
-\r
-            var start = isset(from) ? from : me.getAttr(attr);\r
-            if (isset(to)) {\r
-                end = to;\r
-            }else if(isset(by)) {\r
-                if (Ext.isArray(start)){\r
-                    end = [];\r
-                                       for(var i=0,len=start.length; i<len; i++) {\r
-                                               end[i] = start[i] + by[i];\r
-                                       }\r
-                }else{\r
-                    end = start + by;\r
-                }\r
-            }\r
-\r
-            Ext.apply(ra, {\r
-                start: start,\r
-                end: end,\r
-                unit: isset(unit) ? unit : me.getDefaultUnit(attr)\r
-            });\r
-        },\r
-\r
-\r
-        init: function(el, attributes, duration, method) {\r
-            var me = this,\r
-                actualFrames = 0,\r
-                mgr = EXTLIB.AnimMgr;\r
-                \r
-            Ext.apply(me, {\r
-                isAnimated: false,\r
-                startTime: null,\r
-                el: Ext.getDom(el),\r
-                attributes: attributes || {},\r
-                duration: duration || 1,\r
-                method: method || EXTLIB.Easing.easeNone,\r
-                useSec: true,\r
-                curFrame: 0,\r
-                totalFrames: mgr.fps,\r
-                runAttrs: {},\r
-                animate: function(){\r
-                    var me = this,\r
-                        d = me.duration;\r
-                    \r
-                    if(me.isAnimated){\r
-                        return false;\r
-                    }\r
-\r
-                    me.curFrame = 0;\r
-                    me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;\r
-                    mgr.registerElement(me); \r
-                },\r
-                \r
-                stop: function(finish){\r
-                    var me = this;\r
-                \r
-                    if(finish){\r
-                        me.curFrame = me.totalFrames;\r
-                        me._onTween.fire();\r
-                    }\r
-                    mgr.stop(me);\r
-                }\r
-            });\r
-\r
-            var onStart = function(){\r
-                var me = this,\r
-                    attr;\r
-                \r
-                me.onStart.fire();\r
-                me.runAttrs = {};\r
-                for(attr in this.attributes){\r
-                    this.setRunAttr(attr);\r
-                }\r
-\r
-                me.isAnimated = true;\r
-                me.startTime = now();\r
-                actualFrames = 0;\r
-            };\r
-\r
-\r
-            var onTween = function(){\r
-                var me = this;\r
-\r
-                me.onTween.fire({\r
-                    duration: now() - me.startTime,\r
-                    curFrame: me.curFrame\r
-                });\r
-\r
-                var ra = me.runAttrs;\r
-                for (var attr in ra) {\r
-                    this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit);\r
-                }\r
-\r
-                ++actualFrames;\r
-            };\r
-\r
-            var onComplete = function() {\r
-                var me = this,\r
-                    actual = (now() - me.startTime) / 1000,\r
-                    data = {\r
-                        duration: actual,\r
-                        frames: actualFrames,\r
-                        fps: actualFrames / actual\r
-                    };\r
-\r
-                me.isAnimated = false;\r
-                actualFrames = 0;\r
-                me.onComplete.fire(data);\r
-            };\r
-\r
-            me.onStart = new Ext.util.Event(me);\r
-            me.onTween = new Ext.util.Event(me);            \r
-            me.onComplete = new Ext.util.Event(me);\r
-            (me._onStart = new Ext.util.Event(me)).addListener(onStart);\r
-            (me._onTween = new Ext.util.Event(me)).addListener(onTween);\r
-            (me._onComplete = new Ext.util.Event(me)).addListener(onComplete); \r
-        }\r
-    };\r
-\r
-\r
-    Ext.lib.AnimMgr = new function() {\r
-        var me = this,\r
-            thread = null,\r
-            queue = [],\r
-            tweenCount = 0;\r
-\r
-\r
-        Ext.apply(me, {\r
-            fps: 1000,\r
-            delay: 1,\r
-            registerElement: function(tween){\r
-                queue.push(tween);\r
-                ++tweenCount;\r
-                tween._onStart.fire();\r
-                me.start();\r
-            },\r
-            \r
-            unRegister: function(tween, index){\r
-                tween._onComplete.fire();\r
-                index = index || getIndex(tween);\r
-                if (index != -1) {\r
-                    queue.splice(index, 1);\r
-                }\r
-\r
-                if (--tweenCount <= 0) {\r
-                    me.stop();\r
-                }\r
-            },\r
-            \r
-            start: function(){\r
-                if(thread === null){\r
-                    thread = setInterval(me.run, me.delay);\r
-                }\r
-            },\r
-            \r
-            stop: function(tween){\r
-                if(!tween){\r
-                    clearInterval(thread);\r
-                    for(var i = 0, len = queue.length; i < len; ++i){\r
-                        if(queue[0].isAnimated){\r
-                            me.unRegister(queue[0], 0);\r
-                        }\r
-                    }\r
-\r
-                    queue = [];\r
-                    thread = null;\r
-                    tweenCount = 0;\r
-                }else{\r
-                    me.unRegister(tween);\r
-                }\r
-            },\r
-            \r
-            run: function(){\r
-                var tf, i, len, tween;\r
-                for(i = 0, len = queue.length; i<len; i++) {\r
-                    tween = queue[i];\r
-                    if(tween && tween.isAnimated){\r
-                        tf = tween.totalFrames;\r
-                        if(tween.curFrame < tf || tf === null){\r
-                            ++tween.curFrame;\r
-                            if(tween.useSec){\r
-                                correctFrame(tween);\r
-                            }\r
-                            tween._onTween.fire();\r
-                        }else{\r
-                            me.stop(tween);\r
-                        }\r
-                    }                   \r
-                }\r
-            }\r
-        });\r
-\r
-        var getIndex = function(anim) {\r
-            var i, len;\r
-            for(i = 0, len = queue.length; i<len; i++) {\r
-                if(queue[i] === anim) {\r
-                    return i;\r
-                }\r
-            }\r
-            return -1;\r
-        };\r
-\r
-        var correctFrame = function(tween) {\r
-            var frames = tween.totalFrames,\r
-                frame = tween.curFrame,\r
-                duration = tween.duration,\r
-                expected = (frame * duration * 1000 / frames),\r
-                elapsed = (now() - tween.startTime),\r
-                tweak = 0;\r
-\r
-            if(elapsed < duration * 1000){\r
-                tweak = Math.round((elapsed / expected - 1) * frame);\r
-            }else{\r
-                tweak = frames - (frame + 1);\r
-            }\r
-            if(tweak > 0 && isFinite(tweak)){\r
-                if(tween.curFrame + tweak >= frames){\r
-                    tweak = frames - (frame + 1);\r
-                }\r
-                tween.curFrame += tweak;\r
-            }\r
-        };\r
-    };\r
-\r
-    EXTLIB.Bezier = new function() {\r
-\r
-        this.getPosition = function(points, t) {\r
-            var n = points.length,\r
-                tmp = [],\r
-                c = 1 - t, \r
-                i,\r
-                j;\r
-\r
-            for (i = 0; i < n; ++i) {\r
-                tmp[i] = [points[i][0], points[i][1]];\r
-            }\r
-\r
-            for (j = 1; j < n; ++j) {\r
-                for (i = 0; i < n - j; ++i) {\r
-                    tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];\r
-                    tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];\r
-                }\r
-            }\r
-\r
-            return [ tmp[0][0], tmp[0][1] ];\r
-\r
-        };\r
-    };\r
-\r
-\r
-    EXTLIB.Easing = {\r
-        easeNone: function (t, b, c, d) {\r
-            return c * t / d + b;\r
-        },\r
-\r
-\r
-        easeIn: function (t, b, c, d) {\r
-            return c * (t /= d) * t + b;\r
-        },\r
-\r
-\r
-        easeOut: function (t, b, c, d) {\r
-            return -c * (t /= d) * (t - 2) + b;\r
-        }\r
-    };\r
-\r
-    (function() {\r
-        EXTLIB.Motion = function(el, attributes, duration, method) {\r
-            if (el) {\r
-                EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method);\r
-            }\r
-        };\r
-\r
-        Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);\r
-\r
-        var superclass = EXTLIB.Motion.superclass,\r
-            proto = EXTLIB.Motion.prototype,\r
-            pointsRe = /^points$/i;\r
-\r
-        Ext.apply(EXTLIB.Motion.prototype, {\r
-            setAttr: function(attr, val, unit){\r
-                var me = this,\r
-                    setAttr = superclass.setAttr;\r
-                    \r
-                if (pointsRe.test(attr)) {\r
-                    unit = unit || 'px';\r
-                    setAttr.call(me, 'left', val[0], unit);\r
-                    setAttr.call(me, 'top', val[1], unit);\r
-                } else {\r
-                    setAttr.call(me, attr, val, unit);\r
-                }\r
-            },\r
-            \r
-            getAttr: function(attr){\r
-                var me = this,\r
-                    getAttr = superclass.getAttr;\r
-                    \r
-                return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr);\r
-            },\r
-            \r
-            doMethod: function(attr, start, end){\r
-                var me = this;\r
-                \r
-                return pointsRe.test(attr)\r
-                        ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100)\r
-                        : superclass.doMethod.call(me, attr, start, end);\r
-            },\r
-            \r
-            setRunAttr: function(attr){\r
-                if(pointsRe.test(attr)){\r
-                    \r
-                    var me = this,\r
-                        el = this.el,\r
-                        points = this.attributes.points,\r
-                        control = points.control || [],\r
-                        from = points.from,\r
-                        to = points.to,\r
-                        by = points.by,\r
-                        DOM = EXTLIB.Dom,\r
-                        start,\r
-                        i,\r
-                        end,\r
-                        len,\r
-                        ra;\r
-                  \r
-\r
-                    if(control.length > 0 && !Ext.isArray(control[0])){\r
-                        control = [control];\r
-                    }else{\r
-                        /*\r
-                        var tmp = [];\r
-                        for (i = 0,len = control.length; i < len; ++i) {\r
-                            tmp[i] = control[i];\r
-                        }\r
-                        control = tmp;\r
-                        */\r
-                    }\r
-\r
-                    Ext.fly(el, '_anim').position();\r
-                    DOM.setXY(el, isset(from) ? from : DOM.getXY(el));\r
-                    start = me.getAttr('points');\r
-\r
-\r
-                    if(isset(to)){\r
-                        end = translateValues.call(me, to, start);\r
-                        for (i = 0,len = control.length; i < len; ++i) {\r
-                            control[i] = translateValues.call(me, control[i], start);\r
-                        }\r
-                    } else if (isset(by)) {\r
-                        end = [start[0] + by[0], start[1] + by[1]];\r
-\r
-                        for (i = 0,len = control.length; i < len; ++i) {\r
-                            control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];\r
-                        }\r
-                    }\r
-\r
-                    ra = this.runAttrs[attr] = [start];\r
-                    if (control.length > 0) {\r
-                        ra = ra.concat(control);\r
-                    }\r
-\r
-                    ra[ra.length] = end;\r
-                }else{\r
-                    superclass.setRunAttr.call(this, attr);\r
-                }\r
-            }\r
-        });\r
-\r
-        var translateValues = function(val, start) {\r
-            var pageXY = EXTLIB.Dom.getXY(this.el);\r
-            return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]];\r
-        };\r
-    })();\r
-})();</pre>    \r
-</body>\r
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
+  <title>The source code</title>
+    <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+    <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+</head>
+<body  onload="prettyPrint();">
+    <pre class="prettyprint lang-js">/*!
+ * Ext JS Library 3.2.0
+ * Copyright(c) 2006-2010 Ext JS, Inc.
+ * licensing@extjs.com
+ * http://www.extjs.com/license
+ */
+(function(){
+    var EXTLIB = Ext.lib,
+        noNegatives = /width|height|opacity|padding/i,
+        offsetAttribute = /^((width|height)|(top|left))$/,
+        defaultUnit = /width|height|top$|bottom$|left$|right$/i,
+        offsetUnit =  /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,
+        isset = function(v){
+            return typeof v !== 'undefined';
+        },
+        now = function(){
+            return new Date();
+        };
+
+    EXTLIB.Anim = {
+        motion : function(el, args, duration, easing, cb, scope) {
+            return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion);
+        },
+
+        run : function(el, args, duration, easing, cb, scope, type) {
+            type = type || Ext.lib.AnimBase;
+            if (typeof easing == "string") {
+                easing = Ext.lib.Easing[easing];
+            }
+            var anim = new type(el, args, duration, easing);
+            anim.animateX(function() {
+                if(Ext.isFunction(cb)){
+                    cb.call(scope);
+                }
+            });
+            return anim;
+        }
+    };
+
+    EXTLIB.AnimBase = function(el, attributes, duration, method) {
+        if (el) {
+            this.init(el, attributes, duration, method);
+        }
+    };
+
+    EXTLIB.AnimBase.prototype = {
+        doMethod: function(attr, start, end) {
+            var me = this;
+            return me.method(me.curFrame, start, end - start, me.totalFrames);
+        },
+
+
+        setAttr: function(attr, val, unit) {
+            if (noNegatives.test(attr) && val < 0) {
+                val = 0;
+            }
+            Ext.fly(this.el, '_anim').setStyle(attr, val + unit);
+        },
+
+
+        getAttr: function(attr) {
+            var el = Ext.fly(this.el),
+                val = el.getStyle(attr),
+                a = offsetAttribute.exec(attr) || [];
+
+            if (val !== 'auto' && !offsetUnit.test(val)) {
+                return parseFloat(val);
+            }
+
+            return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0;
+        },
+
+
+        getDefaultUnit: function(attr) {
+            return defaultUnit.test(attr) ? 'px' : '';
+        },
+
+        animateX : function(callback, scope) {
+            var me = this,
+                f = function() {
+                me.onComplete.removeListener(f);
+                if (Ext.isFunction(callback)) {
+                    callback.call(scope || me, me);
+                }
+            };
+            me.onComplete.addListener(f, me);
+            me.animate();
+        },
+
+
+        setRunAttr: function(attr) {
+            var me = this,
+                a = this.attributes[attr],
+                to = a.to,
+                by = a.by,
+                from = a.from,
+                unit = a.unit,
+                ra = (this.runAttrs[attr] = {}),
+                end;
+
+            if (!isset(to) && !isset(by)){
+                return false;
+            }
+
+            var start = isset(from) ? from : me.getAttr(attr);
+            if (isset(to)) {
+                end = to;
+            }else if(isset(by)) {
+                if (Ext.isArray(start)){
+                    end = [];
+                    for(var i=0,len=start.length; i<len; i++) {
+                        end[i] = start[i] + by[i];
+                    }
+                }else{
+                    end = start + by;
+                }
+            }
+
+            Ext.apply(ra, {
+                start: start,
+                end: end,
+                unit: isset(unit) ? unit : me.getDefaultUnit(attr)
+            });
+        },
+
+
+        init: function(el, attributes, duration, method) {
+            var me = this,
+                actualFrames = 0,
+                mgr = EXTLIB.AnimMgr;
+
+            Ext.apply(me, {
+                isAnimated: false,
+                startTime: null,
+                el: Ext.getDom(el),
+                attributes: attributes || {},
+                duration: duration || 1,
+                method: method || EXTLIB.Easing.easeNone,
+                useSec: true,
+                curFrame: 0,
+                totalFrames: mgr.fps,
+                runAttrs: {},
+                animate: function(){
+                    var me = this,
+                        d = me.duration;
+
+                    if(me.isAnimated){
+                        return false;
+                    }
+
+                    me.curFrame = 0;
+                    me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;
+                    mgr.registerElement(me);
+                },
+
+                stop: function(finish){
+                    var me = this;
+
+                    if(finish){
+                        me.curFrame = me.totalFrames;
+                        me._onTween.fire();
+                    }
+                    mgr.stop(me);
+                }
+            });
+
+            var onStart = function(){
+                var me = this,
+                    attr;
+
+                me.onStart.fire();
+                me.runAttrs = {};
+                for(attr in this.attributes){
+                    this.setRunAttr(attr);
+                }
+
+                me.isAnimated = true;
+                me.startTime = now();
+                actualFrames = 0;
+            };
+
+
+            var onTween = function(){
+                var me = this;
+
+                me.onTween.fire({
+                    duration: now() - me.startTime,
+                    curFrame: me.curFrame
+                });
+
+                var ra = me.runAttrs;
+                for (var attr in ra) {
+                    this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit);
+                }
+
+                ++actualFrames;
+            };
+
+            var onComplete = function() {
+                var me = this,
+                    actual = (now() - me.startTime) / 1000,
+                    data = {
+                        duration: actual,
+                        frames: actualFrames,
+                        fps: actualFrames / actual
+                    };
+
+                me.isAnimated = false;
+                actualFrames = 0;
+                me.onComplete.fire(data);
+            };
+
+            me.onStart = new Ext.util.Event(me);
+            me.onTween = new Ext.util.Event(me);
+            me.onComplete = new Ext.util.Event(me);
+            (me._onStart = new Ext.util.Event(me)).addListener(onStart);
+            (me._onTween = new Ext.util.Event(me)).addListener(onTween);
+            (me._onComplete = new Ext.util.Event(me)).addListener(onComplete);
+        }
+    };
+
+
+    Ext.lib.AnimMgr = new function() {
+        var me = this,
+            thread = null,
+            queue = [],
+            tweenCount = 0;
+
+
+        Ext.apply(me, {
+            fps: 1000,
+            delay: 1,
+            registerElement: function(tween){
+                queue.push(tween);
+                ++tweenCount;
+                tween._onStart.fire();
+                me.start();
+            },
+
+            unRegister: function(tween, index){
+                tween._onComplete.fire();
+                index = index || getIndex(tween);
+                if (index != -1) {
+                    queue.splice(index, 1);
+                }
+
+                if (--tweenCount <= 0) {
+                    me.stop();
+                }
+            },
+
+            start: function(){
+                if(thread === null){
+                    thread = setInterval(me.run, me.delay);
+                }
+            },
+
+            stop: function(tween){
+                if(!tween){
+                    clearInterval(thread);
+                    for(var i = 0, len = queue.length; i < len; ++i){
+                        if(queue[0].isAnimated){
+                            me.unRegister(queue[0], 0);
+                        }
+                    }
+
+                    queue = [];
+                    thread = null;
+                    tweenCount = 0;
+                }else{
+                    me.unRegister(tween);
+                }
+            },
+
+            run: function(){
+                var tf, i, len, tween;
+                for(i = 0, len = queue.length; i<len; i++) {
+                    tween = queue[i];
+                    if(tween && tween.isAnimated){
+                        tf = tween.totalFrames;
+                        if(tween.curFrame < tf || tf === null){
+                            ++tween.curFrame;
+                            if(tween.useSec){
+                                correctFrame(tween);
+                            }
+                            tween._onTween.fire();
+                        }else{
+                            me.stop(tween);
+                        }
+                    }
+                }
+            }
+        });
+
+        var getIndex = function(anim) {
+            var i, len;
+            for(i = 0, len = queue.length; i<len; i++) {
+                if(queue[i] === anim) {
+                    return i;
+                }
+            }
+            return -1;
+        };
+
+        var correctFrame = function(tween) {
+            var frames = tween.totalFrames,
+                frame = tween.curFrame,
+                duration = tween.duration,
+                expected = (frame * duration * 1000 / frames),
+                elapsed = (now() - tween.startTime),
+                tweak = 0;
+
+            if(elapsed < duration * 1000){
+                tweak = Math.round((elapsed / expected - 1) * frame);
+            }else{
+                tweak = frames - (frame + 1);
+            }
+            if(tweak > 0 && isFinite(tweak)){
+                if(tween.curFrame + tweak >= frames){
+                    tweak = frames - (frame + 1);
+                }
+                tween.curFrame += tweak;
+            }
+        };
+    };
+
+    EXTLIB.Bezier = new function() {
+
+        this.getPosition = function(points, t) {
+            var n = points.length,
+                tmp = [],
+                c = 1 - t,
+                i,
+                j;
+
+            for (i = 0; i < n; ++i) {
+                tmp[i] = [points[i][0], points[i][1]];
+            }
+
+            for (j = 1; j < n; ++j) {
+                for (i = 0; i < n - j; ++i) {
+                    tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
+                    tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
+                }
+            }
+
+            return [ tmp[0][0], tmp[0][1] ];
+
+        };
+    };
+
+
+    EXTLIB.Easing = {
+        easeNone: function (t, b, c, d) {
+            return c * t / d + b;
+        },
+
+
+        easeIn: function (t, b, c, d) {
+            return c * (t /= d) * t + b;
+        },
+
+
+        easeOut: function (t, b, c, d) {
+            return -c * (t /= d) * (t - 2) + b;
+        }
+    };
+
+    (function() {
+        EXTLIB.Motion = function(el, attributes, duration, method) {
+            if (el) {
+                EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method);
+            }
+        };
+
+        Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);
+
+        var superclass = EXTLIB.Motion.superclass,
+            proto = EXTLIB.Motion.prototype,
+            pointsRe = /^points$/i;
+
+        Ext.apply(EXTLIB.Motion.prototype, {
+            setAttr: function(attr, val, unit){
+                var me = this,
+                    setAttr = superclass.setAttr;
+
+                if (pointsRe.test(attr)) {
+                    unit = unit || 'px';
+                    setAttr.call(me, 'left', val[0], unit);
+                    setAttr.call(me, 'top', val[1], unit);
+                } else {
+                    setAttr.call(me, attr, val, unit);
+                }
+            },
+
+            getAttr: function(attr){
+                var me = this,
+                    getAttr = superclass.getAttr;
+
+                return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr);
+            },
+
+            doMethod: function(attr, start, end){
+                var me = this;
+
+                return pointsRe.test(attr)
+                        ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100)
+                        : superclass.doMethod.call(me, attr, start, end);
+            },
+
+            setRunAttr: function(attr){
+                if(pointsRe.test(attr)){
+
+                    var me = this,
+                        el = this.el,
+                        points = this.attributes.points,
+                        control = points.control || [],
+                        from = points.from,
+                        to = points.to,
+                        by = points.by,
+                        DOM = EXTLIB.Dom,
+                        start,
+                        i,
+                        end,
+                        len,
+                        ra;
+
+
+                    if(control.length > 0 && !Ext.isArray(control[0])){
+                        control = [control];
+                    }else{
+                        /*
+                        var tmp = [];
+                        for (i = 0,len = control.length; i < len; ++i) {
+                            tmp[i] = control[i];
+                        }
+                        control = tmp;
+                        */
+                    }
+
+                    Ext.fly(el, '_anim').position();
+                    DOM.setXY(el, isset(from) ? from : DOM.getXY(el));
+                    start = me.getAttr('points');
+
+
+                    if(isset(to)){
+                        end = translateValues.call(me, to, start);
+                        for (i = 0,len = control.length; i < len; ++i) {
+                            control[i] = translateValues.call(me, control[i], start);
+                        }
+                    } else if (isset(by)) {
+                        end = [start[0] + by[0], start[1] + by[1]];
+
+                        for (i = 0,len = control.length; i < len; ++i) {
+                            control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
+                        }
+                    }
+
+                    ra = this.runAttrs[attr] = [start];
+                    if (control.length > 0) {
+                        ra = ra.concat(control);
+                    }
+
+                    ra[ra.length] = end;
+                }else{
+                    superclass.setRunAttr.call(this, attr);
+                }
+            }
+        });
+
+        var translateValues = function(val, start) {
+            var pageXY = EXTLIB.Dom.getXY(this.el);
+            return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]];
+        };
+    })();
+})();</pre>    
+</body>
 </html>
\ No newline at end of file