/**
 * @class Ext.dom.Element
 * @override Ext.dom.Element
 */
 
Ext.define('Ext.overrides.dom.Element', (function() {
    var Element, // we cannot do this yet "= Ext.dom.Element" 
        WIN = window,
        DOC = document,
        HIDDEN = 'hidden',
        ISCLIPPED = 'isClipped',
        OVERFLOW = 'overflow',
        OVERFLOWX = 'overflow-x',
        OVERFLOWY = 'overflow-y',
        ORIGINALCLIP = 'originalClip',
        HEIGHT = 'height',
        WIDTH = 'width',
        VISIBILITY = 'visibility',
        DISPLAY = 'display',
        NONE = 'none',
        OFFSETS = 'offsets',
        CLIP = 'clip',
        ORIGINALDISPLAY = 'originalDisplay',
        VISMODE = 'visibilityMode',
        ISVISIBLE = 'isVisible',
        OFFSETCLASS = Ext.baseCSSPrefix + 'hidden-offsets',
        CLIPCLASS = Ext.baseCSSPrefix + 'hidden-clip',
        boxMarkup = [
            '<div class="{0}-tl" role="presentation">',
                '<div class="{0}-tr" role="presentation">',
                    '<div class="{0}-tc" role="presentation"></div>',
                '</div>',
            '</div>',
            '<div class="{0}-ml" role="presentation">',
                '<div class="{0}-mr" role="presentation">',
                    '<div class="{0}-mc" role="presentation"></div>',
                '</div>',
            '</div>',
            '<div class="{0}-bl" role="presentation">',
                '<div class="{0}-br" role="presentation">',
                    '<div class="{0}-bc" role="presentation"></div>',
                '</div>',
            '</div>'
        ].join(''),
        scriptTagRe = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
        replaceScriptTagRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
        srcRe = /\ssrc=([\'\"])(.*?)\1/i,
        nonSpaceRe = /\S/,
        typeRe = /\stype=([\'\"])(.*?)\1/i,
        adjustDirect2DTableRe = /table-row|table-.*-group/,
        msRe = /^-ms-/,
        camelRe = /(-[a-z])/gi,
        camelReplaceFn = function(m, a) {
            return a.charAt(1).toUpperCase();
        },
        XMASKED = Ext.baseCSSPrefix + "masked",
        XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
        EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
        bodyRe = /^body/i,
        propertyCache = {},
        getVisMode = function(el){
            var data = el.getData(),
                visMode = data[VISMODE];
                
            if (visMode === undefined) {
                data[VISMODE] = visMode = Element.VISIBILITY;
            }
            return visMode;
        },
        emptyRange = DOC.createRange ? DOC.createRange() : null,
        syncContentFly;
 
    //<feature legacyBrowser> 
    if (Ext.isIE8) {
        var garbageBin = DOC.createElement('div'),
            destroyQueue = [],
 
            // prevent memory leaks in IE8 
            // see http://social.msdn.microsoft.com/Forums/ie/en-US/c76967f0-dcf8-47d0-8984-8fe1282a94f5/ie-appendchildremovechild-memory-problem?forum=iewebdevelopment 
            // This function is called to fully destroy an element on a timer so that code following the 
            // remove call can still access the element. 
            clearGarbage,
            clearGarbageFn = function() {
                var len = destroyQueue.length,
                    i;
 
                for (= 0; i < len; i++) {
                    garbageBin.appendChild(destroyQueue[i]);
                }
                garbageBin.innerHTML = '';
                destroyQueue.length = 0;
            };
            
            //<debug> 
            clearGarbageFn.$skipTimerCheck = true;
            //</debug> 
            
            clearGarbage = Ext.Function.createBuffered(clearGarbageFn, 10);
    }
    //</feature> 
 
    return {
        override: 'Ext.dom.Element',
        
        mixins: [
            'Ext.util.Animate'
        ],
 
        uses: [
            'Ext.dom.GarbageCollector',
            'Ext.dom.Fly',
            'Ext.event.publisher.MouseEnterLeave',
            'Ext.fx.Manager',
            'Ext.fx.Anim'
        ],
 
        skipGarbageCollection: false,
 
        _init: function (E) {
            Element = E; // now we can poke this into closure scope 
            
            // We want to expose destroyQueue on the prototype for testing purposes 
            //<debug> 
            if (WIN.__UNIT_TESTING__) {
                E.destroyQueue = destroyQueue;
            }
            //</debug> 
        },
 
        statics: {
            normalize: function(prop) {
                if (prop === 'float') {
                    prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';
                }
                // For '-ms-foo' we need msFoo 
                return propertyCache[prop] || (propertyCache[prop] = prop.replace(msRe, 'ms-').replace(camelRe, camelReplaceFn));
            }
        },
 
        /**
         * Convenience method for constructing a KeyMap
         * @param {String/Number/Number[]/Object} key Either a string with the keys to listen for, the numeric key code,
         * array of key codes or an object with the following options:
         * @param {Number/Array} key.key
         * @param {Boolean} key.shift
         * @param {Boolean} key.ctrl
         * @param {Boolean} key.alt
         * @param {Function} fn The function to call
         * @param {Object} [scope] The scope (`this` reference) in which the specified function is executed. Defaults to this Element.
         * @return {Ext.util.KeyMap} The KeyMap created
         */
        addKeyListener: function(key, fn, scope){
            var config;
            if(typeof key !== 'object' || Ext.isArray(key)){
                config = {
                    target: this,
                    key: key,
                    fn: fn,
                    scope: scope
                };
            } else {
                config = {
                    target: this,
                    key : key.key,
                    shift : key.shift,
                    ctrl : key.ctrl,
                    alt : key.alt,
                    fn: fn,
                    scope: scope
                };
            }
            return new Ext.util.KeyMap(config);
        },
 
        /**
         * Creates a KeyMap for this element
         * @param {Object} config The KeyMap config. See {@link Ext.util.KeyMap} for more details
         * @return {Ext.util.KeyMap} The KeyMap created
         */
        addKeyMap: function(config) {
            return new Ext.util.KeyMap(Ext.apply({
                target: this
            }, config));
        },
 
        /**
         * @private
         * Returns the fractional portion of this element's measurement in the given dimension.
         * (IE9+ only)
         * @return {Number}
         */
        adjustDirect2DDimension: function(dimension) {
            var me = this,
                dom = me.dom,
                display = me.getStyle('display'),
                inlineDisplay = dom.style.display,
                inlinePosition = dom.style.position,
                originIndex = dimension === WIDTH ? 0 : 1,
                currentStyle = dom.currentStyle,
                floating;
 
            if (display === 'inline') {
                dom.style.display = 'inline-block';
            }
 
            dom.style.position = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
 
            // floating will contain digits that appears after the decimal point 
            // if height or width are set to auto we fallback to msTransformOrigin calculation 
 
            // Use currentStyle here instead of getStyle. In some difficult to reproduce 
            // instances it resets the scrollWidth of the element 
            floating = (parseFloat(currentStyle[dimension]) || parseFloat(currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
 
            dom.style.position = inlinePosition;
 
            if (display === 'inline') {
                dom.style.display = inlineDisplay;
            }
 
            return floating;
        },
 
        /**
         * @private
         */
        afterAnimate: function() {
            var shadow = this.shadow;
 
            if (shadow && !shadow.disabled && !shadow.animate) {
                shadow.show();
            }
        },
 
        /**
         * @private
         */
        anchorAnimX: function(anchor) {
            var xName = (anchor === 'l') ? 'right' : 'left';
            this.dom.style[xName] = '0px';
        },
 
        /**
         * @private
         * process the passed fx configuration.
         */
        anim: function(config) {
            if (!Ext.isObject(config)) {
                return (config) ? {} : false;
            }
 
            var me = this,
                duration = config.duration || Ext.fx.Anim.prototype.duration,
                easing = config.easing || 'ease',
                animConfig;
 
            if (config.stopAnimation) {
                me.stopAnimation();
            }
 
            Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
 
            // Clear any 'paused' defaults. 
            Ext.fx.Manager.setFxDefaults(me.id, {
                delay: 0
            });
 
            animConfig = {
                // Pass the DOM reference. That's tested first so will be converted to an Ext.fx.Target fastest. 
                target: me.dom,
                remove: config.remove,
                alternate: config.alternate || false,
                duration: duration,
                easing: easing,
                callback: config.callback,
                listeners: config.listeners,
                iterations: config.iterations || 1,
                scope: config.scope,
                block: config.block,
                concurrent: config.concurrent,
                delay: config.delay || 0,
                paused: true,
                keyframes: config.keyframes,
                from: config.from || {},
                to: Ext.apply({}, config),
                userConfig: config
            };
            Ext.apply(animConfig.to, config.to);
 
            // Anim API properties - backward compat 
            delete animConfig.to.to;
            delete animConfig.to.from;
            delete animConfig.to.remove;
            delete animConfig.to.alternate;
            delete animConfig.to.keyframes;
            delete animConfig.to.iterations;
            delete animConfig.to.listeners;
            delete animConfig.to.target;
            delete animConfig.to.paused;
            delete animConfig.to.callback;
            delete animConfig.to.scope;
            delete animConfig.to.duration;
            delete animConfig.to.easing;
            delete animConfig.to.concurrent;
            delete animConfig.to.block;
            delete animConfig.to.stopAnimation;
            delete animConfig.to.delay;
            return animConfig;
        },
 
        /**
         * Calls `{@link #addAnimation}` and returns this Element (for call chaining). For
         * details, see `{@link #addAnimation}`.
         *
         * @param {Object} config  Configuration for {@link Ext.fx.Anim}.
         * Note that the {@link Ext.fx.Anim#to to} config is required.
         * @return {Ext.dom.Element} this
         */
        animate: function (config) {
            this.addAnimation(config);
            return this;
        },
 
        /**
         * Starts a custom animation on this Element.
         *
         * The following properties may be specified in `from`, `to`, and `keyframe` objects:
         *
         *   - `x` - The page X position in pixels.
         *   - `y` - The page Y position in pixels
         *   - `left` - The element's CSS `left` value. Units must be supplied.
         *   - `top` - The element's CSS `top` value. Units must be supplied.
         *   - `width` - The element's CSS `width` value. Units must be supplied.
         *   - `height` - The element's CSS `height` value. Units must be supplied.
         *   - `scrollLeft` - The element's `scrollLeft` value.
         *   - `scrollTop` - The element's `scrollTop` value.
         *   - `opacity` - The element's `opacity` value (between `0` and `1`).
         *
         * **Be aware** that animating an Element which is being used by an Ext Component
         * without in some way informing the Component about the changed element state will
         * result in incorrect Component behaviour. This is because the Component will be
         * using the old state of the element. To avoid this problem, it is now possible
         * to directly animate certain properties of Components.
         *
         * @param {Object} config  Configuration for {@link Ext.fx.Anim}.
         * Note that the {@link Ext.fx.Anim#to to} config is required.
         * @return {Ext.fx.Anim} The new animation.
         */
        addAnimation: function (config) {
            var me = this,
                animId = me.dom.id || Ext.id(me.dom),
                listeners, anim, end;
 
            if (!Ext.fx.Manager.hasFxBlock(animId)) {
                // Bit of gymnastics here to ensure our internal listeners get bound first 
                if (config.listeners) {
                    listeners = config.listeners;
                    delete config.listeners;
                }
                if (config.internalListeners) {
                    config.listeners = config.internalListeners;
                    delete config.internalListeners;
                }
                end = config.autoEnd;
                delete config.autoEnd;
                anim = new Ext.fx.Anim(me.anim(config));
                anim.on({
                    afteranimate: 'afterAnimate',
                    beforeanimate: 'beforeAnimate',
                    scope: me,
                    single: true
                });
                if (listeners) {
                    anim.on(listeners);
                }
                Ext.fx.Manager.queueFx(anim);
                if (end) {
                    anim.jumpToEnd();
                }
            }
 
            return anim;
        },
 
        /**
         * @private
         */
        beforeAnimate: function() {
            var shadow = this.shadow;
 
            if (shadow && !shadow.disabled && !shadow.animate) {
                shadow.hide();
            }
        },
 
        /**
         * Wraps the specified element with a special 9 element markup/CSS block that renders by default as
         * a gray container with a gradient background, rounded corners and a 4-way shadow.
         *
         * This special markup is used throughout Ext when box wrapping elements ({@link Ext.button.Button},
         * {@link Ext.panel.Panel} when {@link Ext.panel.Panel#frame frame=true}, {@link Ext.window.Window}).
         * The markup is of this form:
         *
         *     <div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div>
         *     <div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div>
         *     <div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>
         *
         * Example usage:
         *
         *     // Basic box wrap
         *     Ext.get("foo").boxWrap();
         *
         *     // You can also add a custom class and use CSS inheritance rules to customize the box look.
         *     // 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example
         *     // for how to create a custom box wrap style.
         *     Ext.get("foo").boxWrap().addCls("x-box-blue");
         *
         * @param {String} [cls='x-box'] A base CSS class to apply to the containing wrapper element.
         * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
         * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
         * @return {Ext.dom.Element} The outermost wrapping element of the created box structure.
         */
        boxWrap: function(cls) {
            cls = cls || Ext.baseCSSPrefix + 'box';
            var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "' role='presentation'>" + Ext.String.format(boxMarkup, cls) + "</div>"));
            el.selectNode('.' + cls + '-mc').appendChild(this.dom);
            return el;
        },
 
        /**
         * Removes Empty, or whitespace filled text nodes. Combines adjacent text nodes.
         * @param {Boolean} [forceReclean=false] By default the element keeps track if it has been cleaned already
         * so you can call this over and over. However, if you update the element and need to force a re-clean, you
         * can pass true.
         */
        clean: function(forceReclean) {
            var me   = this,
                dom  = me.dom,
                data = me.getData(),
                n    = dom.firstChild,
                ni   = -1,
                nx;
 
            if (data.isCleaned && forceReclean !== true) {
                return me;
            }
 
            while (n) {
                nx = n.nextSibling;
                if (n.nodeType === 3) {
                    // Remove empty/whitespace text nodes 
                    if (!(nonSpaceRe.test(n.nodeValue))) {
                        dom.removeChild(n);
                    // Combine adjacent text nodes 
                    } else if (nx && nx.nodeType === 3) {
                        n.appendData(Ext.String.trim(nx.data));
                        dom.removeChild(nx);
                        nx = n.nextSibling;
                        n.nodeIndex = ++ni;
                    }
                } else {
                    // Recursively clean 
                    Ext.fly(n, '_clean').clean();
                    n.nodeIndex = ++ni;
                }
                n = nx;
            }
 
            data.isCleaned = true;
            return me;
        },
 
        /**
         * @method
         * Empties this element. Removes all child nodes.
         */
        empty: emptyRange ? function() {
            var dom = this.dom;
 
            if (dom.firstChild) {
                emptyRange.setStartBefore(dom.firstChild);
                emptyRange.setEndAfter(dom.lastChild);
                emptyRange.deleteContents();
            }
        } : function() {
            var dom = this.dom;
 
            while (dom.lastChild) {
                dom.removeChild(dom.lastChild);
            }
        },
 
        clearListeners: function() {
            this.removeAnchor();
            this.callParent();
        },
 
        /**
         * Clears positioning back to the default when the document was loaded.
         * @param {String} [value=''] The value to use for the left, right, top, bottom.
         * You could use 'auto'.
         * @return {Ext.dom.Element} this
         */
        clearPositioning: function(value) {
            value = value || '';
            return this.setStyle({
                left : value,
                right : value,
                top : value,
                bottom : value,
                'z-index' : '',
                position : 'static'
            });
        },
 
        /**
         * Creates a proxy element of this element
         * @param {String/Object} config The class name of the proxy element or a DomHelper config object
         * @param {String/HTMLElement} [renderTo] The element or element id to render the proxy to. Defaults to: document.body.
         * @param {Boolean} [matchBox=false] True to align and size the proxy to this element now.
         * @return {Ext.dom.Element} The new proxy element
         */
        createProxy: function(config, renderTo, matchBox) {
            config = (typeof config === 'object') ? config :
                { tag: "div", role: 'presentation', cls: config };
 
            var me = this,
                proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
                                   Ext.DomHelper.insertBefore(me.dom, config, true);
 
            proxy.setVisibilityMode(Element.DISPLAY);
            proxy.hide();
            if (matchBox && me.setBox && me.getBox) { // check to make sure Element_position.js is loaded 
               proxy.setBox(me.getBox());
            }
            return proxy;
        },
 
        /**
         * Clears any opacity settings from this element. Required in some cases for IE.
         * @return {Ext.dom.Element} this
         */
        clearOpacity: function() {
            return this.setOpacity('');
        },
 
        /**
         * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
         * @return {Ext.dom.Element} this
         */
        clip: function() {
            var me = this,
                data = me.getData(),
                style;
 
            if (!data[ISCLIPPED]) {
                data[ISCLIPPED] = true;
                style = me.getStyle([OVERFLOW, OVERFLOWX, OVERFLOWY]);
                data[ORIGINALCLIP] = {
                    o: style[OVERFLOW],
                    x: style[OVERFLOWX],
                    y: style[OVERFLOWY]
                };
                me.setStyle(OVERFLOW, HIDDEN);
                me.setStyle(OVERFLOWX, HIDDEN);
                me.setStyle(OVERFLOWY, HIDDEN);
            }
            return me;
        },
 
        destroy: function() {
            var me = this,
                dom = me.dom,
                data = me.peekData(),
                maskEl, maskMsg;
 
            if (dom) {
                if (me.isAnimate) {
                    me.stopAnimation(true);
                }
                
                me.removeAnchor();
            }
            
            if (me.deferredFocusTimer) {
                Ext.undefer(me.deferredFocusTimer);
                me.deferredFocusTimer = null;
            }
 
            me.callParent();
 
            //<feature legacyBrowser> 
            // prevent memory leaks in IE8 
            // see http://social.msdn.microsoft.com/Forums/ie/en-US/c76967f0-dcf8-47d0-8984-8fe1282a94f5/ie-appendchildremovechild-memory-problem?forum=iewebdevelopment 
            // must not be document, documentElement, body or window object 
            // Have to use != instead of !== for IE8 or it will not recognize that the window 
            // objects are equal 
            if (dom && Ext.isIE8 && (dom.window != dom) && (dom.nodeType !== 9) &&
                    (dom.tagName !== 'BODY') && (dom.tagName !== 'HTML')) {
                destroyQueue[destroyQueue.length] = dom;
 
 
                // Will perform extra IE8 cleanup in 10 milliseconds 
                // see http://social.msdn.microsoft.com/Forums/ie/en-US/c76967f0-dcf8-47d0-8984-8fe1282a94f5/ie-appendchildremovechild-memory-problem?forum=iewebdevelopment 
                clearGarbage();
            }
            //</feature> 
 
            if (data) {
                maskEl = data.maskEl;
                maskMsg = data.maskMsg;
 
                if (maskEl) {
                    maskEl.destroy();
                }
 
                if (maskMsg) {
                    maskMsg.destroy();
                }
            }
        },
 
        /**
         * Convenience method for setVisibilityMode(Element.DISPLAY).
         * @param {String} [display] What to set display to when visible
         * @return {Ext.dom.Element} this
         */
        enableDisplayMode : function(display) {
            var me = this;
 
            me.setVisibilityMode(Element.DISPLAY);
 
            if (display !== undefined) {
                me.getData()[ORIGINALDISPLAY] = display;
            }
 
            return me;
        },
 
        /**
         * Fade an element in (from transparent to opaque). The ending opacity can be specified using the `opacity`
         * config option. Usage:
         *
         *     // default: fade in from opacity 0 to 100%
         *     el.fadeIn();
         *
         *     // custom: fade in from opacity 0 to 75% over 2 seconds
         *     el.fadeIn({ opacity: .75, duration: 2000});
         *
         *     // common config options shown with default values
         *     el.fadeIn({
         *         opacity: 1, //can be any value between 0 and 1 (e.g. .5)
         *         easing: 'easeOut',
         *         duration: 500
         *     });
         *
         * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
         * @return {Ext.dom.Element} The Element
         */
        fadeIn: function(options) {
            var me = this,
                dom = me.dom,
                animFly = new Ext.dom.Fly();
                
            me.animate(Ext.apply({}, options, {
                opacity: 1,
                internalListeners: {
                    beforeanimate: function(anim) {
                        // Reattach to the DOM in case the caller animated a Fly 
                        // in which case the dom reference will have changed by now. 
                        animFly.attach(dom);
 
                        // restore any visibility/display that may have  
                        // been applied by a fadeout animation 
                        if (animFly.isStyle('display', 'none')) {
                            animFly.setDisplayed('');
                        } else {
                            animFly.show();
                        } 
                    }
                }
            }));
            return this;
        },
 
        /**
         * Fade an element out (from opaque to transparent). The ending opacity can be specified using the `opacity`
         * config option. Note that IE may require `useDisplay:true` in order to redisplay correctly.
         * Usage:
         *
         *     // default: fade out from the element's current opacity to 0
         *     el.fadeOut();
         *
         *     // custom: fade out from the element's current opacity to 25% over 2 seconds
         *     el.fadeOut({ opacity: .25, duration: 2000});
         *
         *     // common config options shown with default values
         *     el.fadeOut({
         *         opacity: 0, //can be any value between 0 and 1 (e.g. .5)
         *         easing: 'easeOut',
         *         duration: 500,
         *         remove: false,
         *         useDisplay: false
         *     });
         *
         * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
         * @return {Ext.dom.Element} The Element
         */
        fadeOut: function(options) {
            var me = this,
                dom = me.dom,
                animFly = new Ext.dom.Fly();
                
            options = Ext.apply({
                opacity: 0,
                internalListeners: {
                    afteranimate: function(anim) {
                        if (anim.to.opacity === 0) {
                            // Reattach to the DOM in case the caller animated a Fly 
                            // in which case the dom reference will have changed by now. 
                            animFly.attach(dom);
 
                            // Reattach to the DOM in case the caller animated a Fly 
                            // in which case the dom reference will have changed by now. 
                            animFly.attach(dom);
                            if (options.useDisplay) {
                                animFly.setDisplayed(false);
                            } else {
                                animFly.hide();
                            }
                        }         
                    }
                }
            }, options);
            me.animate(options);
            return me;
        },
 
        /**
         * @private
         */
        fixDisplay: function(){
            var me = this;
            if (me.isStyle(DISPLAY, NONE)) {
                me.setStyle(VISIBILITY, HIDDEN);
                me.setStyle(DISPLAY, me._getDisplay()); // first try reverting to default 
                if (me.isStyle(DISPLAY, NONE)) { // if that fails, default to block 
                    me.setStyle(DISPLAY, "block");
                }
            }
        },
 
        /**
         * Shows a ripple of exploding, attenuating borders to draw attention to an Element. Usage:
         *
         *     // default: a single light blue ripple
         *     el.frame();
         *
         *     // custom: 3 red ripples lasting 3 seconds total
         *     el.frame("#ff0000", 3, { duration: 3000 });
         *
         *     // common config options shown with default values
         *     el.frame("#C3DAF9", 1, {
         *         duration: 1000 // duration of each individual ripple.
         *         // Note: Easing is not configurable and will be ignored if included
         *     });
         *
         * @param {String} [color='#C3DAF9'] The hex color value for the border.
         * @param {Number} [count=1] The number of ripples to display.
         * @param {Object} [obj] Object literal with any of the {@link Ext.fx.Anim} config options
         * @return {Ext.dom.Element} The Element
         */
        frame: function(color, count, obj){
            var me = this,
                dom = me.dom,
                animFly = new Ext.dom.Fly(),
                beforeAnim;
 
            color = color || '#C3DAF9';
            count = count || 1;
            obj = obj || {};
 
            beforeAnim = function() {
                var animScope = this,
                    box,
                    proxy, proxyAnim;
 
                // Reattach to the DOM in case the caller animated a Fly 
                // in which case the dom reference will have changed by now. 
                animFly.attach(dom);
                animFly.show();
                box = animFly.getBox();
                proxy = Ext.getBody().createChild({
                    role: 'presentation',
                    id: animFly.dom.id + '-anim-proxy',
                    style: {
                        position : 'absolute',
                        'pointer-events': 'none',
                        'z-index': 35000,
                        border : '0px solid ' + color
                    }
                });
                
                proxyAnim = new Ext.fx.Anim({
                    target: proxy,
                    duration: obj.duration || 1000,
                    iterations: count,
                    from: {
                        top: box.y,
                        left: box.x,
                        borderWidth: 0,
                        opacity: 1,
                        height: box.height,
                        width: box.width
                    },
                    to: {
                        top: box.y - 20,
                        left: box.x - 20,
                        borderWidth: 10,
                        opacity: 0,
                        height: box.height + 40,
                        width: box.width + 40
                    }
                });
                proxyAnim.on('afteranimate', function() {
                    proxy.destroy();
                    // kill the no-op element animation created below 
                    animScope.end();
                });
            };
 
            me.animate({
                // See "A Note About Wrapped Animations" at the top of this class: 
                duration: (Math.max(obj.duration, 500) * 2) || 2000,
                listeners: {
                    beforeanimate: {
                        fn: beforeAnim
                    }
                },
                callback: obj.callback,
                scope: obj.scope
            });
            return me;
        },
 
        /**
         * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like `#fff`)
         * and valid values are convert to standard 6 digit hex color.
         * @param {String} attr The css attribute
         * @param {String} defaultValue The default value to use when a valid color isn't found
         * @param {String} [prefix] defaults to #. Use an empty string when working with
         * color anims.
         * @private
         */
        getColor: function(attr, defaultValue, prefix) {
            var v = this.getStyle(attr),
                color = prefix || prefix === '' ? prefix : '#',
                h, len, i=0;
 
            if (!|| (/transparent|inherit/.test(v))) {
                return defaultValue;
            }
            if (/^r/.test(v)) {
                 v = v.slice(4, v.length - 1).split(',');
                 len = v.length;
                 for (; i<len; i++) {
                    h = parseInt(v[i], 10);
                    color += (< 16 ? '0' : '') + h.toString(16);
                }
            } else {
                v = v.replace('#', '');
                color += v.length === 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
            }
            return(color.length > 5 ? color.toLowerCase() : defaultValue);
        },
 
        /**
         * Gets this element's {@link Ext.ElementLoader ElementLoader}
         * @return {Ext.ElementLoader} The loader
         */
        getLoader: function() {
            var me = this,
                data = me.getData(),
                loader = data.loader;
 
            if (!loader) {
                data.loader = loader = new Ext.ElementLoader({
                    target: me
                });
            }
            return loader;
        },
 
        /**
         * Gets an object with all CSS positioning properties. Useful along with
         * `setPositioning` to get snapshot before performing an update and then restoring
         * the element.
         * @param {Boolean} [autoPx=false] true to return pixel values for "auto" styles.
         * @return {Object}
         */
        getPositioning: function(autoPx){
            var styles = this.getStyle(['left', 'top', 'position', 'z-index']),
                dom = this.dom;
 
            if(autoPx) {
                if(styles.left === 'auto') {
                    styles.left = dom.offsetLeft + 'px';
                }
                if(styles.top === 'auto') {
                    styles.top = dom.offsetTop + 'px';
                }
            }
 
            return styles;
        },
 
        /**
         * Slides the element while fading it out of view. An anchor point can be optionally passed to set the ending point
         * of the effect. Usage:
         *
         *     // default: slide the element downward while fading out
         *     el.ghost();
         *
         *     // custom: slide the element out to the right with a 2-second duration
         *     el.ghost('r', { duration: 2000 });
         *
         *     // common config options shown with default values
         *     el.ghost('b', {
         *         easing: 'easeOut',
         *         duration: 500
         *     });
         *
         * @param {String} [anchor] One of the valid {@link Ext.fx.Anim} anchor positions (defaults to bottom: 'b')
         * @param {Object} [options] Object literal with any of the {@link Ext.fx.Anim} config options
         * @return {Ext.dom.Element} The Element
         */
        ghost: function(anchor, options) {
            var me = this,
                dom = me.dom,
                animFly = new Ext.dom.Fly(),
                beforeAnim;
 
            anchor = anchor || "b";
            beforeAnim = function() {
                // Reattach to the DOM in case the caller animated a Fly 
                // in which case the dom reference will have changed by now. 
                animFly.attach(dom);
 
                var width = animFly.getWidth(),
                    height = animFly.getHeight(),
                    xy = animFly.getXY(),
                    position = animFly.getPositioning(),
                    to = {
                        opacity: 0
                    };
 
                switch (anchor) {
                    case 't':
                        to.y = xy[1] - height;
                        break;
                    case 'l':
                        to.x = xy[0] - width;
                        break;
                    case 'r':
                        to.x = xy[0] + width;
                        break;
                    case 'b':
                        to.y = xy[1] + height;
                        break;
                    case 'tl':
                        to.x = xy[0] - width;
                        to.y = xy[1] - height;
                        break;
                    case 'bl':
                        to.x = xy[0] - width;
                        to.y = xy[1] + height;
                        break;
                    case 'br':
                        to.x = xy[0] + width;
                        to.y = xy[1] + height;
                        break;
                    case 'tr':
                        to.x = xy[0] + width;
                        to.y = xy[1] - height;
                        break;
                }
                this.to = to;
                this.on('afteranimate', function () {
                    // Reattach to the DOM in case the caller animated a Fly 
                    // in which case the dom reference will have changed by now. 
                    animFly.attach(dom);
 
                    if (animFly) {
                        animFly.hide();
                        animFly.clearOpacity();
                        animFly.setPositioning(position);
                    }
                });
            };
 
            me.animate(Ext.applyIf(options || {}, {
                duration: 500,
                easing: 'ease-out',
                listeners: {
                    beforeanimate: beforeAnim
                }
            }));
            return me;
        },
 
        //<feature legacyBrowser> 
        getTextSelection: function () {
            var ret = this.callParent();
 
            if (typeof ret[0] !== 'number') {
                var dom = this.dom;
                var doc = dom.ownerDocument;
                var range = doc.selection.createRange();
                var textRange = dom.createTextRange();
 
                textRange.setEndPoint('EndToStart', range);
 
                ret[0] = textRange.text.length;
                ret[1] = ret[0] + range.text.length;
            }
 
            return ret;
        },
        //</feature> 
 
        /**
         * Hide this element - Uses display mode to determine whether to use "display",
         * "visibility", "offsets", or "clip". See {@link #setVisible}.
         * @param {Boolean/Object} [animate] true for the default animation or a standard
         * Element animation config object
         * @return {Ext.dom.Element} this
         */
        hide: function(animate){
            // hideMode override 
            if (typeof animate === 'string'){
                this.setVisible(false, animate);
                return this;
            }
            this.setVisible(false, this.anim(animate));
            return this;
        },
 
        /**
         * Highlights the Element by setting a color (applies to the background-color by default, but can be changed using
         * the "attr" config option) and then fading back to the original color. If no original color is available, you
         * should provide the "endColor" config option which will be cleared after the animation. Usage:
         *
         *     // default: highlight background to yellow
         *     el.highlight();
         *
         *     // custom: highlight foreground text to blue for 2 seconds
         *     el.highlight("0000ff", { attr: 'color', duration: 2000 });
         *
         *     // common config options shown with default values
         *     el.highlight("ffff9c", {
         *         attr: "backgroundColor", //can be any valid CSS property (attribute) that supports a color value
         *         endColor: (current color) or "ffffff",
         *         easing: 'easeIn',
         *         duration: 1000
         *     });
         *
         * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading #
         * (defaults to yellow: 'ffff9c')
         * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
         * @return {Ext.dom.Element} The Element
         */
        highlight: function(color, options) {
            var me = this,
                dom = me.dom,
                from = {},
                animFly = new Ext.dom.Fly(),
                restore, to, attr, lns, event, fn;
 
            options = options || {};
            lns = options.listeners || {};
            attr = options.attr || 'backgroundColor';
            from[attr] = color || 'ffff9c';
 
            if (!options.to) {
                to = {};
                to[attr] = options.endColor || me.getColor(attr, 'ffffff', '');
            }
            else {
                to = options.to;
            }
 
            // Don't apply directly on lns, since we reference it in our own callbacks below 
            options.listeners = Ext.apply(Ext.apply({}, lns), {
                beforeanimate: function() {
                    // Reattach to the DOM in case the caller animated a Fly 
                    // in which case the dom reference will have changed by now. 
                    animFly.attach(dom);
                    
                    restore = dom.style[attr];
                    animFly.clearOpacity();
                    animFly.show();
 
                    event = lns.beforeanimate;
                    if (event) {
                        fn = event.fn || event;
                        return fn.apply(event.scope || lns.scope || WIN, arguments);
                    }
                },
                afteranimate: function() {
                    if (dom) {
                        dom.style[attr] = restore;
                    }
 
                    event = lns.afteranimate;
                    if (event) {
                        fn = event.fn || event;
                        fn.apply(event.scope || lns.scope || WIN, arguments);
                    }
                }
            });
 
            me.animate(Ext.apply({}, options, {
                duration: 1000,
                easing: 'ease-in',
                from: from,
                to: to
            }));
            return me;
        },
 
        /**
         * Initializes a {@link Ext.dd.DD} drag drop object for this element.
         * @param {String} group The group the DD object is member of
         * @param {Object} config The DD config object
         * @param {Object} overrides An object containing methods to override/implement on the DD object
         * @return {Ext.dd.DD} The DD object
         */
        initDD: function(group, config, overrides){
            var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
            return Ext.apply(dd, overrides);
        },
 
        /**
         * Initializes a {@link Ext.dd.DDProxy} object for this element.
         * @param {String} group The group the DDProxy object is member of
         * @param {Object} config The DDProxy config object
         * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
         * @return {Ext.dd.DDProxy} The DDProxy object
         */
        initDDProxy: function(group, config, overrides){
            var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
            return Ext.apply(dd, overrides);
        },
 
        /**
         * Initializes a {@link Ext.dd.DDTarget} object for this element.
         * @param {String} group The group the DDTarget object is member of
         * @param {Object} config The DDTarget config object
         * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
         * @return {Ext.dd.DDTarget} The DDTarget object
         */
        initDDTarget: function(group, config, overrides){
            var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
            return Ext.apply(dd, overrides);
        },
 
        /**
         * Returns true if this element is masked. Also re-centers any displayed message
         * within the mask.
         *
         * @param {Boolean} [deep] Go up the DOM hierarchy to determine if any parent
         * element is masked.
         *
         * @return {Boolean}
         */
        isMasked: function(deep) {
            var me = this,
                data = me.getData(),
                maskEl = data.maskEl,
                maskMsg = data.maskMsg,
                hasMask = false,
                parent;
 
            if (maskEl && maskEl.isVisible()) {
                if (maskMsg) {
                    maskMsg.center(me);
                }
                hasMask = true;
            }
            else if (deep) {
                parent = me.findParentNode();
                
                if (parent) {
                    return Ext.fly(parent).isMasked(deep);
                }
            }
            
            return hasMask;
        },
 
        /**
         * Direct access to the Ext.ElementLoader {@link Ext.ElementLoader#method-load} method.
         * The method takes the same object parameter as {@link Ext.ElementLoader#method-load}
         * @param {Object} options a options object for Ext.ElementLoader {@link Ext.ElementLoader#method-load}
         * @return {Ext.dom.Element} this
         */
        load: function(options) {
            this.getLoader().load(options);
            return this;
        },
 
        /**
         * Puts a mask over this element to disable user interaction.
         * This method can only be applied to elements which accept child nodes. Use
         * {@link #unmask} to remove the mask.
         *
         * @param {String} [msg] A message to display in the mask
         * @param {String} [msgCls] A css class to apply to the msg element
         * @param {Number} elHeight (private) Passed by AbstractComponent.mask to avoid the need to interrogate the DOM to get the height
         * @return {Ext.dom.Element} The mask element
         */
        mask: function (msg, msgCls, elHeight) {
            var me = this,
                dom = me.dom,
                data = me.getData(),
                maskEl = data.maskEl,
                maskMsg;
 
            if (!(bodyRe.test(dom.tagName) && me.getStyle('position') === 'static')) {
                me.addCls(XMASKEDRELATIVE);
            }
 
            // We always needs to recreate the mask since the DOM element may have been re-created 
            if (maskEl) {
                maskEl.destroy();
            }
 
            maskEl = Ext.DomHelper.append(dom, {
                role: 'presentation',
                cls : Ext.baseCSSPrefix + "mask " + Ext.baseCSSPrefix + "border-box",
                children: {
                    role: 'presentation',
                    cls : msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG,
                    cn  : {
                        tag: 'div',
                        role: 'presentation',
                        cls: Ext.baseCSSPrefix + 'mask-msg-inner',
                        cn: {
                            tag: 'div',
                            role: 'presentation',
                            cls: Ext.baseCSSPrefix + 'mask-msg-text',
                            html: msg || ''
                        }
                    }
                }
            }, true);
            
            maskMsg = Ext.fly(maskEl.dom.firstChild);
 
            data.maskEl = maskEl;
 
            me.addCls(XMASKED);
            maskEl.setDisplayed(true);
 
            if (typeof msg === 'string') {
                maskMsg.setDisplayed(true);
                maskMsg.center(me);
            } else {
                maskMsg.setDisplayed(false);
            }
 
            if (dom === DOC.body) {
                maskEl.addCls(Ext.baseCSSPrefix + 'mask-fixed');
            }
            
            // When masking the body, don't touch its tabbable state 
            me.saveTabbableState({
                skipSelf: dom === DOC.body
            });
 
            // ie will not expand full height automatically 
            if (Ext.isIE9m && dom !== DOC.body && me.isStyle('height', 'auto')) {
                maskEl.setSize(undefined, elHeight || me.getHeight());
            }
            
            return maskEl;
        },
 
        /**
         * Fades the element out while slowly expanding it in all directions. When the effect is completed, the element will
         * be hidden (visibility = 'hidden') but block elements will still take up space in the document. Usage:
         *
         *     // default
         *     el.puff();
         *
         *     // common config options shown with default values
         *     el.puff({
         *         easing: 'easeOut',
         *         duration: 500,
         *         useDisplay: false
         *     });
         *
         * @param {Object} obj (optional) Object literal with any of the {@link Ext.fx.Anim} config options
         * @return {Ext.dom.Element} The Element
         */
        puff: function(obj) {
            var me = this,
                dom = me.dom,
                animFly = new Ext.dom.Fly(),
                beforeAnim,
                box = me.getBox(),
                originalStyles = me.getStyle(['width', 'height', 'left', 'right', 'top', 'bottom', 'position', 'z-index', 'font-size', 'opacity'], true);
 
            obj = Ext.applyIf(obj || {}, {
                easing: 'ease-out',
                duration: 500,
                useDisplay: false
            });
 
            beforeAnim = function() {
                // Reattach to the DOM in case the caller animated a Fly 
                // in which case the dom reference will have changed by now. 
                animFly.attach(dom);
                
                animFly.clearOpacity();
                animFly.show();
                this.to = {
                    width: box.width * 2,
                    height: box.height * 2,
                    x: box.x - (box.width / 2),
                    y: box.y - (box.height /2),
                    opacity: 0,
                    fontSize: '200%'
                };
                this.on('afteranimate',function() {
                    // Reattach to the DOM in case the caller animated a Fly 
                    // in which case the dom reference will have changed by now. 
                    animFly.attach(dom);
 
                    if (obj.useDisplay) {
                        animFly.setDisplayed(false);
                    } else {
                        animFly.hide();
                    }
                    animFly.setStyle(originalStyles);
                    Ext.callback(obj.callback, obj.scope);
                });
            };
 
            me.animate({
                duration: obj.duration,
                easing: obj.easing,
                listeners: {
                    beforeanimate: {
                        fn: beforeAnim
                    }
                }
            });
            return me;
        },
 
        //<feature legacyBrowser> 
        // private 
        // used to ensure the mouseup event is captured if it occurs outside of the 
        // window in IE9m.  The only reason this method exists, (vs just calling 
        // el.dom.setCapture() directly) is so that we can override it to emptyFn 
        // during testing because setCapture() can wreak havoc on emulated mouse events 
        // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx 
        setCapture: function() {
            var dom = this.dom;
            if (Ext.isIE9m && dom.setCapture) {
                dom.setCapture();
            }
        },
        //</feature> 
 
        /**
         * Set the height of this Element.
         * 
         *     // change the height to 200px and animate with default configuration
         *     Ext.fly('elementId').setHeight(200, true);
         *
         *     // change the height to 150px and animate with a custom configuration
         *     Ext.fly('elId').setHeight(150, {
         *         duration : 500, // animation will have a duration of .5 seconds
         *         // will change the content to "finished"
         *         callback: function(){ this.setHtml("finished"); }
         *     });
         *     
         * @param {Number/String} height The new height. This may be one of:
         *
         * - A Number specifying the new height in pixels.
         * - A String used to set the CSS height style. Animation may **not** be used.
         *     
         * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
         * the default animation (`{duration: 350, easing: 'ease-in'}`)
         * @return {Ext.dom.Element} this
         */
        setHeight: function(height, animate) {
            var me = this;
 
            if (!animate || !me.anim) {
                me.callParent(arguments);
            }
            else {
                if (!Ext.isObject(animate)) {
                    animate = {};
                }
                me.animate(Ext.applyIf({
                    to: {
                        height: height
                    }
                }, animate));
            }
 
            return me;
        },
 
        /**
         * Removes "vertical" state from this element (reverses everything done
         * by {@link #setVertical}).
         * @private
         */
        setHorizontal: function() {
            var me = this,
                cls = me.verticalCls;
 
            delete me.vertical;
            if (cls) {
                delete me.verticalCls;
                me.removeCls(cls);
            }
 
            // delete the inverted methods and revert to inheriting from the prototype  
            delete me.setWidth;
            delete me.setHeight;
            if (!Ext.isIE8) {
                delete me.getWidth;
                delete me.getHeight;
            }
 
            // revert to inheriting styleHooks from the prototype 
            delete me.styleHooks;
        },
 
        /**
         * Updates the *text* value of this element.
         * Replaces the content of this element with a *single text node* containing the passed text.
         * @param {String} text The text to display in this Element.
         */
        updateText: function(text) {
            var me = this,
                dom,
                textNode;
 
            if (dom) {
                textNode = dom.firstChild;
                if (!textNode || (textNode.nodeType !== 3 || textNode.nextSibling)) {
                    textNode = DOC.createTextNode();
                    me.empty();
                    dom.appendChild(textNode);
                }
                if (text) {
                    textNode.data = text;
                }
            }
        },
 
        /**
         * Updates the innerHTML of this element, optionally searching for and processing scripts.
         * @param {String} html The new HTML
         * @param {Boolean} [loadScripts] Pass `true` to look for and process scripts.
         * @param {Function} [callback] For async script loading you can be notified when the update completes.
         * @param {Object} [scope=`this`] The scope (`this` reference) in which to execute the callback.
         * 
         * Also used as the scope for any *inline* script source if the `loadScripts` parameter is `true`.
         * Scripts with a `src` attribute cannot be executed in this scope.
         *
         * Defaults to this Element.
         * @return {Ext.dom.Element} this
         */
        setHtml: function(html, loadScripts, callback, scope) {
            var me = this,
                id,
                dom,
                interval;
 
            if (!me.dom) {
                return me;
            }
            html = html || '';
            dom = me.dom;
 
            if (loadScripts !== true) {
                dom.innerHTML = html;
                Ext.callback(callback, me);
                return me;
            }
 
            id  = Ext.id();
            html += '<span id="' + id + '" role="presentation"></span>';
 
            interval = Ext.interval(function() {
                var hd, match, attrs, srcMatch, typeMatch, el, s;
 
                if (!(el = DOC.getElementById(id))) {
                    return false;
                }
 
                Ext.uninterval(interval);
                Ext.removeNode(el);
                hd = Ext.getHead().dom;
 
                while ((match = scriptTagRe.exec(html))) {
                    attrs = match[1];
                    srcMatch = attrs ? attrs.match(srcRe) : false;
 
                    if (srcMatch && srcMatch[2]) {
                       s = DOC.createElement("script");
                       s.src = srcMatch[2];
                       typeMatch = attrs.match(typeRe);
                       if (typeMatch && typeMatch[2]) {
                           s.type = typeMatch[2];
                       }
                       hd.appendChild(s);
                    }
                    else if (match[2] && match[2].length > 0) {
                        if (scope) {
                            Ext.functionFactory(match[2]).call(scope);
                        } else {
                            Ext.globalEval(match[2]);
                        }
                    }
                }
 
                Ext.callback(callback, scope || me);
            }, 20);
 
            dom.innerHTML = html.replace(replaceScriptTagRe, '');
            return me;
        },
 
        /**
         * Set the opacity of the element
         * @param {Number} opacity The new opacity. 0 = transparent, .5 = 50% visible, 1 = fully visible, etc
         * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
         * the default animation (`{duration: 350, easing: 'ease-in'}`)
         * @return {Ext.dom.Element} this
         */
        setOpacity: function(opacity, animate) {
            var me = this;
 
            if (!me.dom) {
                return me;
            }
 
            if (!animate || !me.anim) {
                me.setStyle('opacity', opacity);
            }
            else {
                if (typeof animate != 'object') {
                    animate = {
                        duration: 350,
                        easing: 'ease-in'
                    };
                }
 
                me.animate(Ext.applyIf({
                    to: {
                        opacity: opacity
                    }
                }, animate));
            }
            return me;
        },
 
        /**
         * Set positioning with an object returned by `getPositioning`.
         * @param {Object} pc 
         * @return {Ext.dom.Element} this
         */
        setPositioning: function(pc) {
            return this.setStyle(pc);
        },
 
        /**
         * Changes this Element's state to "vertical" (rotated 90 or 270 degrees).
         * This involves inverting the getters and setters for height and width,
         * and applying hooks for rotating getters and setters for border/margin/padding.
         * (getWidth becomes getHeight and vice versa), setStyle and getStyle will
         * also return the inverse when height or width are being operated on.
         * 
         * @param {Number} angle the angle of rotation - either 90 or 270
         * @param {String} cls an optional css class that contains the required
         * styles for switching the element to vertical orientation. Omit this if
         * the element already contains vertical styling.  If cls is provided,
         * it will be removed from the element when {@link #setHorizontal} is called.
         * @private
         */
        setVertical: function(angle, cls) {
            var me = this,
                proto = Element.prototype;
 
            me.vertical = true;
            if (cls) {
                me.addCls(me.verticalCls = cls);
            }
 
            me.setWidth = proto.setHeight;
            me.setHeight = proto.setWidth;
            if (!Ext.isIE8) {
                // In browsers that use CSS3 transforms we must invert getHeight and 
                // get Width. In IE8 no adjustment is needed because we use 
                // a BasicImage filter to rotate the element and the element's 
                // offsetWidth and offsetHeight are automatically inverted. 
                me.getWidth = proto.getHeight;
                me.getHeight = proto.getWidth;
            }
 
            // Switch to using the appropriate vertical style hooks 
            me.styleHooks = (angle === 270) ?
                proto.verticalStyleHooks270 : proto.verticalStyleHooks90;
        },
 
        /**
         * Set the size of this Element. If animation is true, both width and height will be animated concurrently.
         * @param {Number/String} width The new width. This may be one of:
         *
         * - A Number specifying the new width in pixels.
         * - A String used to set the CSS width style. Animation may **not** be used.
         * - A size object in the format `{width: widthValue, height: heightValue}`.
         *
         * @param {Number/String} height The new height. This may be one of:
         *
         * - A Number specifying the new height in  pixels.
         * - A String used to set the CSS height style. Animation may **not** be used.
         *
         * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
         * the default animation (`{duration: 350, easing: 'ease-in'}`)
         *
         * @return {Ext.dom.Element} this
         */
        setSize: function(width, height, animate) {
            var me = this;
 
            if (Ext.isObject(width)) { // in case of object from getSize() 
                animate = height;
                height = width.height;
                width = width.width;
            }
 
            if (!animate || !me.anim) {
                me.dom.style.width = Element.addUnits(width);
                me.dom.style.height = Element.addUnits(height);
 
                if (me.shadow || me.shim) {
                    me.syncUnderlays();
                }
            }
            else {
                if (animate === true) {
                    animate = {};
                }
                me.animate(Ext.applyIf({
                    to: {
                        width: width,
                        height: height
                    }
                }, animate));
            }
 
            return me;
        },
 
        /**
         * Sets the visibility of the element (see details). If the visibilityMode is set
         * to Element.DISPLAY, it will use the display property to hide the element,
         * otherwise it uses visibility. The default is to hide and show using the
         * visibility property.
         *
         * @param {Boolean} visible Whether the element is visible
         * @param {Boolean/Object} [animate] True for the default animation,
         * or a standard Element animation config object.
         *
         * @return {Ext.dom.Element} this
         */
        setVisible: function(visible, animate) {
            var me = this,
                dom = me.dom,
                animFly,
                visMode = getVisMode(me);
 
            // hideMode string override 
            if (typeof animate === 'string') {
                switch (animate) {
                    case DISPLAY:
                        visMode = Element.DISPLAY;
                        break;
                    case VISIBILITY:
                        visMode = Element.VISIBILITY;
                        break;
                    case OFFSETS:
                        visMode = Element.OFFSETS;
                        break;
                    case CLIP:
                        visMode = Element.CLIP;
                        break;
                }
                me.setVisibilityMode(visMode);
                animate = false;
            }
 
            if (!animate || !me.anim) {
                if (visMode === Element.DISPLAY) {
                    return me.setDisplayed(visible);
                }
                else if (visMode === Element.OFFSETS) {
                    me[visible ? 'removeCls' : 'addCls'](OFFSETCLASS);
                }
                else if (visMode === Element.CLIP) {
                    me[visible ? 'removeCls' : 'addCls'](CLIPCLASS);
                }
                else if (visMode === Element.VISIBILITY) {
                    me.fixDisplay();
                    // Show by clearing visibility style. Explicitly setting to "visible" overrides parent visibility setting 
                    dom.style.visibility = visible ? '' : HIDDEN;
                }
            } else {
                // closure for composites 
                if (visible) {
                    me.setOpacity(0.01);
                    me.setVisible(true);
                }
                if (!Ext.isObject(animate)) {
                    animate = {
                        duration: 350,
                        easing: 'ease-in'
                    };
                }
                animFly = new Ext.dom.Fly(),
                me.animate(Ext.applyIf({
                    callback: function() {
                        if (!visible) {
                            
                            // Grab the dom again, since the reference may have changed if we use fly 
                            animFly.attach(dom).setVisible(false).setOpacity(1);
                        }
                    },
                    to: {
                        opacity: (visible) ? 1 : 0
                    }
                }, animate));
            }
            me.getData()[ISVISIBLE] = visible;
 
            if (me.shadow || me.shim) {
                me.setUnderlaysVisible(visible);
            }
 
            return me;
        },
 
        /**
         * Set the width of this Element.
         * 
         *     // change the width to 200px and animate with default configuration
         *     Ext.fly('elementId').setWidth(200, true);
         *
         *     // change the width to 150px and animate with a custom configuration
         *     Ext.fly('elId').setWidth(150, {
         *         duration : 500, // animation will have a duration of .5 seconds
         *         // will change the content to "finished"
         *         callback: function(){ this.setHtml("finished"); }
         *     });
         *     
         * @param {Number/String} width The new width. This may be one of:
         *
         * - A Number specifying the new width in pixels.
         * - A String used to set the CSS width style. Animation may **not** be used.
         * 
         * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
         * the default animation (`{duration: 350, easing: 'ease-in'}`)
         * @return {Ext.dom.Element} this
         */
        setWidth: function(width, animate) {
            var me = this;
            if (!animate || !me.anim) {
                me.callParent(arguments);
            }
            else {
                if (!Ext.isObject(animate)) {
                    animate = {};
                }
                me.animate(Ext.applyIf({
                    to: {
                        width: width
                    }
                }, animate));
            }
            return me;
        },
 
        setX: function(x, animate) {
            return this.setXY([x, this.getY()], animate);
        }