    // @tag dom,core
    /**
     */
    Ext.define('Ext.dom.Element_position', {
        override: 'Ext.dom.Element'
    },
    function() {

    var flyInstance,
        Element = this,
        LEFT = "left",
        RIGHT = "right",
        TOP = "top",
        BOTTOM = "bottom",
        POSITION = "position",
        STATIC = "static",
        RELATIVE = "relative",
        ZINDEX = "z-index",
        BODY = 'BODY',

        PADDING = 'padding',
        BORDER = 'border',
        SLEFT = '-left',
        SRIGHT = '-right',
        STOP = '-top',
        SBOTTOM = '-bottom',
        SWIDTH = '-width',
        // special markup used throughout Ext when box wrapping elements
        borders = {l: BORDER + SLEFT + SWIDTH, r: BORDER + SRIGHT + SWIDTH, t: BORDER + STOP + SWIDTH, b: BORDER + SBOTTOM + SWIDTH},
        paddings = {l: PADDING + SLEFT, r: PADDING + SRIGHT, t: PADDING + STOP, b: PADDING + SBOTTOM},
        paddingsTLRB = [paddings.l, paddings.r, paddings.t, paddings.b],
        bordersTLRB = [borders.l,  borders.r,  borders.t,  borders.b],
        round = Math.round,
        doc = document,
        fly = function (el) {
            if (!flyInstance) {
                flyInstance = new Ext.Element.Fly();
            }
            flyInstance.attach(el);
            return flyInstance;
        };

        Element.override({

            pxRe: /^\d+(?:\.\d*)?px$/i,

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

                getXY: function(el) {
                    var bd = doc.body,
                        docEl = doc.documentElement,
                        leftBorder = 0,
                        topBorder = 0,
                        ret = [0,0],
                        box,
                        scroll;

                    el = Ext.getDom(el);

                    if(el != doc && el != bd){
                        // IE has the potential to throw when getBoundingClientRect
                        // is called on an element not attached to dom
                        if (Ext.isIE) {
                            try {
                                box = el.getBoundingClientRect();
                                // In some versions of IE, the documentElement (HTML element)
                                // will have a 2px border that gets included, so subtract it off
                                topBorder = docEl.clientTop || bd.clientTop;
                                leftBorder = docEl.clientLeft || bd.clientLeft;
                            } catch (ex) {
                                box = { left: 0, top: 0 };
                            }
                        } else {
                            box = el.getBoundingClientRect();
                        }

                        scroll = fly(doc).getScroll();
                        ret = [
                            round(box.left + scroll.left - leftBorder),
                            round(box.top + scroll.top - topBorder)
                        ];
                    }
                    return ret;
                },

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

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

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

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

                    // right position may have been previously set by rtlSetXY or
                    // rtlSetLocalXY so clear it here just in case.
                    style.right = 'auto';
                    for (pos in pts) {
                        if (!isNaN(pts[pos])) {
                            style[pos] = pts[pos] + "px";
                        }
                    }
                },

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

            /**
             * Centers the Element in either the viewport, or another Element.
             * @param {String/HTMLElement/Ext.dom.Element} centerIn element in
             * which to center the element.
             */
            center: function(centerIn){
                return this.alignTo(centerIn || doc, 'c-c');
            },

            /**
             * 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
                });
            },

            getAnchorToXY: function(el, anchor, local, mySize) {
                return el.getAnchorXY(anchor, local, mySize);
            },

            /**
             * 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}
             * @deprecated
             */
            getBottom: function(local) {
                return (local ? this.getLocalY() : this.getY()) + this.getHeight();
            },

            getBorderPadding: function() {
                var paddingWidth = this.getStyle(paddingsTLRB),
                    bordersWidth = this.getStyle(bordersTLRB);

                return {
                    beforeX: (parseFloat(bordersWidth[borders.l]) || 0) + (parseFloat(paddingWidth[paddings.l]) || 0),
                    afterX: (parseFloat(bordersWidth[borders.r]) || 0) + (parseFloat(paddingWidth[paddings.r]) || 0),
                    beforeY: (parseFloat(bordersWidth[borders.t]) || 0) + (parseFloat(paddingWidth[paddings.t]) || 0),
                    afterY: (parseFloat(bordersWidth[borders.b]) || 0) + (parseFloat(paddingWidth[paddings.b]) || 0)
                };
            },

            /**
             * Calculates the x, y to center this element on the screen
             * @return {Number[]} The x, y values [x, y]
             * @deprecated
             */
            getCenterXY: function(){
                return this.getAlignToXY(doc, 'c-c');
            },

            /**
             * Gets the left X coordinate
             * @param {Boolean} local True to get the local css position instead of
             * page coordinate
             * @return {Number}
             * @deprecated Use {@link #getX} or {@link #getLocalX}
             */
            getLeft: function(local) {
                return local ? this.getLocalX() : this.getX();
            },

            /**
             * Gets the local CSS X position for the element
             *
             * @return {Number}
             */
            getLocalX: function() {
                var me = this,
                    offsetParent = me.dom.offsetParent,
                    x = me.getStyle('left');

                if (!x || x === 'auto') {
                    x = 0;
                } else if (me.pxRe.test(x)) {
                    x = parseFloat(x);
                } else {
                    x = me.getX();
                    if (offsetParent) {
                        x -= Element.getX(offsetParent);
                    }
                }

                return x;
            },

            /**
             * Gets the local CSS X and Y position for the element
             *
             * @return {Array} [x, y]
             */
            getLocalXY: function() {
                var me = this,
                    offsetParent = me.dom.offsetParent,
                    style = me.getStyle(['left', 'top']),
                    x = style.left,
                    y = style.top;

                if (!x || x === 'auto') {
                    x = 0;
                } else if (me.pxRe.test(x)) {
                    x = parseFloat(x);
                } else {
                    x = me.getX();
                    if (offsetParent) {
                        x -= Element.getX(offsetParent);
                    }
                }

                if (!y || y === 'auto') {
                    y = 0;
                } else if (me.pxRe.test(y)) {
                    y = parseFloat(y);
                } else {
                    y = me.getY();
                    if (offsetParent) {
                        y -= Element.getY(offsetParent);
                    }
                }

                return [x, y];
            },

            /**
             * Gets the local CSS Y position for the element
             *
             * @return {Number}
             */
            getLocalY: function() {
                var me = this,
                    offsetParent = me.dom.offsetParent,
                    y = me.getStyle('top');

                if (!y || y === 'auto') {
                    y = 0;
                } else if (me.pxRe.test(y)) {
                    y = parseFloat(y);
                } else {
                    y = me.getY();
                    if (offsetParent) {
                        y -= Element.getY(offsetParent);
                    }
                }

                return y;
            },

            /**
             * Returns an object defining the area of this Element which can be passed to
             * {@link Ext.util.Positionable#setBox} to set another Element's size/location to match this element.
             *
             * @param {Boolean} [asRegion] If true an Ext.util.Region will be returned
             * @return {Object/Ext.util.Region} box An object in the following format:
             *
             *     {
             *         left: <Element's X position>,
             *         top: <Element's Y position>,
             *         width: <Element's width>,
             *         height: <Element's height>,
             *         bottom: <Element's lower bound>,
             *         right: <Element's rightmost bound>
             *     }
             *
             * 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}
             * @deprecated use {@link Ext.util.Positionable#getBox} to get a box object, and
             * {@link Ext.util.Positionable#getRegion} to get a {@link Ext.util.Region Region}.
             */
            getPageBox: function(getRegion) {
                var me = this,
                    dom = me.dom,
                    isDoc = dom.nodeName == BODY,
                    w = isDoc ? Ext.Element.getViewWidth() : dom.offsetWidth,
                    h = isDoc ? Ext.Element.getViewHeight() : dom.offsetHeight,
                    xy = me.getXY(),
                    t = xy[1],
                    r = xy[0] + w,
                    b = xy[1] + h,
                    l = xy[0];

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

            /**
             * Gets an object with all CSS positioning properties. Useful along with
             * #setPostioning 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;
            },

            /**
             * 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
             * coordinates
             * @return {Number}
             * @deprecated
             */
            getRight: function(local) {
                return (local ? this.getLocalX() : this.getX()) + this.getWidth();
            },

            /**
             * Gets the top Y coordinate
             * @param {Boolean} local True to get the local css position instead of page
             * coordinates
             * @return {Number}
             * @deprecated Use {@link #getY} or {@link #getLocalY}
             */
            getTop: function(local) {
                return local ? this.getLocalY() : this.getY();
            },

            /**
             * Gets element X position in page coordinates
             *
             * @return {Number}
             */
            getX: function() {
                return Element.getX(this.dom);
            },

            /**
             * Gets element X and Y positions in page coordinates
             *
             * @return {Array} [x, y]
             */
            getXY: function() {
                return Element.getXY(this.dom);
            },

            /**
             * Gets element Y position in page coordinates
             *
             * @return {Number}
             */
            getY: function() {
                return Element.getY(this.dom);
            },

            /**
             * Sets the position of the element in page coordinates.
             * @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] True for the default animation, or a standard
             * Element animation config object
             * @return {Ext.dom.Element} this
             * @deprecated Use {@link #setXY} instead.
             */
            moveTo: function(x, y, animate) {
                return this.setXY([x, y], animate);
            },

            /**
             * 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] Positioning to use "relative", "absolute" or "fixed"
             * @param {Number} [zIndex] The zIndex to apply
             * @param {Number} [x] Set the page X position
             * @param {Number} [y] 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]);
                }
            },

            /**
             * Sets the element's CSS bottom style.
             * @param {Number/String} bottom Number of pixels or CSS string value to set as
             * the bottom CSS property value
             * @return {Ext.dom.Element} this
             * @deprecated
             */
            setBottom: function(bottom) {
                this.dom.style[BOTTOM] = this.addUnits(bottom);
                return this;
            },

            /**
             * 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:
             *
             * - A Number specifying the new width in this Element's
             * {@link #defaultUnit}s (by default, pixels)
             * - A String used to set the CSS width style. Animation may **not** be used.
             *
             * @param {Number/String} height The new height. This may be one of:
             *
             * - A Number specifying the new height in this Element's
             * {@link #defaultUnit}s (by default, pixels)
             * - A String used to set the CSS height style. Animation may **not** be used.
             *
             * @param {Boolean/Object} [animate] true for the default animation or
             * a standard Element animation config object
             *
             * @return {Ext.dom.Element} this
             * @deprecated Use {@link Ext.util.Positionable#setBox} instead.
             */
            setBounds: function(x, y, width, height, animate) {
                return this.setBox({
                    x: x,
                    y: y,
                    width: width,
                    height: height
                }, animate);
            },

            /**
             * Sets the element's left position directly using CSS style
             * (instead of {@link #setX}).
             * @param {Number/String} left Number of pixels or CSS string value to
             * set as the left CSS property value
             * @return {Ext.dom.Element} this
             * @deprecated
             */
            setLeft: function(left) {
                this.dom.style[LEFT] = this.addUnits(left);
                return this;
            },

            /**
             * Sets the element's left and top positions directly using CSS style
             * @param {Number/String} left Number of pixels or CSS string value to
             * set as the left CSS property value
             * @param {Number/String} top Number of pixels or CSS string value to
             * set as the top CSS property value
             * @return {Ext.dom.Element} this
             * @deprecated
             */
            setLeftTop: function(left, top) {
                var me = this,
                    style = me.dom.style;

                style.left = me.addUnits(left);
                style.top = me.addUnits(top);

                return me;
            },

            setLocalX: function(x) {
                var style = this.dom.style;

                // clear right style just in case it was previously set by rtlSetXY/rtlSetLocalXY
                style.right = 'auto';
                style.left = (x === null) ? 'auto' : x + 'px';
            },

            setLocalXY: function(x, y) {
                var style = this.dom.style;

                // clear right style just in case it was previously set by rtlSetXY/rtlSetLocalXY
                style.right = 'auto';

                if (x && x.length) {
                    y = x[1];
                    x = x[0];
                }

                if (x === null) {
                    style.left = 'auto';
                } else if (x !== undefined) {
                    style.left = x + 'px';
                }

                if (y === null) {
                    style.top = 'auto';
                } else if (y !== undefined) {
                    style.top = y + 'px';
                }
            },

            setLocalY: function(y) {
                this.dom.style.top = (y === null) ? 'auto' : y + 'px';
            },

            /**
             * Sets the position of the element in page coordinates.
             * @param {Number} x X value for new position
             * @param {Number} y Y value for new position
             * @param {Boolean/Object} [animate] True for the default animation, or a standard
             * Element animation config object
             * @return {Ext.dom.Element} this
             * @deprecated Use {@link #setXY} instead.
             */
            setLocation: function(x, y, animate) {
                return this.setXY([x, y], animate);
            },

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

            /**
             * Sets the element's CSS right style.
             * @param {Number/String} right Number of pixels or CSS string value to
             * set as the right CSS property value
             * @return {Ext.dom.Element} this
             * @deprecated
             */
            setRight: function(right) {
                this.dom.style[RIGHT] = this.addUnits(right);
                return this;
            },

            /**
             * Sets the element's top position directly using CSS style
             * (instead of {@link #setY}).
             * @param {Number/String} top Number of pixels or CSS string value to
             * set as the top CSS property value
             * @return {Ext.dom.Element} this
             * @deprecated
             */
            setTop: function(top) {
                this.dom.style[TOP] = this.addUnits(top);
                return this;
            },

            setX: function(x, animate) {
                return this.setXY([x, this.getY()], animate);
            },

            setXY: function(xy, animate) {
                var me = this;

                if (!animate || !me.anim) {
                    Element.setXY(me.dom, xy);
                } else {
                    if (!Ext.isObject(animate)) {
                        animate = {};
                    }
                    me.animate(Ext.applyIf({ to: { x: xy[0], y: xy[1] } }, animate));
                }
                return this;
            },

            setY: function(y, animate) {
                return this.setXY([this.getX(), y], animate);
            }
        });

        /**
         * @private
         * Returns the `X,Y` position of the passed element in browser document space without regard
         * to any RTL direction settings.
         */
        Element.getTrueXY = Element.getXY;

    });