    /**
     * @class Ext.Element
     */
    (function(){

    var ELEMENT = Ext.Element,
        LEFT = "left",
        RIGHT = "right",
        TOP = "top",
        BOTTOM = "bottom",
        POSITION = "position",
        STATIC = "static",
        RELATIVE = "relative",
        AUTO = "auto",
        ZINDEX = "z-index";

    Ext.override(Ext.Element, {
        /**
          * Gets the current X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
          * @return {Number} The X position of the element
          */
        getX : function(){
            return ELEMENT.getX(this.dom);
        },

        /**
          * Gets the current Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
          * @return {Number} The Y position of the element
          */
        getY : function(){
            return ELEMENT.getY(this.dom);
        },

        /**
          * Gets the current position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
          * @return {Number[]} The XY position of the element
          */
        getXY : function(){
            return ELEMENT.getXY(this.dom);
        },

        /**
          * Returns the offsets of this element from the passed element. Both element must be part of the DOM tree and not have display:none to have page coordinates.
          * @param {String/HTMLElement/Ext.Element} element The element to get the offsets from.
          * @return {Number[]} The XY page offsets (e.g. [100, -200])
          */
        getOffsetsTo : function(el){
            var o = this.getXY(),
                e = Ext.fly(el, '_internal').getXY();
            return [o[0]-e[0],o[1]-e[1]];
        },

        /**
         * Sets the X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
         * @param {Number} The X position of the element
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setX : function(x, animate){
            return this.setXY([x, this.getY()], animate);
        },

        /**
         * Sets the Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
         * @param {Number} The Y position of the element
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setY : function(y, animate){
            return this.setXY([this.getX(), y], animate);
        },

        /**
         * Sets the element's left position directly using CSS style (instead of {@link #setX}).
         * @param {String} left The left CSS property value
         * @return {Ext.Element} this
         */
        setLeft : function(left){
            this.setStyle(LEFT, this.addUnits(left));
            return this;
        },

        /**
         * Sets the element's top position directly using CSS style (instead of {@link #setY}).
         * @param {String} top The top CSS property value
         * @return {Ext.Element} this
         */
        setTop : function(top){
            this.setStyle(TOP, this.addUnits(top));
            return this;
        },

        /**
         * Sets the element's CSS right style.
         * @param {String} right The right CSS property value
         * @return {Ext.Element} this
         */
        setRight : function(right){
            this.setStyle(RIGHT, this.addUnits(right));
            return this;
        },

        /**
         * Sets the element's CSS bottom style.
         * @param {String} bottom The bottom CSS property value
         * @return {Ext.Element} this
         */
        setBottom : function(bottom){
            this.setStyle(BOTTOM, this.addUnits(bottom));
            return this;
        },

        /**
         * Sets the position of the element in page coordinates, regardless of how the element is positioned.
         * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
         * @param {Number[]} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setXY: function(pos, animate) {
            var me = this;
            if (!animate || !me.anim) {
                ELEMENT.setXY(me.dom, pos);
            }
            else {
                if (!Ext.isObject(animate)) {
                    animate = {};
                }
                me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
            }
            return me;
        },

        /**
         * Sets the position of the element in page coordinates, regardless of how the element is positioned.
         * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
         * @param {Number} x X value for new position (coordinates are page-based)
         * @param {Number} y Y value for new position (coordinates are page-based)
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setLocation : function(x, y, animate){
            return this.setXY([x, y], animate);
        },

        /**
         * Sets the position of the element in page coordinates, regardless of how the element is positioned.
         * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
         * @param {Number} x X value for new position (coordinates are page-based)
         * @param {Number} y Y value for new position (coordinates are page-based)
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
         * @return {Ext.Element} this
         */
        moveTo : function(x, y, animate){
            return this.setXY([x, y], animate);
        },

        /**
         * Gets the left X coordinate
         * @param {Boolean} local True to get the local css position instead of page coordinate
         * @return {Number}
         */
        getLeft : function(local){
            return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
        },

        /**
         * Gets the right X coordinate of the element (element X position + element width)
         * @param {Boolean} local True to get the local css position instead of page coordinate
         * @return {Number}
         */
        getRight : function(local){
            var me = this;
            return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
        },

        /**
         * Gets the top Y coordinate
         * @param {Boolean} local True to get the local css position instead of page coordinate
         * @return {Number}
         */
        getTop : function(local) {
            return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
        },

        /**
         * Gets the bottom Y coordinate of the element (element Y position + element height)
         * @param {Boolean} local True to get the local css position instead of page coordinate
         * @return {Number}
         */
        getBottom : function(local){
            var me = this;
            return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
        },

        /**
        * Initializes positioning on this element. If a desired position is not passed, it will make the
        * the element positioned relative IF it is not already positioned.
        * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
        * @param {Number} zIndex (optional) The zIndex to apply
        * @param {Number} x (optional) Set the page X position
        * @param {Number} y (optional) Set the page Y position
        */
        position : function(pos, zIndex, x, y) {
            var me = this;

            if (!pos && me.isStyle(POSITION, STATIC)){
                me.setStyle(POSITION, RELATIVE);
            } else if(pos) {
                me.setStyle(POSITION, pos);
            }
            if (zIndex){
                me.setStyle(ZINDEX, zIndex);
            }
            if (x || y) {
                me.setXY([x || false, y || false]);
            }
        },

        /**
        * Clear positioning back to the default when the document was loaded
        * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
        * @return {Ext.Element} this
         */
        clearPositioning : function(value){
            value = value || '';
            this.setStyle({
                left : value,
                right : value,
                top : value,
                bottom : value,
                "z-index" : "",
                position : STATIC
            });
            return this;
        },

        /**
        * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
        * snapshot before performing an update and then restoring the element.
        * @return {Object}
        */
        getPositioning : function(){
            var l = this.getStyle(LEFT);
            var t = this.getStyle(TOP);
            return {
                "position" : this.getStyle(POSITION),
                "left" : l,
                "right" : l ? "" : this.getStyle(RIGHT),
                "top" : t,
                "bottom" : t ? "" : this.getStyle(BOTTOM),
                "z-index" : this.getStyle(ZINDEX)
            };
        },

        /**
        * Set positioning with an object returned by getPositioning().
        * @param {Object} posCfg
        * @return {Ext.Element} this
         */
        setPositioning : function(pc){
            var me = this,
                style = me.dom.style;

            me.setStyle(pc);

            if(pc.right == AUTO){
                style.right = "";
            }
            if(pc.bottom == AUTO){
                style.bottom = "";
            }

            return me;
        },

        /**
         * Translates the passed page coordinates into left/top css values for this element
         * @param {Number/Number[]} x The page x or an array containing [x, y]
         * @param {Number} y (optional) The page y, required if x is not an array
         * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
         */
        translatePoints: function(x, y) {
            if (Ext.isArray(x)) {
                 y = x[1];
                 x = x[0];
            }
            var me = this,
                relative = me.isStyle(POSITION, RELATIVE),
                o = me.getXY(),
                left = parseInt(me.getStyle(LEFT), 10),
                top = parseInt(me.getStyle(TOP), 10);

            if (!Ext.isNumber(left)) {
                left = relative ? 0 : me.dom.offsetLeft;
            }
            if (!Ext.isNumber(top)) {
                top = relative ? 0 : me.dom.offsetTop;
            }
            left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
            top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
            return {
                left: left,
                top: top
            };
        },

        /**
         * Sets the element's box. Use getBox() on another element to get a box obj. If animate is true then width, height, x and y will be animated concurrently.
         * @param {Object} box The box to fill {x, y, width, height}
         * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setBox: function(box, adjust, animate) {
            var me = this,
                w = box.width,
                h = box.height;
            if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
                w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
                h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
            }
            me.setBounds(box.x, box.y, w, h, animate);
            return me;
        },

        /**
         * Return an object defining the area of this Element which can be passed to {@link #setBox} to
         * set another Element's size/location to match this element.
         * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
         * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
         * @return {Object} box An object in the format<pre><code>
    {
        x: &lt;Element's X position>,
        y: &lt;Element's Y position>,
        width: &lt;Element's width>,
        height: &lt;Element's height>,
        bottom: &lt;Element's lower bound>,
        right: &lt;Element's rightmost bound>
    }
    </code></pre>
         * The returned object may also be addressed as an Array where index 0 contains the X position
         * and index 1 contains the Y position. So the result may also be used for {@link #setXY}
         */
        getBox: function(contentBox, local) {
            var me = this,
                xy,
                left,
                top,
                getBorderWidth = me.getBorderWidth,
                getPadding = me.getPadding,
                l, r, t, b, w, h, bx;
            if (!local) {
                xy = me.getXY();
            } else {
                left = parseInt(me.getStyle("left"), 10) || 0;
                top = parseInt(me.getStyle("top"), 10) || 0;
                xy = [left, top];
            }
            w = me.getWidth();
            h = me.getHeight();
            if (!contentBox) {
                bx = {
                    x: xy[0],
                    y: xy[1],
                    0: xy[0],
                    1: xy[1],
                    width: w,
                    height: h
                };
            } else {
                l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
                r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
                t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
                b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
                bx = {
                    x: xy[0] + l,
                    y: xy[1] + t,
                    0: xy[0] + l,
                    1: xy[1] + t,
                    width: w - (l + r),
                    height: h - (t + b)
                };
            }
            bx.right = bx.x + bx.width;
            bx.bottom = bx.y + bx.height;
            return bx;
        },

        /**
         * Move this element relative to its current position.
         * @param {String} direction Possible values are: "l" (or "left"), "r" (or "right"), "t" (or "top", or "up"), "b" (or "bottom", or "down").
         * @param {Number} distance How far to move the element in pixels
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
         */
        move: function(direction, distance, animate) {
            var me = this,
                xy = me.getXY(),
                x = xy[0],
                y = xy[1],
                left = [x - distance, y],
                right = [x + distance, y],
                top = [x, y - distance],
                bottom = [x, y + distance],
                hash = {
                    l: left,
                    left: left,
                    r: right,
                    right: right,
                    t: top,
                    top: top,
                    up: top,
                    b: bottom,
                    bottom: bottom,
                    down: bottom
                };

            direction = direction.toLowerCase();
            me.moveTo(hash[direction][0], hash[direction][1], animate);
        },

        /**
         * Quick set left and top adding default units
         * @param {String} left The left CSS property value
         * @param {String} top The top CSS property value
         * @return {Ext.Element} this
         */
        setLeftTop: function(left, top) {
            var me = this,
                style = me.dom.style;
            style.left = me.addUnits(left);
            style.top = me.addUnits(top);
            return me;
        },

        /**
         * Returns the region of this element.
         * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
         * @return {Ext.util.Region} A Region containing "top, left, bottom, right" member data.
         */
        getRegion: function() {
            return this.getPageBox(true);
        },

        /**
         * Returns the <b>content</b> region of this element. That is the region within the borders and padding.
         * @return {Ext.util.Region} A Region containing "top, left, bottom, right" member data.
         */
        getViewRegion: function() {
            var me = this,
                isBody = me.dom === document.body,
                scroll, pos, top, left, width, height;

            // For the body we want to do some special logic
            if (isBody) {
                scroll = me.getScroll();
                left = scroll.left;
                top = scroll.top;
                width = Ext.Element.getViewportWidth();
                height = Ext.Element.getViewportHeight();
            }
            else {
                pos = me.getXY();
                left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
                top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
                width = me.getWidth(true);
                height = me.getHeight(true);
            }

            return Ext.create('Ext.util.Region', top, left + width, top + height, left);
        },

        /**
         * Return an object defining the area of this Element which can be passed to {@link #setBox} to
         * set another Element's size/location to match this element.
         * @param {Boolean} asRegion(optional) If true an Ext.util.Region will be returned
         * @return {Object} box An object in the format<pre><code>
    {
        x: &lt;Element's X position>,
        y: &lt;Element's Y position>,
        width: &lt;Element's width>,
        height: &lt;Element's height>,
        bottom: &lt;Element's lower bound>,
        right: &lt;Element's rightmost bound>
    }
    </code></pre>
         * The returned object may also be addressed as an Array where index 0 contains the X position
         * and index 1 contains the Y position. So the result may also be used for {@link #setXY}
         */
        getPageBox : function(getRegion) {
            var me = this,
                el = me.dom,
                isDoc = el === document.body,
                w = isDoc ? Ext.Element.getViewWidth()  : el.offsetWidth,
                h = isDoc ? Ext.Element.getViewHeight() : el.offsetHeight,
                xy = me.getXY(),
                t = xy[1],
                r = xy[0] + w,
                b = xy[1] + h,
                l = xy[0];

            if (getRegion) {
                return Ext.create('Ext.util.Region', t, r, b, l);
            }
            else {
                return {
                    left: l,
                    top: t,
                    width: w,
                    height: h,
                    right: r,
                    bottom: b
                };
            }
        },

        /**
         * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
         * @param {Number} x X value for new position (coordinates are page-based)
         * @param {Number} y Y value for new position (coordinates are page-based)
         * @param {Number/String} width The new width. This may be one of:<div class="mdetail-params"><ul>
         * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels)</li>
         * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
         * </ul></div>
         * @param {Number/String} height The new height. This may be one of:<div class="mdetail-params"><ul>
         * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels)</li>
         * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
         * </ul></div>
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setBounds: function(x, y, width, height, animate) {
            var me = this;
            if (!animate || !me.anim) {
                me.setSize(width, height);
                me.setLocation(x, y);
            } else {
                if (!Ext.isObject(animate)) {
                    animate = {};
                }
                me.animate(Ext.applyIf({
                    to: {
                        x: x,
                        y: y,
                        width: me.adjustWidth(width),
                        height: me.adjustHeight(height)
                    }
                }, animate));
            }
            return me;
        },

        /**
         * Sets the element's position and size the specified region. If animation is true then width, height, x and y will be animated concurrently.
         * @param {Ext.util.Region} region The region to fill
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
         * @return {Ext.Element} this
         */
        setRegion: function(region, animate) {
            return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);
        }
    });
    })();