    /*

    Siesta 5.3.0
    Copyright(c) 2009-2019 Bryntum AB
    https://bryntum.com/contact
    https://bryntum.com/products/siesta/license

    */
    Role('Siesta.Util.Role.CanCalculatePageScroll', {
        // also recognizes the "global" attribute

        methods : {

            getElForPageScroll : function (win) {
                win                 = win || this.global
                var doc             = win.document

                return doc.scrollingElement || (bowser.webkit || bowser.blink || bowser.msedge ? doc.body : doc.documentElement)
            },

            getPageScrollX : function (win) {
                win                 = win || this.global
                var doc             = win.document

                if (window.pageXOffset != null) return win.pageXOffset

                var scrollEl        = this.getElForPageScroll()

                return scrollEl ? scrollEl.scrollLeft : 0
            },

            getPageScrollY : function (win) {
                win                 = win || this.global
                var doc             = win.document

                if (window.pageYOffset != null) return win.pageYOffset

                var scrollEl        = this.getElForPageScroll()

                return scrollEl ? scrollEl.scrollTop : 0
            },

            viewportXtoPageX : function (x, win) {
                win                 = win || this.global
                var docEl           = win.document.documentElement

                // seems the "docEl.clientLeft" thing is copied from jQuery, not sure what kind of
                // edge case it is supposed to solve
                return x + this.getPageScrollX(win) - docEl.clientLeft
            },

            viewportYtoPageY : function (y, win) {
                win                 = win || this.global
                var docEl           = win.document.documentElement

                // seems the "docEl.clientLeft" thing is copied from jQuery, not sure what kind of
                // edge case it is supposed to solve
                return y + this.getPageScrollY(win) - docEl.clientTop
            },

            pageXtoViewportX : function (x, win) {
                win                 = win || this.global
                var docEl           = win.document.documentElement

                // seems the "docEl.clientLeft" thing is copied from jQuery, not sure what kind of
                // edge case it is supposed to solve
                return x - this.getPageScrollX(win) + docEl.clientLeft
            },

            pageYtoViewportY : function (y, win) {
                win                 = win || this.global
                var docEl           = win.document.documentElement

                // seems the "docEl.clientLeft" thing is copied from jQuery, not sure what kind of
                // edge case it is supposed to solve
                return y - this.getPageScrollY(win) + docEl.clientTop
            },

            // this method is only actual, when Siesta UI is embedded inside the iframe of the parent window
            // in this case we don't want the scrolling position of the parent window to change in reaction
            // to the Siesta tests launches / progress
            maintainScrollPositionDuring : function (func, scope) {
                var parent                  = window.parent
                var isEmbedded              = Boolean(parent)

                var scrollLeftBefore        = isEmbedded && this.getPageScrollX(parent)
                var scrollTopBefore         = isEmbedded && this.getPageScrollY(parent)

                func.call(scope || this)

                // prevent scroll position change in the parent window, if Siesta UI is embedded
                if (isEmbedded) {
                    var scrollEl            = this.getElForPageScroll(parent)

                    if (scrollLeftBefore !== this.getPageScrollX(parent)) scrollEl.scrollLeft = scrollLeftBefore
                    if (scrollTopBefore !== this.getPageScrollY(parent)) scrollEl.scrollTop = scrollTopBefore
                }
            }
        }
    })