    /**
     * @class Ext.Element
     */
    (function(){
        var doc = document,
            activeElement = null,
            isCSS1 = doc.compatMode == "CSS1Compat",
            ELEMENT = Ext.Element,
            fly = function(el){
                if (!_fly) {
                    _fly = new Ext.Element.Flyweight();
                }
                _fly.dom = el;
                return _fly;
            }, _fly;

        // If the browser does not support document.activeElement we need some assistance.
        // This covers old Safari 3.2 (4.0 added activeElement along with just about all
        // other browsers). We need this support to handle issues with old Safari.
        if (!('activeElement' in doc) && doc.addEventListener) {
            doc.addEventListener('focus',
                function (ev) {
                    if (ev && ev.target) {
                        activeElement = (ev.target == doc) ? null : ev.target;
                    }
                }, true);
        }

        /*
         * Helper function to create the function that will restore the selection.
         */
        function makeSelectionRestoreFn (activeEl, start, end) {
            return function () {
                activeEl.selectionStart = start;
                activeEl.selectionEnd = end;
            };
        }

        Ext.apply(ELEMENT, {
            isAncestor : function(p, c) {
                var ret = false;

                p = Ext.getDom(p);
                c = Ext.getDom(c);
                if (p && c) {
                    if (p.contains) {
                        return p.contains(c);
                    } else if (p.compareDocumentPosition) {
                        return !!(p.compareDocumentPosition(c) & 16);
                    } else {
                        while ((c = c.parentNode)) {
                            ret = c == p || ret;
                        }
                    }
                }
                return ret;
            },

            /**
             * Returns the active element in the DOM. If the browser supports activeElement
             * on the document, this is returned. If not, the focus is tracked and the active
             * element is maintained internally.
             * @return {HTMLElement} The active (focused) element in the document.
             */
            getActiveElement: function () {
                return doc.activeElement || activeElement;
            },

            /**
             * Creates a function to call to clean up problems with the work-around for the
             * WebKit RightMargin bug. The work-around is to add "display: 'inline-block'" to
             * the element before calling getComputedStyle and then to restore its original
             * display value. The problem with this is that it corrupts the selection of an
             * INPUT or TEXTAREA element (as in the "I-beam" goes away but ths focus remains).
             * To cleanup after this, we need to capture the selection of any such element and
             * then restore it after we have restored the display style.
             *
             * @param target {Element} The top-most element being adjusted.
             * @private
             */
            getRightMarginFixCleaner: function (target) {
                var supports = Ext.supports,
                    hasInputBug = supports.DisplayChangeInputSelectionBug,
                    hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug;

                if (hasInputBug || hasTextAreaBug) {
                    var activeEl = doc.activeElement || activeElement, // save a call
                        tag = activeEl && activeEl.tagName,
                        start,
                        end;

                    if ((hasTextAreaBug && tag == 'TEXTAREA') ||
                        (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) {
                        if (ELEMENT.isAncestor(target, activeEl)) {
                            start = activeEl.selectionStart;
                            end = activeEl.selectionEnd;

                            if (Ext.isNumber(start) && Ext.isNumber(end)) { // to be safe...
                                // We don't create the raw closure here inline because that
                                // will be costly even if we don't want to return it (nested
                                // function decls and exprs are often instantiated on entry
                                // regardless of whether execution ever reaches them):
                                return makeSelectionRestoreFn(activeEl, start, end);
                            }
                        }
                    }
                }

                return Ext.emptyFn; // avoid special cases, just return a nop
            },

            getViewWidth : function(full) {
                return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
            },

            getViewHeight : function(full) {
                return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
            },

            getDocumentHeight: function() {
                return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
            },

            getDocumentWidth: function() {
                return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
            },

            getViewportHeight: function(){
                return Ext.isIE ?
                       (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
                       self.innerHeight;
            },

            getViewportWidth : function() {
                return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
                       Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
            },

            getY : function(el) {
                return ELEMENT.getXY(el)[1];
            },

            getX : function(el) {
                return ELEMENT.getXY(el)[0];
            },

            getOffsetParent: function (el) {
                el = Ext.getDom(el);
                try {
                    // accessing offsetParent can throw "Unspecified Error" in IE6-8 (not 9)
                    return el.offsetParent;
                } catch (e) {
                    var body = document.body; // safe bet, unless...
                    return (el == body) ? null : body;
                }
            },

            getXY : function(el) {
                var p,
                    pe,
                    b,
                    bt,
                    bl,
                    dbd,
                    x = 0,
                    y = 0,
                    scroll,
                    hasAbsolute,
                    bd = (doc.body || doc.documentElement),
                    ret;

                el = Ext.getDom(el);

                if(el != bd){
                    hasAbsolute = fly(el).isStyle("position", "absolute");

                    if (el.getBoundingClientRect) {
                        try {
                            b = el.getBoundingClientRect();
                            scroll = fly(document).getScroll();
                            ret = [ Math.round(b.left + scroll.left), Math.round(b.top + scroll.top) ];
                        } catch (e) {
                            // IE6-8 can also throw from getBoundingClientRect...
                        }
                    }

                    if (!ret) {
                        for (p = el; p; p = ELEMENT.getOffsetParent(p)) {
                            pe = fly(p);
                            x += p.offsetLeft;
                            y += p.offsetTop;

                            hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");

                            if (Ext.isGecko) {
                                y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
                                x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;

                                if (p != el && !pe.isStyle('overflow','visible')) {
                                    x += bl;
                                    y += bt;
                                }
                            }
                        }

                        if (Ext.isSafari && hasAbsolute) {
                            x -= bd.offsetLeft;
                            y -= bd.offsetTop;
                        }

                        if (Ext.isGecko && !hasAbsolute) {
                            dbd = fly(bd);
                            x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
                            y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
                        }

                        p = el.parentNode;
                        while (p && p != bd) {
                            if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
                                x -= p.scrollLeft;
                                y -= p.scrollTop;
                            }
                            p = p.parentNode;
                        }
                        ret = [x,y];
                    }
                }
                return ret || [0,0];
            },

            setXY : function(el, xy) {
                (el = Ext.fly(el, '_setXY')).position();

                var pts = el.translatePoints(xy),
                    style = el.dom.style,
                    pos;

                for (pos in pts) {
                    if (!isNaN(pts[pos])) {
                        style[pos] = pts[pos] + "px";
                    }
                }
            },

            setX : function(el, x) {
                ELEMENT.setXY(el, [x, false]);
            },

            setY : function(el, y) {
                ELEMENT.setXY(el, [false, y]);
            },

            /**
             * Serializes a DOM form into a url encoded string
             * @param {Object} form The form
             * @return {String} The url encoded form
             */
            serializeForm: function(form) {
                var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
                    hasSubmit = false,
                    encoder = encodeURIComponent,
                    name,
                    data = '',
                    type,
                    hasValue;

                Ext.each(fElements, function(element){
                    name = element.name;
                    type = element.type;

                    if (!element.disabled && name) {
                        if (/select-(one|multiple)/i.test(type)) {
                            Ext.each(element.options, function(opt){
                                if (opt.selected) {
                                    hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified;
                                    data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text));
                                }
                            });
                        } else if (!(/file|undefined|reset|button/i.test(type))) {
                            if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) {
                                data += encoder(name) + '=' + encoder(element.value) + '&';
                                hasSubmit = /submit/i.test(type);
                            }
                        }
                    }
                });
                return data.substr(0, data.length - 1);
            }
        });
    })();