    Ext.define('Ext.rtl.dom.Element_scroll', {
        override: 'Ext.dom.Element',

        rtlGetScroll: function() {
            var me = this,
                dom = me.dom,
                doc = document,
                body = doc.body,
                scroll = me.getScroll(),
                // The left value returned from getScroll() may be a negative number.  In rtl
                // mode left should always be reported as a positive number of pixels from the
                // right, so use the absolute value of left.
                left = Math.abs(scroll.left),
                isDocOrBody = (dom === doc || dom === body);

            if (isDocOrBody ? (3 & me._rtlDocScrollFlag) : (me._rtlScrollFlag === 1)) {
                // If the browser reports scrollLeft as the number of pixels from left
                // (same as ltr) we need to convert it to a rtl position by subtracting it
                // from scrollWidth
                if (isDocOrBody) {
                    dom = body;
                }

                left = dom.scrollWidth - left -
                    (isDocOrBody ? Ext.Element.getViewportWidth() : dom.clientWidth);
            }
            scroll.left = left;

            return scroll;
        },

        rtlGetScrollLeft: function() {
            return this.rtlGetScroll().left;
        },

        rtlSetScrollLeft: function(left){
            var me = this;

            me.dom.scrollLeft = me.rtlNormalizeScrollLeft(left);
            return me;
        },

        rtlScrollTo: function(side, value, animate) {
            if (side === 'left') {
                value = this.rtlNormalizeScrollLeft(value);
            }

            return this.scrollTo(side, value, animate);
        },

        rtlScrollBy: function(deltaX, deltaY, animate) {
            var me = this,
                dom = me.dom,
                left, maxScroll;

            // Extract args if deltas were passed as an Array.
            if (deltaX.length) {
                animate = deltaY;
                deltaY = deltaX[1];
                deltaX = deltaX[0];
            } else if (typeof deltaX != 'number') { // or an object
                animate = deltaY;
                deltaY = deltaX.y;
                deltaX = deltaX.x;
            }

            if (deltaX) {
                left = me.rtlNormalizeScrollLeft(
                    me.constrainScrollLeft(me.rtlGetScrollLeft() + deltaX)
                );

                me.scrollTo('left', left, animate);
            }
            if (deltaY) {
                me.scrollTo('top', me.constrainScrollTop(dom.scrollTop + deltaY), animate);
            }

            return me;
        },

        rtlScroll: function(direction, distance, animate) {
            if (!this.isScrollable()) {
                return false;
            }
            var me = this,
                side = direction === 'r' || direction === 'l' ? 'left' : 'top',
                scrolled = false,
                currentScroll, constrainedScroll;

            if (direction === 'r') {
                distance = -distance;
            }

            if (side === 'left') {
                currentScroll = me.rtlGetScrollLeft();
                constrainedScroll = me.constrainScrollLeft(currentScroll + distance);
            } else {
                currentScroll = me.dom.scrollTop;
                constrainedScroll = me.constrainScrollTop(currentScroll + distance);
            }

            if (constrainedScroll !== currentScroll) {
                this.rtlScrollTo(side, constrainedScroll, animate);
                scrolled = true;
            }

            return scrolled;
        },

        rtlNormalizeScrollLeft: function(left){
            var dom = this.dom,
                flag = this._rtlScrollFlag;

            if (flag === 0) {
                left = -left;
            } else if (flag === 1) {
                left = dom.scrollWidth - left - dom.clientWidth;
            }
            return left;
        }

    }, function() {
        var Element = this;

        /*
         * Sets a _rtlScrollFlag property on the Element class prototype indicating how the
         * browser reports scrollLeft on overflowing rtl elements.  This method cannot be used
         * reliably on the documentElement or document.body because the behavior of these
         * elements can be different from other elements in some browsers.
         *
         * 0: offset from right (negative number) - firefox
         * 1: offset from left (positive number) - IE6, IE7, IE6 - IE9 quirks, and Webkit
         * 2: offset from right (positive number) - IE8 - IE10 & IE10 quirks
         */
        function cacheRtlScrollFlag() {
            var el = Ext.getBody().createChild({
                tag: 'div',
                style: 'direction:rtl;position:absolute;overflow:auto;height:100px;width:100px;',
                children: [{
                    tag: 'div',
                    style: 'height:30px;width:150px;'
                }]
            }),
            dom = el.dom,
            flag = 2;

            if (dom.scrollLeft === 50) {
                flag = 1;
            } else {
                dom.scrollLeft = -1;
                if (dom.scrollLeft) {
                    flag = 0;
                }
            }

            el.remove();
            Element.prototype._rtlScrollFlag = flag;
        }

        /*
         * scrollLeft on the document/body is reported differently from ordinary
         * overflowing elements in many browsers (see getRtlScrollFlag).There are 2
         * separate things we have to detect:
         * 1. The element that overflows - when the document overflows some browsers
         * set scrollLeft on the document body (webkit and IE quirks), while other
         * browsers set scrollLeft on the documentElement (all other supported browsers
         * at the time of this writing).
         * 2. The scrollLeft of the overflowing document/body can be one of the
         * following:
         *    a. number of pixels offset from right expressed as a negative number
         *       (Webkit, Firefox)
         *    b. number of pixels offset from right expressed as a positive number
         *       (IE8 - IE10 strict mode, and IE10 quirks mode.
         *    c. number of pixels offset from left expressed as a positive number
         *       (IE6 - IE9 quirks mode, and IE6/IE7 strict mode.
         *
         * The following logic feture detects the handling of scrollLeft and sets the
         * _rtlDocScrollFlag property on this class' prototype as a bit flag which has
         * the following values:
         *
         * 0 - docEl, negative right
         * 1 - docEl, positive left
         * 2 - docEl, positive right
         * 4 - body, negative right
         * 5 - body, positive left
         */
        function cacheRtlDocScrollFlag() {
            var doc = document,
                docEl = doc.documentElement,
                body = doc.body,
                // flag defaults to body, negative right (webkit) so no detection needed
                // is needed for this scenario
                flag = 4,
                bodyStyle = body.style,
                // save the direction property so we can set it back when we are done.
                direction = bodyStyle.direction,
                el = Ext.getBody().createChild(
                    '<div style="height:20000px;width:20000px;"></div>'
                ),
                dom = el.dom,
                ltrRight, rtlRight

            bodyStyle.direction = 'ltr';
            ltrRight = dom.getBoundingClientRect().right;

            bodyStyle.direction = 'rtl';
            rtlRight = dom.getBoundingClientRect().right;

            // when the body has vertical overflow some browser continue to show the
            // vertical scrollbar on the right side of the page even in rtl mode.
            Element.prototype._rtlBodyScrollbarOnRight = (ltrRight === rtlRight);

            // First, check if scrollLeft is a non-zero value on the documentElement or
            // body. This means scrollLeft is a positive number offset from the left.
            if (docEl.scrollLeft > 0) {
                // IE6/7 strict
                flag = 1;
            } else if (body.scrollLeft > 0) {
                // IE6 - IE9 quirks
                flag = 5;
            } else {
                // The next step is to attempt to set scrollLeft values, This allows us to
                // test for non-zero values to see if the value was valid (scrollLeft
                // resets to 0 when a non-valid value is set).
                // attempt to set the documentElement's scrollLeft to a negative number
                docEl.scrollLeft = -1;
                if (docEl.scrollLeft) {
                    // it worked! we were able to set a negative scroll left on the
                    // documentElement (firefox)
                    flag = 0;
                } else {
                    // attempt to set the documentElement's scrollLeft to a positive number
                    docEl.scrollLeft = 1;
                    if (docEl.scrollLeft) {
                        // success setting scroll left to a positive number on
                        // documentElement (IE8 strict, IE9 strict, and IE10 quirks)
                        flag = 2;
                    }
                }
            }

            el.remove();
            if (!direction) {
                // if direction is an empty string, we set it back to "ltr", because once
                // the direction style on the body element is changed to "rtl" in webkit,
                // it becomes permanent, even after it is set back to "", unless it is first
                // explicitly set back to "ltr"
                bodyStyle.direction = 'ltr';
                // read the scroll width before setting the direction back to "".
                // This forces webkit to update its computed direction style to ltr
                body.scrollWidth;
            }
            // set direction back to its original value
            bodyStyle.direction = direction;
            Element.prototype._rtlDocScrollFlag = flag;
        }

        Ext.on({
            ready: function() {
                // This function attaches to onReady with a priority of 1000 so that we can
                // detect how the browser reports scrollLeft by manipulating the document/body
                // before any components have been rendered to the page.
                cacheRtlDocScrollFlag();
                cacheRtlScrollFlag();
            },
            single: true,
            priority: 1001
        });
    });