Search code examples
javascriptseleniumselenium-webdriverscrollprotractor

Finding all elements with a scroll


What is the most reliable and efficient way to find all elements having a scroll on a page?


Currently, I'm thinking about using element.all() with filter() comparing the height and scrollHeight attribute values:

element.all(by.xpath("//*")).filter(function (elm) {
    return protractor.promise.all([
        elm.getAttribute("height"),
        elm.getAttribute("scrollHeight")
    ]).then(function (heights) { 
        return heights[1] > heights[0];
    });
});

But I'm not sure about the correctness and performance of this approach.


Solution

  • This works with both horizontal and vertical scrollbars. The trick is detecting BOTH the too-wide/too-short AND if the computed CSS is going to allow you to display a scrollbar.

    var ElementsWithScrolls = (function() {
        var getComputedStyle = document.body && document.body.currentStyle ? function(elem) {
            return elem.currentStyle;
        } : function(elem) {
            return document.defaultView.getComputedStyle(elem, null);
        };
    
        function getActualCss(elem, style) {
            return getComputedStyle(elem)[style];
        }
    
        function isXScrollable(elem) {
            return elem.offsetWidth < elem.scrollWidth &&
                autoOrScroll(getActualCss(elem, 'overflow-x'));
        }
    
        function isYScrollable(elem) {
            return elem.offsetHeight < elem.scrollHeight &&
                autoOrScroll(getActualCss(elem, 'overflow-y'));
        }
    
        function autoOrScroll(text) {
            return text == 'scroll' || text == 'auto';
        }
    
        function hasScroller(elem) {
            return isYScrollable(elem) || isXScrollable(elem);
        }
        return function ElemenetsWithScrolls() {
            return [].filter.call(document.querySelectorAll('*'), hasScroller);
        };
    })();
    
    ElementsWithScrolls();