Fx.js

Ext.enableFx = true;

Ext.apply(Ext.Element.prototype, {
    slideIn : function(anchor, o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){

            anchor = anchor || 'tl';

            // fix display to visibility
            this.fixDisplay();

            // restore values after effect
            var r = this.getFxRestore();

            var b = this.getBox();
            // fixed size for slide
            this.setSize(b);

            // wrap if needed
            var wrap = this.fxWrap(r.pos, o, 'hidden');

            var st = this.dom.style;
            st.visibility = 'visible';
            st.position = 'absolute';

            // clear out temp styles after slide and unwrap
            var after = function(){
                el.fxUnwrap(wrap, r.pos, o);
                st.width = r.width;
                st.height = r.height;
                el.afterFx(o);
            };
            // time to calc the positions
            var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};

            switch(anchor.toLowerCase()){
                case 't':
                    wrap.setSize(b.width, 0);
                    st.left = st.bottom = '0';
                    a = {height: bh};
                break;
                case 'l':
                    wrap.setSize(0, b.height);
                    st.right = st.top = '0';
                    a = {width: bw};
                break;
                case 'r':
                    wrap.setSize(0, b.height);
                    wrap.setX(b.right);
                    st.left = st.top = '0';
                    a = {width: bw, points: pt};
                break;
                case 'b':
                    wrap.setSize(b.width, 0);
                    wrap.setY(b.bottom);
                    st.left = st.top = '0';
                    a = {height: bh, points: pt};
                break;
                case 'tl':
                    wrap.setSize(0, 0);
                    st.right = st.bottom = '0';
                    a = {width: bw, height: bh};
                break;
                case 'bl':
                    wrap.setSize(0, 0);
                    wrap.setY(b.y+b.height);
                    st.right = st.top = '0';
                    a = {width: bw, height: bh, points: pt};
                break;
                case 'br':
                    wrap.setSize(0, 0);
                    wrap.setXY([b.right, b.bottom]);
                    st.left = st.top = '0';
                    a = {width: bw, height: bh, points: pt};
                break;
                case 'tr':
                    wrap.setSize(0, 0);
                    wrap.setX(b.x+b.width);
                    st.left = st.bottom = '0';
                    a = {width: bw, height: bh, points: pt};
                break;
            }
            this.dom.style.visibility = 'visible';
            wrap.show();

            arguments.callee.anim = wrap.fxanim(a,
                o,
                YAHOO.util.Motion,
                .5,
                YAHOO.util.Easing.easeOut, after);
        });
        return this;
    },

    slideOut : function(anchor, o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){

            anchor = anchor || 'tl';

            // restore values after effect
            var r = this.getFxRestore();

            var b = this.getBox();
            // fixed size for slide
            this.setSize(b);

            // wrap if needed
            var wrap = this.fxWrap(r.pos, o, 'visible');

            var st = this.dom.style;
            st.visibility = 'visible';
            st.position = 'absolute';

            wrap.setSize(b);

            var after = function(){
                el.hide();

                el.fxUnwrap(wrap, r.pos, o);

                st.width = r.width;
                st.height = r.height;

                el.afterFx(o);
            };

            var a, zero = {to: 0};
            switch(anchor.toLowerCase()){
                case 't':
                    st.left = st.bottom = '0';
                    a = {height: zero};
                break;
                case 'l':
                    st.right = st.top = '0';
                    a = {width: zero};
                break;
                case 'r':
                    st.left = st.top = '0';
                    a = {width: zero, points: {to:[b.right, b.y]}};
                break;
                case 'b':
                    st.left = st.top = '0';
                    a = {height: zero, points: {to:[b.x, b.bottom]}};
                break;
                case 'tl':
                    st.right = st.bottom = '0';
                    a = {width: zero, height: zero};
                break;
                case 'bl':
                    st.right = st.top = '0';
                    a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
                break;
                case 'br':
                    st.left = st.top = '0';
                    a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
                break;
                case 'tr':
                    st.left = st.bottom = '0';
                    a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
                break;
            }

            arguments.callee.anim = wrap.fxanim(a,
                o,
                YAHOO.util.Motion,
                .5,
                YAHOO.util.Easing.easeOut, after);
        });
        return this;
    },

    puff : function(o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){
            this.clearOpacity();
            this.show();

            // restore values after effect
            var r = this.getFxRestore();
            var st = this.dom.style;

            var after = function(){
                el.hide();

                el.clearOpacity();

                el.setPositioning(r.pos);
                st.width = r.width;
                st.height = r.height;

                el.afterFx(o);
            };

            var width = this.getWidth();
            var height = this.getHeight();

            arguments.callee.anim = this.fxanim({
                    width : {to: this.adjustWidth(width * 2)},
                    height : {to: this.adjustHeight(height * 2)},
                    points : {by: [-(width * .5), -(height * .5)]},
                    opacity : {to: 0},
                    fontSize: {to:200, unit: '%'}
                },
                o,
                YAHOO.util.Motion,
                .5,
                YAHOO.util.Easing.easeOut, after);
        });
        return this;
    },

    switchOff : function(o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){
            this.clearOpacity();
            this.clip();

            // restore values after effect
            var r = this.getFxRestore();
            var st = this.dom.style;

            var after = function(){
                el.hide();

                el.clearOpacity();
                el.setPositioning(r.pos);
                st.width = r.width;
                st.height = r.height;

                el.afterFx(o);
            };

            this.fxanim({opacity:{to:0.3}}, {duration: .1, callback: function(){
                this.clearOpacity();
                (function(){
                    this.fxanim({
                        height:{to:1},
                        points:{by:[0, this.getHeight() * .5]}
                    }, o, YAHOO.util.Motion, 0.3, YAHOO.util.Easing.easeIn, after);
                }).defer(100, this);
            }, scope: this});
        });
        return this;
    },

    /**
     * Highlights the Element by setting a color (defaults to background-color) and then
     * fading back to the original color. If no original color is available, you should
     * provide an "endColor" option which will be cleared after the animation. The available options
     * for the "options" parameter are listed below (with their default values): <br/>
<pre><code>
el.highlight('ff0000', {<br/>
    attr: 'background-color',<br/>
    endColor: (current color) or 'ffffff'<br/>
    callback: yourFunction,<br/>
    scope: yourObject,<br/>
    easing: YAHOO.util.Easing.easeNone, <br/>
    duration: .75<br/>
});
</code></pre>
     * @param {String} color (optional) The highlight color. Should be a 6 char hex color (no #). (defaults to ffff9c)
     * @param {Object} options (optional) Object literal with any of the options listed above
     */
    highlight : function(color, o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){
            color = color || 'ffff9c';
            attr = o.attr || 'backgroundColor';

            this.clearOpacity();
            this.show();

            var origColor = this.getColor(attr);
            endColor = (o.endColor || origColor) || 'ffffff';

            var after = function(){
                el.dom.style[attr] = origColor || '';
                el.afterFx(o);
            };

            var a = {};
            a[attr] = {from: color, to: endColor};

            arguments.callee.anim = this.fxanim(a,
                o,
                YAHOO.util.ColorAnim,
                1,
                YAHOO.util.Easing.easeIn, after);
        });
        return this;
    },

    /**
    * Show a ripple of exploding, attenuating borders to draw attention to an Element.
    * @param {<i>Number<i>} color (optional) The color of the border (default to #C3DAF9).
    * @param {<i>Number</i>} count (optional) How many ripples. defaults to 1
    * @param {<i>Float</i>} options (optional) 
    */
    frame : function(color, count, o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){
            color = color || "#C3DAF9";
            if(color.length == 6){
                color = '#' + color;
            }
            count = count || 1;
            duration = o.duration || 1;
            this.show();

            var b = this.getBox();
            var animFn = function(){
                var proxy = this.createProxy({
                     tag:"div",
                     style:{
                        visbility:"hidden",
                        position:"absolute",
                        'z-index':"35000", // yee haw
                        border:"0px solid " + color
                     }
                  });
                var scale = Ext.isBorderBox ? 2 : 1;
                proxy.animate({
                    top:{from:b.y, to:b.y - 20},
                    left:{from:b.x, to:b.x - 20},
                    borderWidth:{from:0, to:10},
                    opacity:{from:1, to:0},
                    height:{from:b.height, to:(b.height + (20*scale))},
                    width:{from:b.width, to:(b.width + (20*scale))}
                }, duration, function(){
                    proxy.remove();
                });
                if(--count > 0){
                     animFn.defer((duration/2)*1000, this);
                }else{
                    el.afterFx(o);
                }
            };
            animFn.call(this);
        });
        return this;
    },

    pause : function(seconds){
        var el = this.getFxEl();
        var o = {};

        el.queueFx(o, function(){
            setTimeout(function(){
                el.afterFx(o);
            }, seconds * 1000);
        });
        return this;
    },

    fadeIn : function(o){
        this.show(o || true);
        return this;
    },

    fadeOut : function(o){
        this.hide(o || true);
        return this;
    },

    ghost : function(anchor, o){
        var el = this.getFxEl();
        o = o || {};

        el.queueFx(o, function(){
            anchor = anchor || 'b';

            // restore values after effect
            var r = this.getFxRestore();
            var w = this.getWidth(),
                h = this.getHeight();

            var st = this.dom.style;

            var after = function(){
                el.hide();

                el.clearOpacity();
                el.setPositioning(r.pos);
                st.width = r.width;
                st.height = r.height;

                el.afterFx(o);
            };

            var a = {opacity: {to: 0}, points: {}}, pt = a.points;
            switch(anchor.toLowerCase()){
                case 't':
                    pt.by = [0, -h];
                break;
                case 'l':
                    pt.by = [-w, 0];
                break;
                case 'r':
                    pt.by = [w, 0];
                break;
                case 'b':
                    pt.by = [0, h];
                break;
                case 'tl':
                    pt.by = [-w, -h];
                break;
                case 'bl':
                    pt.by = [-w, h];
                break;
                case 'br':
                    pt.by = [w, h];
                break;
                case 'tr':
                    pt.by = [w, -h];
                break;
            }

            arguments.callee.anim = this.fxanim(a,
                o,
                YAHOO.util.Motion,
                .5,
                YAHOO.util.Easing.easeOut, after);
        });
        return this;
    },

    syncFx : function(){
        this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
            block : false,
            concurrent : true,
            stopFx : false
        });
    },

    sequenceFx : function(){
        this.fxDefaults = Ext.apply(this.fxDefaults || {}, {
            block : false,
            concurrent : false,
            stopFx : false
        });
    },

    nextFx : function(){
        var ef = this.fxQueue[0];
        if(ef){
            ef.call(this);
        }
    },

    hasActiveFx : function(){
        return this.fxQueue && this.fxQueue[0];
    },

    stopFx : function(){
        if(this.hasActiveFx()){
            var cur = this.fxQueue[0];
            if(cur && cur.anim && cur.anim.isAnimated()){
                this.fxQueue = [cur]; // clear out others
                cur.anim.stop(true);
            }
        }
        return this;
    },

    beforeFx : function(o){
        if(this.hasActiveFx() && !o.concurrent){
           if(o.stopFx){
               this.stopFx();
               return true;
           }
           return false;
        }
        return true;
    },

    hasFxBlock : function(){
        var q = this.fxQueue;
        return q && q[0] && q[0].block;
    },

    queueFx : function(o, fn){
        if(!this.fxQueue){
            this.fxQueue = [];
        }
        if(!this.hasFxBlock()){
            Ext.applyIf(o, this.fxDefaults);
            var run = this.beforeFx(o);
            fn.block = o.block;
            this.fxQueue.push(fn);
            if(run){
                this.nextFx();
            }
        }
    },

    fxWrap : function(pos, o, vis){
        var wrap;
        if(!o.wrap || !(wrap = Ext.get(o.wrap))){
            var div = document.createElement('div');
            div.style.visibility = vis;
            wrap = Ext.get(this.dom.parentNode.insertBefore(div, this.dom));
            wrap.setPositioning(pos);
            if(wrap.getStyle('position') == 'static'){
                wrap.position('relative');
            }
            this.clearPositioning();
            wrap.clip();
            wrap.dom.appendChild(this.dom);
        }
        return wrap;
    },

    fxUnwrap : function(wrap, pos, o){
        this.clearPositioning();
        this.setPositioning(pos);
        if(!o.wrap){
            wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
            wrap.remove();
        }
    },

    getFxRestore : function(){
       return {pos: this.getPositioning(), width: this.getStyle('width'), height : this.getStyle('height')};
    },

    afterFx : function(o){
        this.fxQueue.shift();
        if(o.remove){
            this.remove();
        }
        Ext.callback(o.callback, o.scope, [this]);
        this.nextFx();
    },

    getFxEl : function(){ // support for composite element fx
        if(this.shadow){  // layer element?
            return this;
        }
        return Ext.get(this.dom);
    },

    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
        var ES = YAHOO.util.Easing; opt = opt || {};
        if(typeof opt.easing == 'string'){
            opt.easing = ES[opt.easing];
        }
        var anim = opt.anim = new (animType || YAHOO.util.Anim)(
                this.dom, args,
                (opt.duration || defaultDur) || .35,
                (opt.easing || defaultEase) || ES.easeOut
        );
        anim.animateX(function(){
            Ext.callback(cb, this);
        }, this);
        return anim;
    },

    anim : function(a, o, t, d, e, cb){
        var el = this.getFxEl();
        el.queueFx(o, function(){
            var c = function(){
                Ext.callback(cb, this, [this]);
                el.afterFx(o);
            };
            this.fxanim(a, o, t, d, e, c);
        });
        return this;
    }
});

yui-ext - Copyright © 2006 Jack Slocum. | Yahoo! UI - Copyright © 2006 Yahoo! Inc.
All rights reserved.