Best Python code snippet using uiautomator
node-scroll-info-coverage.js
Source:node-scroll-info-coverage.js  
1/*2YUI 3.7.3 (build 5687)3Copyright 2012 Yahoo! Inc. All rights reserved.4Licensed under the BSD License.5http://yuilibrary.com/license/6*/7if (typeof _yuitest_coverage == "undefined"){8    _yuitest_coverage = {};9    _yuitest_coverline = function(src, line){10        var coverage = _yuitest_coverage[src];11        if (!coverage.lines[line]){12            coverage.calledLines++;13        }14        coverage.lines[line]++;15    };16    _yuitest_coverfunc = function(src, name, line){17        var coverage = _yuitest_coverage[src],18            funcId = name + ":" + line;19        if (!coverage.functions[funcId]){20            coverage.calledFunctions++;21        }22        coverage.functions[funcId]++;23    };24}25_yuitest_coverage["build/node-scroll-info/node-scroll-info.js"] = {26    lines: {},27    functions: {},28    coveredLines: 0,29    calledLines: 0,30    coveredFunctions: 0,31    calledFunctions: 0,32    path: "build/node-scroll-info/node-scroll-info.js",33    code: []34};35_yuitest_coverage["build/node-scroll-info/node-scroll-info.js"].code=["YUI.add('node-scroll-info', function (Y, NAME) {","","/**","Provides the ScrollInfo Node plugin, which exposes convenient events and methods","related to scrolling.","","@module node-scroll-info","@since 3.7.0","**/","","/**","Provides convenient events and methods related to scrolling. This could be used,","for example, to implement infinite scrolling, or to lazy-load content based on","the current scroll position.","","### Example","","    var body = Y.one('body');","","    body.plug(Y.Plugin.ScrollInfo);","","    body.scrollInfo.on('scrollToBottom', function (e) {","        // Load more content when the user scrolls to the bottom of the page.","    });","","@class Plugin.ScrollInfo","@extends Plugin.Base","@since 3.7.0","**/","","/**","Fired when the user scrolls within the host node.","","This event (like all scroll events exposed by ScrollInfo) is throttled and fired","only after the number of milliseconds specified by the `scrollDelay` attribute","have passed in order to prevent thrashing.","","This event passes along the event facade for the standard DOM `scroll` event and","mixes in the following additional properties.","","@event scroll","@param {Boolean} atBottom Whether the current scroll position is at the bottom","    of the scrollable region.","@param {Boolean} atLeft Whether the current scroll position is at the extreme","    left of the scrollable region.","@param {Boolean} atRight Whether the current scroll position is at the extreme","    right of the scrollable region.","@param {Boolean} atTop Whether the current scroll position is at the top of the","    scrollable region.","@param {Boolean} isScrollDown `true` if the user scrolled down.","@param {Boolean} isScrollLeft `true` if the user scrolled left.","@param {Boolean} isScrollRight `true` if the user scrolled right.","@param {Boolean} isScrollUp `true` if the user scrolled up.","@param {Number} scrollBottom Y value of the bottom-most onscreen pixel of the","    scrollable region.","@param {Number} scrollHeight Total height in pixels of the scrollable region,","    including offscreen pixels.","@param {Number} scrollLeft X value of the left-most onscreen pixel of the","    scrollable region.","@param {Number} scrollRight X value of the right-most onscreen pixel of the","    scrollable region.","@param {Number} scrollTop Y value of the top-most onscreen pixel of the","    scrollable region.","@param {Number} scrollWidth Total width in pixels of the scrollable region,","    including offscreen pixels.","@see scrollDelay","@see scrollMargin","**/","var EVT_SCROLL = 'scroll',","","    /**","    Fired when the user scrolls down within the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollDown","    @see scroll","    **/","    EVT_SCROLL_DOWN = 'scrollDown',","","    /**","    Fired when the user scrolls left within the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollLeft","    @see scroll","    **/","    EVT_SCROLL_LEFT = 'scrollLeft',","","    /**","    Fired when the user scrolls right within the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollRight","    @see scroll","    **/","    EVT_SCROLL_RIGHT = 'scrollRight',","","    /**","    Fired when the user scrolls up within the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollUp","    @see scroll","    **/","    EVT_SCROLL_UP = 'scrollUp',","","    /**","    Fired when the user scrolls to the bottom of the scrollable region within","    the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollToBottom","    @see scroll","    **/","    EVT_SCROLL_TO_BOTTOM = 'scrollToBottom',","","    /**","    Fired when the user scrolls to the extreme left of the scrollable region","    within the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollToLeft","    @see scroll","    **/","    EVT_SCROLL_TO_LEFT = 'scrollToLeft',","","    /**","    Fired when the user scrolls to the extreme right of the scrollable region","    within the host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollToRight","    @see scroll","    **/","    EVT_SCROLL_TO_RIGHT = 'scrollToRight',","","    /**","    Fired when the user scrolls to the top of the scrollable region within the","    host node.","","    This event provides the same event facade as the `scroll` event. See that","    event for details.","","    @event scrollToTop","    @see scroll","    **/","    EVT_SCROLL_TO_TOP = 'scrollToTop';","","Y.Plugin.ScrollInfo = Y.Base.create('scrollInfoPlugin', Y.Plugin.Base, [], {","    // -- Lifecycle Methods ----------------------------------------------------","    initializer: function (config) {","        // Cache for quicker lookups in the critical path.","        this._host         = config.host;","        this._hostIsBody   = this._host.get('nodeName').toLowerCase() === 'body';","        this._scrollDelay  = this.get('scrollDelay');","        this._scrollMargin = this.get('scrollMargin');","        this._scrollNode   = this._getScrollNode();","","        this.refreshDimensions();","","        this._lastScroll = this.getScrollInfo();","","        this._bind();","    },","","    destructor: function () {","        (new Y.EventHandle(this._events)).detach();","        delete this._events;","    },","","    // -- Public Methods -------------------------------------------------------","","    /**","    Returns a NodeList containing all offscreen nodes inside the host node that","    match the given CSS selector. An offscreen node is any node that is entirely","    outside the visible (onscreen) region of the host node based on the current","    scroll location.","","    @method getOffscreenNodes","    @param {String} [selector] CSS selector. If omitted, all offscreen nodes","        will be returned.","    @param {Number} [margin] Additional margin in pixels beyond the actual","        onscreen region that should be considered \"onscreen\" for the purposes of","        this query. Defaults to the value of the `scrollMargin` attribute.","    @return {NodeList} Offscreen nodes matching _selector_.","    @see scrollMargin","    **/","    getOffscreenNodes: function (selector, margin) {","        if (typeof margin === 'undefined') {","            margin = this._scrollMargin;","        }","","        var lastScroll = this._lastScroll,","            nodes      = this._host.all(selector || '*'),","","            scrollBottom = lastScroll.scrollBottom + margin,","            scrollLeft   = lastScroll.scrollLeft - margin,","            scrollRight  = lastScroll.scrollRight + margin,","            scrollTop    = lastScroll.scrollTop - margin,","","            self = this;","","        return nodes.filter(function (el) {","            var xy     = Y.DOM.getXY(el),","                elLeft = xy[0] - self._left,","                elTop  = xy[1] - self._top,","                elBottom, elRight;","","            // Check whether the element's top left point is within the","            // viewport. This is the least expensive check.","            if (elLeft >= scrollLeft && elLeft < scrollRight &&","                    elTop >= scrollTop && elTop < scrollBottom) {","","                return false;","            }","","            // Check whether the element's bottom right point is within the","            // viewport. This check is more expensive since we have to get the","            // element's height and width.","            elBottom = elTop + el.offsetHeight;","            elRight  = elLeft + el.offsetWidth;","","            if (elRight < scrollRight && elRight >= scrollLeft &&","                    elBottom < scrollBottom && elBottom >= scrollTop) {","","                return false;","            }","","            // If we get here, the element isn't within the viewport.","            return true;","        });","    },","","    /**","    Returns a NodeList containing all onscreen nodes inside the host node that","    match the given CSS selector. An onscreen node is any node that is fully or","    partially within the visible (onscreen) region of the host node based on the","    current scroll location.","","    @method getOnscreenNodes","    @param {String} [selector] CSS selector. If omitted, all onscreen nodes will","        be returned.","    @param {Number} [margin] Additional margin in pixels beyond the actual","        onscreen region that should be considered \"onscreen\" for the purposes of","        this query. Defaults to the value of the `scrollMargin` attribute.","    @return {NodeList} Onscreen nodes matching _selector_.","    @see scrollMargin","    **/","    getOnscreenNodes: function (selector, margin) {","        if (typeof margin === 'undefined') {","            margin = this._scrollMargin;","        }","","        var lastScroll = this._lastScroll,","            nodes      = this._host.all(selector || '*'),","","            scrollBottom = lastScroll.scrollBottom + margin,","            scrollLeft   = lastScroll.scrollLeft - margin,","            scrollRight  = lastScroll.scrollRight + margin,","            scrollTop    = lastScroll.scrollTop - margin,","","            self = this;","","        return nodes.filter(function (el) {","            var xy     = Y.DOM.getXY(el),","                elLeft = xy[0] - self._left,","                elTop  = xy[1] - self._top,","                elBottom, elRight;","","            // Check whether the element's top left point is within the","            // viewport. This is the least expensive check.","            if (elLeft >= scrollLeft && elLeft < scrollRight &&","                    elTop >= scrollTop && elTop < scrollBottom) {","","                return true;","            }","","            // Check whether the element's bottom right point is within the","            // viewport. This check is more expensive since we have to get the","            // element's height and width.","            elBottom = elTop + el.offsetHeight;","            elRight  = elLeft + el.offsetWidth;","","            if (elRight < scrollRight && elRight >= scrollLeft &&","                    elBottom < scrollBottom && elBottom >= scrollTop) {","","                return true;","            }","","            // If we get here, the element isn't within the viewport.","            return false;","        });","    },","","    /**","    Returns an object hash containing information about the current scroll","    position of the host node. This is the same information that's mixed into","    the event facade of the `scroll` event and other scroll-related events.","","    @method getScrollInfo","    @return {Object} Object hash containing information about the current scroll","        position. See the `scroll` event for details on what properties this","        object contains.","    @see scroll","    **/","    getScrollInfo: function () {","        var domNode    = this._scrollNode,","            lastScroll = this._lastScroll,","            margin     = this._scrollMargin,","","            scrollLeft   = domNode.scrollLeft,","            scrollHeight = domNode.scrollHeight,","            scrollTop    = domNode.scrollTop,","            scrollWidth  = domNode.scrollWidth,","","            scrollBottom = scrollTop + this._height,","            scrollRight  = scrollLeft + this._width;","","        return {","            atBottom: scrollBottom > (scrollHeight - margin),","            atLeft  : scrollLeft < margin,","            atRight : scrollRight > (scrollWidth - margin),","            atTop   : scrollTop < margin,","","            isScrollDown : lastScroll && scrollTop > lastScroll.scrollTop,","            isScrollLeft : lastScroll && scrollLeft < lastScroll.scrollLeft,","            isScrollRight: lastScroll && scrollLeft > lastScroll.scrollLeft,","            isScrollUp   : lastScroll && scrollTop < lastScroll.scrollTop,","","            scrollBottom: scrollBottom,","            scrollHeight: scrollHeight,","            scrollLeft  : scrollLeft,","            scrollRight : scrollRight,","            scrollTop   : scrollTop,","            scrollWidth : scrollWidth","        };","    },","","    /**","    Refreshes cached position, height, and width dimensions for the host node.","    If the host node is the body, then the viewport height and width will be","    used.","","    This info is cached to improve performance during scroll events, since it's","    expensive to touch the DOM for these values. Dimensions are automatically","    refreshed whenever the browser is resized, but if you change the dimensions","    or position of the host node in JS, you may need to call","    `refreshDimensions()` manually to cache the new dimensions.","","    @method refreshDimensions","    **/","    refreshDimensions: function () {","        // WebKit only returns reliable scroll info on the body, and only","        // returns reliable height/width info on the documentElement, so we","        // have to special-case it (see the other special case in","        // _getScrollNode()).","        //","        // On iOS devices, documentElement.clientHeight/Width aren't reliable,","        // but window.innerHeight/Width are. And no, dom-screen's viewport size","        // methods don't account for this, which is why we do it here.","","        var hostIsBody = this._hostIsBody,","            iosHack    = hostIsBody && Y.UA.ios,","            win        = Y.config.win,","            el;","","        if (hostIsBody && Y.UA.webkit) {","            el = Y.config.doc.documentElement;","        } else {","            el = this._scrollNode;","        }","","        this._height = iosHack ? win.innerHeight : el.clientHeight;","        this._left   = el.offsetLeft;","        this._top    = el.offsetTop;","        this._width  = iosHack ? win.innerWidth : el.clientWidth;","    },","","    // -- Protected Methods ----------------------------------------------------","","    /**","    Binds event handlers.","","    @method _bind","    @protected","    **/","    _bind: function () {","        var winNode = Y.one('win');","","        this._events = [","            this.after({","                scrollDelayChange : this._afterScrollDelayChange,","                scrollMarginChange: this._afterScrollMarginChange","            }),","","            winNode.on('windowresize', this._afterResize, this),","","            // If we're attached to the body, listen for the scroll event on the","            // window, since <body> doesn't have a scroll event.","            (this._hostIsBody ? winNode : this._host).after(","                'scroll', this._afterScroll, this)","        ];","    },","","    /**","    Returns the DOM node that should be used to lookup scroll coordinates. In","    some browsers, the `<body>` element doesn't return scroll coordinates, and","    the documentElement must be used instead; this method takes care of","    determining which node should be used.","","    @method _getScrollNode","    @return {HTMLElement} DOM node.","    @protected","    **/","    _getScrollNode: function () {","        // WebKit returns scroll coordinates on the body element, but other","        // browsers don't, so we have to use the documentElement.","        return this._hostIsBody && !Y.UA.webkit ? Y.config.doc.documentElement :","                Y.Node.getDOMNode(this._host);","    },","","    /**","    Mixes detailed scroll information into the given DOM `scroll` event facade","    and fires appropriate local events.","","    @method _triggerScroll","    @param {EventFacade} e Event facade from the DOM `scroll` event.","    @protected","    **/","    _triggerScroll: function (e) {","        var info       = this.getScrollInfo(),","            facade     = Y.merge(e, info),","            lastScroll = this._lastScroll;","","        this._lastScroll = info;","","        this.fire(EVT_SCROLL, facade);","","        if (info.isScrollLeft) {","            this.fire(EVT_SCROLL_LEFT, facade);","        } else if (info.isScrollRight) {","            this.fire(EVT_SCROLL_RIGHT, facade);","        }","","        if (info.isScrollUp) {","            this.fire(EVT_SCROLL_UP, facade);","        } else if (info.isScrollDown) {","            this.fire(EVT_SCROLL_DOWN, facade);","        }","","        if (info.atBottom && (!lastScroll.atBottom ||","                info.scrollHeight > lastScroll.scrollHeight)) {","","            this.fire(EVT_SCROLL_TO_BOTTOM, facade);","        }","","        if (info.atLeft && !lastScroll.atLeft) {","            this.fire(EVT_SCROLL_TO_LEFT, facade);","        }","","        if (info.atRight && (!lastScroll.atRight ||","                info.scrollWidth > lastScroll.scrollWidth)) {","","            this.fire(EVT_SCROLL_TO_RIGHT, facade);","        }","","        if (info.atTop && !lastScroll.atTop) {","            this.fire(EVT_SCROLL_TO_TOP, facade);","        }","    },","","    // -- Protected Event Handlers ---------------------------------------------","","    /**","    Handles browser resize events.","","    @method _afterResize","    @param {EventFacade} e","    @protected","    **/","    _afterResize: function (e) {","        this.refreshDimensions();","    },","","    /**","    Handles DOM `scroll` events.","","    @method _afterScroll","    @param {EventFacade} e","    @protected","    **/","    _afterScroll: function (e) {","        var self = this;","","        clearTimeout(this._scrollTimeout);","","        this._scrollTimeout = setTimeout(function () {","            self._triggerScroll(e);","        }, this._scrollDelay);","    },","","    /**","    Caches the `scrollDelay` value after that attribute changes to allow","    quicker lookups in critical path code.","","    @method _afterScrollDelayChange","    @param {EventFacade} e","    @protected","    **/","    _afterScrollDelayChange: function (e) {","        this._scrollDelay = e.newVal;","    },","","    /**","    Caches the `scrollMargin` value after that attribute changes to allow","    quicker lookups in critical path code.","","    @method _afterScrollMarginChange","    @param {EventFacade} e","    @protected","    **/","    _afterScrollMarginChange: function (e) {","        this._scrollMargin = e.newVal;","    }","}, {","    NS: 'scrollInfo',","","    ATTRS: {","        /**","        Number of milliseconds to wait after a native `scroll` event before","        firing local scroll events. If another native scroll event occurs during","        this time, previous events will be ignored. This ensures that we don't","        fire thousands of events when the user is scrolling quickly.","","        @attribute scrollDelay","        @type Number","        @default 50","        **/","        scrollDelay: {","            value: 50","        },","","        /**","        Additional margin in pixels beyond the onscreen region of the host node","        that should be considered \"onscreen\".","","        For example, if set to 50, then a `scrollToBottom` event would be fired","        when the user scrolls to within 50 pixels of the bottom of the","        scrollable region, even if they don't actually scroll completely to the","        very bottom pixel.","","        This margin also applies to the `getOffscreenNodes()` and","        `getOnscreenNodes()` methods by default.","","        @attribute scrollMargin","        @type Number","        @default 50","        **/","        scrollMargin: {","            value: 50","        }","    }","});","","","}, '3.7.3', {\"requires\": [\"base-build\", \"dom-screen\", \"event-resize\", \"node-pluginhost\", \"plugin\"]});"];36_yuitest_coverage["build/node-scroll-info/node-scroll-info.js"].lines = {"1":0,"69":0,"163":0,"167":0,"168":0,"169":0,"170":0,"171":0,"173":0,"175":0,"177":0,"181":0,"182":0,"203":0,"204":0,"207":0,"217":0,"218":0,"225":0,"228":0,"234":0,"235":0,"237":0,"240":0,"244":0,"264":0,"265":0,"268":0,"278":0,"279":0,"286":0,"289":0,"295":0,"296":0,"298":0,"301":0,"305":0,"321":0,"333":0,"376":0,"381":0,"382":0,"384":0,"387":0,"388":0,"389":0,"390":0,"402":0,"404":0,"432":0,"445":0,"449":0,"451":0,"453":0,"454":0,"455":0,"456":0,"459":0,"460":0,"461":0,"462":0,"465":0,"468":0,"471":0,"472":0,"475":0,"478":0,"481":0,"482":0,"496":0,"507":0,"509":0,"511":0,"512":0,"525":0,"537":0};37_yuitest_coverage["build/node-scroll-info/node-scroll-info.js"].functions = {"initializer:165":0,"destructor:180":0,"(anonymous 2):217":0,"getOffscreenNodes:202":0,"(anonymous 3):278":0,"getOnscreenNodes:263":0,"getScrollInfo:320":0,"refreshDimensions:366":0,"_bind:401":0,"_getScrollNode:429":0,"_triggerScroll:444":0,"_afterResize:495":0,"(anonymous 4):511":0,"_afterScroll:506":0,"_afterScrollDelayChange:524":0,"_afterScrollMarginChange:536":0,"(anonymous 1):1":0};38_yuitest_coverage["build/node-scroll-info/node-scroll-info.js"].coveredLines = 76;39_yuitest_coverage["build/node-scroll-info/node-scroll-info.js"].coveredFunctions = 17;40_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 1);41YUI.add('node-scroll-info', function (Y, NAME) {42/**43Provides the ScrollInfo Node plugin, which exposes convenient events and methods44related to scrolling.45@module node-scroll-info46@since 3.7.047**/48/**49Provides convenient events and methods related to scrolling. This could be used,50for example, to implement infinite scrolling, or to lazy-load content based on51the current scroll position.52### Example53    var body = Y.one('body');54    body.plug(Y.Plugin.ScrollInfo);55    body.scrollInfo.on('scrollToBottom', function (e) {56        // Load more content when the user scrolls to the bottom of the page.57    });58@class Plugin.ScrollInfo59@extends Plugin.Base60@since 3.7.061**/62/**63Fired when the user scrolls within the host node.64This event (like all scroll events exposed by ScrollInfo) is throttled and fired65only after the number of milliseconds specified by the `scrollDelay` attribute66have passed in order to prevent thrashing.67This event passes along the event facade for the standard DOM `scroll` event and68mixes in the following additional properties.69@event scroll70@param {Boolean} atBottom Whether the current scroll position is at the bottom71    of the scrollable region.72@param {Boolean} atLeft Whether the current scroll position is at the extreme73    left of the scrollable region.74@param {Boolean} atRight Whether the current scroll position is at the extreme75    right of the scrollable region.76@param {Boolean} atTop Whether the current scroll position is at the top of the77    scrollable region.78@param {Boolean} isScrollDown `true` if the user scrolled down.79@param {Boolean} isScrollLeft `true` if the user scrolled left.80@param {Boolean} isScrollRight `true` if the user scrolled right.81@param {Boolean} isScrollUp `true` if the user scrolled up.82@param {Number} scrollBottom Y value of the bottom-most onscreen pixel of the83    scrollable region.84@param {Number} scrollHeight Total height in pixels of the scrollable region,85    including offscreen pixels.86@param {Number} scrollLeft X value of the left-most onscreen pixel of the87    scrollable region.88@param {Number} scrollRight X value of the right-most onscreen pixel of the89    scrollable region.90@param {Number} scrollTop Y value of the top-most onscreen pixel of the91    scrollable region.92@param {Number} scrollWidth Total width in pixels of the scrollable region,93    including offscreen pixels.94@see scrollDelay95@see scrollMargin96**/97_yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "(anonymous 1)", 1);98_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 69);99var EVT_SCROLL = 'scroll',100    /**101    Fired when the user scrolls down within the host node.102    This event provides the same event facade as the `scroll` event. See that103    event for details.104    @event scrollDown105    @see scroll106    **/107    EVT_SCROLL_DOWN = 'scrollDown',108    /**109    Fired when the user scrolls left within the host node.110    This event provides the same event facade as the `scroll` event. See that111    event for details.112    @event scrollLeft113    @see scroll114    **/115    EVT_SCROLL_LEFT = 'scrollLeft',116    /**117    Fired when the user scrolls right within the host node.118    This event provides the same event facade as the `scroll` event. See that119    event for details.120    @event scrollRight121    @see scroll122    **/123    EVT_SCROLL_RIGHT = 'scrollRight',124    /**125    Fired when the user scrolls up within the host node.126    This event provides the same event facade as the `scroll` event. See that127    event for details.128    @event scrollUp129    @see scroll130    **/131    EVT_SCROLL_UP = 'scrollUp',132    /**133    Fired when the user scrolls to the bottom of the scrollable region within134    the host node.135    This event provides the same event facade as the `scroll` event. See that136    event for details.137    @event scrollToBottom138    @see scroll139    **/140    EVT_SCROLL_TO_BOTTOM = 'scrollToBottom',141    /**142    Fired when the user scrolls to the extreme left of the scrollable region143    within the host node.144    This event provides the same event facade as the `scroll` event. See that145    event for details.146    @event scrollToLeft147    @see scroll148    **/149    EVT_SCROLL_TO_LEFT = 'scrollToLeft',150    /**151    Fired when the user scrolls to the extreme right of the scrollable region152    within the host node.153    This event provides the same event facade as the `scroll` event. See that154    event for details.155    @event scrollToRight156    @see scroll157    **/158    EVT_SCROLL_TO_RIGHT = 'scrollToRight',159    /**160    Fired when the user scrolls to the top of the scrollable region within the161    host node.162    This event provides the same event facade as the `scroll` event. See that163    event for details.164    @event scrollToTop165    @see scroll166    **/167    EVT_SCROLL_TO_TOP = 'scrollToTop';168_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 163);169Y.Plugin.ScrollInfo = Y.Base.create('scrollInfoPlugin', Y.Plugin.Base, [], {170    // -- Lifecycle Methods ----------------------------------------------------171    initializer: function (config) {172        // Cache for quicker lookups in the critical path.173        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "initializer", 165);174_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 167);175this._host         = config.host;176        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 168);177this._hostIsBody   = this._host.get('nodeName').toLowerCase() === 'body';178        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 169);179this._scrollDelay  = this.get('scrollDelay');180        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 170);181this._scrollMargin = this.get('scrollMargin');182        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 171);183this._scrollNode   = this._getScrollNode();184        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 173);185this.refreshDimensions();186        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 175);187this._lastScroll = this.getScrollInfo();188        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 177);189this._bind();190    },191    destructor: function () {192        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "destructor", 180);193_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 181);194(new Y.EventHandle(this._events)).detach();195        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 182);196delete this._events;197    },198    // -- Public Methods -------------------------------------------------------199    /**200    Returns a NodeList containing all offscreen nodes inside the host node that201    match the given CSS selector. An offscreen node is any node that is entirely202    outside the visible (onscreen) region of the host node based on the current203    scroll location.204    @method getOffscreenNodes205    @param {String} [selector] CSS selector. If omitted, all offscreen nodes206        will be returned.207    @param {Number} [margin] Additional margin in pixels beyond the actual208        onscreen region that should be considered "onscreen" for the purposes of209        this query. Defaults to the value of the `scrollMargin` attribute.210    @return {NodeList} Offscreen nodes matching _selector_.211    @see scrollMargin212    **/213    getOffscreenNodes: function (selector, margin) {214        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "getOffscreenNodes", 202);215_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 203);216if (typeof margin === 'undefined') {217            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 204);218margin = this._scrollMargin;219        }220        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 207);221var lastScroll = this._lastScroll,222            nodes      = this._host.all(selector || '*'),223            scrollBottom = lastScroll.scrollBottom + margin,224            scrollLeft   = lastScroll.scrollLeft - margin,225            scrollRight  = lastScroll.scrollRight + margin,226            scrollTop    = lastScroll.scrollTop - margin,227            self = this;228        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 217);229return nodes.filter(function (el) {230            _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "(anonymous 2)", 217);231_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 218);232var xy     = Y.DOM.getXY(el),233                elLeft = xy[0] - self._left,234                elTop  = xy[1] - self._top,235                elBottom, elRight;236            // Check whether the element's top left point is within the237            // viewport. This is the least expensive check.238            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 225);239if (elLeft >= scrollLeft && elLeft < scrollRight &&240                    elTop >= scrollTop && elTop < scrollBottom) {241                _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 228);242return false;243            }244            // Check whether the element's bottom right point is within the245            // viewport. This check is more expensive since we have to get the246            // element's height and width.247            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 234);248elBottom = elTop + el.offsetHeight;249            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 235);250elRight  = elLeft + el.offsetWidth;251            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 237);252if (elRight < scrollRight && elRight >= scrollLeft &&253                    elBottom < scrollBottom && elBottom >= scrollTop) {254                _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 240);255return false;256            }257            // If we get here, the element isn't within the viewport.258            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 244);259return true;260        });261    },262    /**263    Returns a NodeList containing all onscreen nodes inside the host node that264    match the given CSS selector. An onscreen node is any node that is fully or265    partially within the visible (onscreen) region of the host node based on the266    current scroll location.267    @method getOnscreenNodes268    @param {String} [selector] CSS selector. If omitted, all onscreen nodes will269        be returned.270    @param {Number} [margin] Additional margin in pixels beyond the actual271        onscreen region that should be considered "onscreen" for the purposes of272        this query. Defaults to the value of the `scrollMargin` attribute.273    @return {NodeList} Onscreen nodes matching _selector_.274    @see scrollMargin275    **/276    getOnscreenNodes: function (selector, margin) {277        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "getOnscreenNodes", 263);278_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 264);279if (typeof margin === 'undefined') {280            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 265);281margin = this._scrollMargin;282        }283        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 268);284var lastScroll = this._lastScroll,285            nodes      = this._host.all(selector || '*'),286            scrollBottom = lastScroll.scrollBottom + margin,287            scrollLeft   = lastScroll.scrollLeft - margin,288            scrollRight  = lastScroll.scrollRight + margin,289            scrollTop    = lastScroll.scrollTop - margin,290            self = this;291        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 278);292return nodes.filter(function (el) {293            _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "(anonymous 3)", 278);294_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 279);295var xy     = Y.DOM.getXY(el),296                elLeft = xy[0] - self._left,297                elTop  = xy[1] - self._top,298                elBottom, elRight;299            // Check whether the element's top left point is within the300            // viewport. This is the least expensive check.301            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 286);302if (elLeft >= scrollLeft && elLeft < scrollRight &&303                    elTop >= scrollTop && elTop < scrollBottom) {304                _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 289);305return true;306            }307            // Check whether the element's bottom right point is within the308            // viewport. This check is more expensive since we have to get the309            // element's height and width.310            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 295);311elBottom = elTop + el.offsetHeight;312            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 296);313elRight  = elLeft + el.offsetWidth;314            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 298);315if (elRight < scrollRight && elRight >= scrollLeft &&316                    elBottom < scrollBottom && elBottom >= scrollTop) {317                _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 301);318return true;319            }320            // If we get here, the element isn't within the viewport.321            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 305);322return false;323        });324    },325    /**326    Returns an object hash containing information about the current scroll327    position of the host node. This is the same information that's mixed into328    the event facade of the `scroll` event and other scroll-related events.329    @method getScrollInfo330    @return {Object} Object hash containing information about the current scroll331        position. See the `scroll` event for details on what properties this332        object contains.333    @see scroll334    **/335    getScrollInfo: function () {336        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "getScrollInfo", 320);337_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 321);338var domNode    = this._scrollNode,339            lastScroll = this._lastScroll,340            margin     = this._scrollMargin,341            scrollLeft   = domNode.scrollLeft,342            scrollHeight = domNode.scrollHeight,343            scrollTop    = domNode.scrollTop,344            scrollWidth  = domNode.scrollWidth,345            scrollBottom = scrollTop + this._height,346            scrollRight  = scrollLeft + this._width;347        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 333);348return {349            atBottom: scrollBottom > (scrollHeight - margin),350            atLeft  : scrollLeft < margin,351            atRight : scrollRight > (scrollWidth - margin),352            atTop   : scrollTop < margin,353            isScrollDown : lastScroll && scrollTop > lastScroll.scrollTop,354            isScrollLeft : lastScroll && scrollLeft < lastScroll.scrollLeft,355            isScrollRight: lastScroll && scrollLeft > lastScroll.scrollLeft,356            isScrollUp   : lastScroll && scrollTop < lastScroll.scrollTop,357            scrollBottom: scrollBottom,358            scrollHeight: scrollHeight,359            scrollLeft  : scrollLeft,360            scrollRight : scrollRight,361            scrollTop   : scrollTop,362            scrollWidth : scrollWidth363        };364    },365    /**366    Refreshes cached position, height, and width dimensions for the host node.367    If the host node is the body, then the viewport height and width will be368    used.369    This info is cached to improve performance during scroll events, since it's370    expensive to touch the DOM for these values. Dimensions are automatically371    refreshed whenever the browser is resized, but if you change the dimensions372    or position of the host node in JS, you may need to call373    `refreshDimensions()` manually to cache the new dimensions.374    @method refreshDimensions375    **/376    refreshDimensions: function () {377        // WebKit only returns reliable scroll info on the body, and only378        // returns reliable height/width info on the documentElement, so we379        // have to special-case it (see the other special case in380        // _getScrollNode()).381        //382        // On iOS devices, documentElement.clientHeight/Width aren't reliable,383        // but window.innerHeight/Width are. And no, dom-screen's viewport size384        // methods don't account for this, which is why we do it here.385        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "refreshDimensions", 366);386_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 376);387var hostIsBody = this._hostIsBody,388            iosHack    = hostIsBody && Y.UA.ios,389            win        = Y.config.win,390            el;391        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 381);392if (hostIsBody && Y.UA.webkit) {393            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 382);394el = Y.config.doc.documentElement;395        } else {396            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 384);397el = this._scrollNode;398        }399        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 387);400this._height = iosHack ? win.innerHeight : el.clientHeight;401        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 388);402this._left   = el.offsetLeft;403        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 389);404this._top    = el.offsetTop;405        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 390);406this._width  = iosHack ? win.innerWidth : el.clientWidth;407    },408    // -- Protected Methods ----------------------------------------------------409    /**410    Binds event handlers.411    @method _bind412    @protected413    **/414    _bind: function () {415        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_bind", 401);416_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 402);417var winNode = Y.one('win');418        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 404);419this._events = [420            this.after({421                scrollDelayChange : this._afterScrollDelayChange,422                scrollMarginChange: this._afterScrollMarginChange423            }),424            winNode.on('windowresize', this._afterResize, this),425            // If we're attached to the body, listen for the scroll event on the426            // window, since <body> doesn't have a scroll event.427            (this._hostIsBody ? winNode : this._host).after(428                'scroll', this._afterScroll, this)429        ];430    },431    /**432    Returns the DOM node that should be used to lookup scroll coordinates. In433    some browsers, the `<body>` element doesn't return scroll coordinates, and434    the documentElement must be used instead; this method takes care of435    determining which node should be used.436    @method _getScrollNode437    @return {HTMLElement} DOM node.438    @protected439    **/440    _getScrollNode: function () {441        // WebKit returns scroll coordinates on the body element, but other442        // browsers don't, so we have to use the documentElement.443        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_getScrollNode", 429);444_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 432);445return this._hostIsBody && !Y.UA.webkit ? Y.config.doc.documentElement :446                Y.Node.getDOMNode(this._host);447    },448    /**449    Mixes detailed scroll information into the given DOM `scroll` event facade450    and fires appropriate local events.451    @method _triggerScroll452    @param {EventFacade} e Event facade from the DOM `scroll` event.453    @protected454    **/455    _triggerScroll: function (e) {456        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_triggerScroll", 444);457_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 445);458var info       = this.getScrollInfo(),459            facade     = Y.merge(e, info),460            lastScroll = this._lastScroll;461        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 449);462this._lastScroll = info;463        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 451);464this.fire(EVT_SCROLL, facade);465        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 453);466if (info.isScrollLeft) {467            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 454);468this.fire(EVT_SCROLL_LEFT, facade);469        } else {_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 455);470if (info.isScrollRight) {471            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 456);472this.fire(EVT_SCROLL_RIGHT, facade);473        }}474        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 459);475if (info.isScrollUp) {476            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 460);477this.fire(EVT_SCROLL_UP, facade);478        } else {_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 461);479if (info.isScrollDown) {480            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 462);481this.fire(EVT_SCROLL_DOWN, facade);482        }}483        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 465);484if (info.atBottom && (!lastScroll.atBottom ||485                info.scrollHeight > lastScroll.scrollHeight)) {486            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 468);487this.fire(EVT_SCROLL_TO_BOTTOM, facade);488        }489        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 471);490if (info.atLeft && !lastScroll.atLeft) {491            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 472);492this.fire(EVT_SCROLL_TO_LEFT, facade);493        }494        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 475);495if (info.atRight && (!lastScroll.atRight ||496                info.scrollWidth > lastScroll.scrollWidth)) {497            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 478);498this.fire(EVT_SCROLL_TO_RIGHT, facade);499        }500        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 481);501if (info.atTop && !lastScroll.atTop) {502            _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 482);503this.fire(EVT_SCROLL_TO_TOP, facade);504        }505    },506    // -- Protected Event Handlers ---------------------------------------------507    /**508    Handles browser resize events.509    @method _afterResize510    @param {EventFacade} e511    @protected512    **/513    _afterResize: function (e) {514        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_afterResize", 495);515_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 496);516this.refreshDimensions();517    },518    /**519    Handles DOM `scroll` events.520    @method _afterScroll521    @param {EventFacade} e522    @protected523    **/524    _afterScroll: function (e) {525        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_afterScroll", 506);526_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 507);527var self = this;528        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 509);529clearTimeout(this._scrollTimeout);530        _yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 511);531this._scrollTimeout = setTimeout(function () {532            _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "(anonymous 4)", 511);533_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 512);534self._triggerScroll(e);535        }, this._scrollDelay);536    },537    /**538    Caches the `scrollDelay` value after that attribute changes to allow539    quicker lookups in critical path code.540    @method _afterScrollDelayChange541    @param {EventFacade} e542    @protected543    **/544    _afterScrollDelayChange: function (e) {545        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_afterScrollDelayChange", 524);546_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 525);547this._scrollDelay = e.newVal;548    },549    /**550    Caches the `scrollMargin` value after that attribute changes to allow551    quicker lookups in critical path code.552    @method _afterScrollMarginChange553    @param {EventFacade} e554    @protected555    **/556    _afterScrollMarginChange: function (e) {557        _yuitest_coverfunc("build/node-scroll-info/node-scroll-info.js", "_afterScrollMarginChange", 536);558_yuitest_coverline("build/node-scroll-info/node-scroll-info.js", 537);559this._scrollMargin = e.newVal;560    }561}, {562    NS: 'scrollInfo',563    ATTRS: {564        /**565        Number of milliseconds to wait after a native `scroll` event before566        firing local scroll events. If another native scroll event occurs during567        this time, previous events will be ignored. This ensures that we don't568        fire thousands of events when the user is scrolling quickly.569        @attribute scrollDelay570        @type Number571        @default 50572        **/573        scrollDelay: {574            value: 50575        },576        /**577        Additional margin in pixels beyond the onscreen region of the host node578        that should be considered "onscreen".579        For example, if set to 50, then a `scrollToBottom` event would be fired580        when the user scrolls to within 50 pixels of the bottom of the581        scrollable region, even if they don't actually scroll completely to the582        very bottom pixel.583        This margin also applies to the `getOffscreenNodes()` and584        `getOnscreenNodes()` methods by default.585        @attribute scrollMargin586        @type Number587        @default 50588        **/589        scrollMargin: {590            value: 50591        }592    }593});...ScrollPanel.js
Source:ScrollPanel.js  
1// ScrollPanel.js2var scrollPanels = new Array();3var scrollResizeTimer = null;4var scrollGlobalPosition = 0;5// Initialize the scroll panel variables6function scrollPanelInit(scrollContainer, forceReload) {7    if (!(scrollContainer in scrollPanels)) {8        return;9    }10    var scrollPanel = scrollPanels[scrollContainer];11    var isVerticalLayout = scrollPanel.IsVerticalLayout;12    var isRTL = scrollPanel.IsRTL;13    if (forceReload) {14        // Renew the scroll panel variables15        scrollPanel.Container = null;16        scrollPanel.ScrollAreaContainer = null;17        scrollPanel.LastItem = null;18        scrollPanel.ItemWidth = null;19        scrollPanel.ItemHeight = null;20    }21    // Load the scroll panel element variables22    if (scrollPanel.Container === null) {23        scrollPanel.Container = $cmsj('#' + scrollContainer);24    }25    // Do not proceed when the scroll panel is hidden26    if (!scrollPanel.Container.is(':visible')) {27        return;28    }29    if (scrollPanel.ScrollAreaContainer === null) {30        scrollPanel.ScrollAreaContainer = $cmsj('#' + scrollPanel.InnerContainerId + ':first', scrollPanel.Container);31    }32    if (scrollPanel.SeparatorItem === null) {33        if (scrollPanel.ItemSeparatorClass.length > 0) {34            scrollPanel.SeparatorItem = $cmsj('.' + scrollPanel.ItemSeparatorClass + ':first', scrollPanel.ScrollAreaContainer);35        }36    }37    if (scrollPanel.LastItem === null) {38        // Setup the last item variable (and its related variables) when the default step is not defined39        if (scrollPanel.ItemClass.length > 0) {40            var items = $cmsj('.' + scrollPanel.ItemClass, scrollPanel.Container);41            var itemsVisible = items;42            if (items.first().parent().is(":visible")) {43                // Filter out invisible items (Web part toolbar)44                itemsVisible = items.filter(":visible");45            }46            var lastItem = itemsVisible.last();47            scrollPanel.LastItem = lastItem;48            if (!spIsAbsuluteOrFixed(scrollPanel.Container.parent())) {49                scrollPanel.ScrollAreaContainer.height(scrollPanel.Container.outerHeight());50            }51            if (scrollPanel.ItemWidth === null) {52                // Calculate the ItemWidht according to the rendered items if their class is defined53                var separatorWidth = 0;54                if (scrollPanel.SeparatorItem != null) {55                    separatorWidth = scrollPanel.SeparatorItem.outerWidth();56                }57                scrollPanel.ItemWidth = lastItem.outerWidth() + spTryParseInt(lastItem.css("margin-left"), 0) + spTryParseInt(lastItem.css("margin-right"), 0) + separatorWidth;58            }59            if (scrollPanel.ItemHeight === null) {60                // Calculate the ItemHeight according to the rendered items if their class is defined61                var separatorHeight = 0;62                if (scrollPanel.SeparatorItem != null) {63                    separatorHeight = scrollPanel.SeparatorItem.outerHeight();64                }65                scrollPanel.ItemHeight = lastItem.outerHeight() + spTryParseInt(lastItem.css("margin-top"), 0) + spTryParseInt(lastItem.css("margin-bottom"), 0) + separatorHeight;66            }67            // Expand the scroll area div in order to accommodate all the rendered web part items and ensure its scrolling capabilities68            if (scrollPanel.AdjustScrollAreaSize && !spIsAbsuluteOrFixed(scrollPanel.Container.parent())) {69                if (!isVerticalLayout) {70                    if ((items.length * scrollPanel.ItemWidth) > scrollPanel.ScrollStep) {71                        scrollPanel.ScrollAreaContainer.width((scrollPanel.ItemWidth * items.length) + scrollPanel.Container.outerWidth());72                    }73                }74                else {75                    if ((items.length * scrollPanel.ItemHeight) > scrollPanel.ScrollStep) {76                        scrollPanel.ScrollAreaContainer.height((scrollPanel.ItemHeight * items.length) + scrollPanel.Container.outerHeight());77                    }78                }79            }80        }81        else {82            // Calculate the ItemWidth/Height as a total width/height of the rendered content of the scroll panel (i.e. <UL> -> <LI> structure without css class)83            if ((scrollPanel.ItemWidth === null) || (scrollPanel.ItemHeight === null)) {84                scrollPanel.ItemWidth = scrollPanel.ScrollAreaContainer.outerWidth();85                scrollPanel.ItemHeight = scrollPanel.ScrollAreaContainer.outerHeight();86            }87        }88    }89    // Check whether to slide to the beginning (top/left) when the displayed area is out of boundaries90    if ((scrollPanel.ItemClass.length > 0)) {91        if (!isVerticalLayout) {92            var lastItemLeft = 0;93            if (scrollPanel.LastItem.length > 0) {94                lastItemLeft = scrollPanel.LastItem.position().left;95            }96            if ((scrollPanel.LastItem.length == 0)97			|| (!isRTL && (lastItemLeft < 0) && (lastItemLeft + scrollPanel.LastItem.width() < 0))98			|| (isRTL && (lastItemLeft > scrollPanel.Container.position().left + scrollPanel.Container.width()))) {99                var bodyElem = $cmsj('body');100                if (bodyElem.hasClass('Chrome') && isRTL) {101                    scrollPanel.Container.scrollLeft(scrollPanel.ScrollAreaContainer.outerWidth());102                }103                else {104                    scrollPanel.Container.scrollLeft(0);105                }106                spScrollBack(scrollContainer);107            }108        }109        else {110            if ((scrollPanel.LastItem.length == 0) || (scrollPanel.LastItem.position().top < 0)) {111                scrollPanel.Container.scrollTop(0);112                spScrollBack(scrollContainer);113            }114        }115    }116    // Setup the scroll step and set the forward button visibility117    spSetupForwardScroll(scrollContainer, forceReload);118    // Display/Hide the back scroller119    var backScrollerVisible = false;120    if (!isVerticalLayout) {121        if (!isRTL) {122            backScrollerVisible = (scrollPanel.Container.scrollLeft() > 0);123        }124        else {125            // RTL126            var originalScrollLeft = scrollPanel.Container.scrollLeft();127            // Display the back scroller if it is possible to scroll back by 1px128            var scrollOnePixelForward = (scrollPanel.ForwardScrollStep > 0) ? 1 : -1;129            scrollPanel.Container.scrollLeft(originalScrollLeft - scrollOnePixelForward);130            backScrollerVisible = (scrollPanel.Container.scrollLeft() != originalScrollLeft);131            // Restore the original scroll position132            scrollPanel.Container.scrollLeft(originalScrollLeft);133        }134    }135    else {136        backScrollerVisible = (scrollPanel.Container.scrollTop() > 0);137    }138    if (backScrollerVisible) {139        scrollPanel.BackwardScroller.fadeIn();140    }141    else {142        scrollPanel.BackwardScroller.fadeOut();143    }144    if (forceReload) {145        // Append mouse wheel event on menu146        scrollPanel.Container.mousewheel(function (event, delta) {147            if (delta > 0) { spScrollBack(scrollContainer); }148            else { spScrollForward(scrollContainer); }149            return false;150        });151        // Disable selection of the scroll buttons152        scrollPanel.ForwardScroller.spDisableSelection();153        scrollPanel.BackwardScroller.spDisableSelection();154    }155}156// Setup the scroll step and set the forward button visibility157function spSetupForwardScroll(scrollContainer, forceReload) {158    var scrollPanel = scrollPanels[scrollContainer];159    var isVerticalLayout = scrollPanel.IsVerticalLayout;160    var isRTL = scrollPanel.IsRTL;161    var forwardScrollerFadeIn = (scrollPanel.ItemClass.length == 0);162    var lastItem = scrollPanel.LastItem;163    if (lastItem == null) {164        lastItem = scrollPanel.ScrollAreaContainer.children().last();165    }166    var lastItemVisible = true;167    // Set the lastItemVisible variable only when the whole scroll panel is visible168    if (lastItem.parent().is(":visible")) {169        lastItemVisible = lastItem.is(':visible');170    }171    // Display the last item in order to indicate whether the forward scroll button should be displayed172    if (!lastItemVisible) {173        lastItem.show();174    }175    var containerPosition = scrollPanel.Container.position();176    var containerLeft = containerPosition.left;177    var containerTop = containerPosition.top;178    var docScroll = { x: 0, y: 0 };179    var containerParent = scrollPanel.Container.parent();180    // Get scroll container position for absolute/fixed context menus181    if (spIsAbsuluteOrFixed(containerParent)) {182        var parentContainerPosition = containerParent.offset();183        var parentContainerBorderLeft = parseInt(containerParent.css('border-left-width'), 10);184        var parentContainerBorderTop = parseInt(containerParent.css('border-top-width'), 10);185        containerLeft = parentContainerPosition.left + parentContainerBorderLeft;186        containerTop = parentContainerPosition.top + parentContainerBorderTop;187        // Take in account document scrolling for absolute positioning188        docScroll.x = document.body.scrollLeft || document.documentElement.scrollLeft;189        docScroll.y = document.body.scrollTop || document.documentElement.scrollTop;190    }191    // Decide whether the forward scroller should be displayed192    if (lastItem.length > 0) {193        if (!isVerticalLayout) {194            if (!isRTL) {195                forwardScrollerFadeIn = (lastItem.position().left + lastItem.width() - docScroll.x) > (containerLeft + scrollPanel.Container.width() - spTryParseInt(scrollPanel.ScrollAreaContainer.css('margin-right'), 0));196            }197            else {198                forwardScrollerFadeIn = (lastItem.position().left - docScroll.x) < (containerLeft + spTryParseInt(scrollPanel.ScrollAreaContainer.css('margin-left'), 0));199            }200        }201        else {202            var lastItemMargin = spTryParseInt(lastItem.css('margin-top'), 10);203            forwardScrollerFadeIn = (lastItem.offset().top + scrollPanel.ItemHeight - docScroll.y) > (containerTop + scrollPanel.Container.height() + lastItemMargin - spTryParseInt(scrollPanel.ScrollAreaContainer.css('margin-bottom'), 0));204        }205    }206    // Hide the last item if it was originally hidden207    if (!lastItemVisible) {208        lastItem.hide();209    }210    if (forceReload) {211        scrollPanel.ForwardScrollStep = scrollPanel.ScrollStep;212        // Revert the scroll step for RTL213        if (!scrollPanel.IsVerticalLayout && scrollPanel.IsRTL) {214            // ScrollLeft() in RTL - different behavior for different browsers:215            //                             |  FF  |  IE  |  Chrome/Safari  |216            //                  No scroll: |  0   |  0   |  scrollAreaWidth (example: 4000)217            // After 300px forward scroll: | -300 |  300 |  scrollAreaWidth - 300 (example: 3700)218            // Revert the forward scroll step219            scrollPanel.ForwardScrollStep = (-1) * scrollPanel.ScrollStep;220            var bodyElem = $cmsj('body');221            // Keep the positive step size for IE8/9 bug in RTL222            if (bodyElem.hasClass('IE8') || bodyElem.hasClass('IE9')) {223                scrollPanel.ForwardScrollStep = scrollPanel.ScrollStep;224            }225        }226    }227    if (scrollPanel.Container.is(':visible')) {228        // Display/Hide the forward scroller229        if (forwardScrollerFadeIn) {230            // Set the flag indicating whether the forward scroll is enabled231            scrollPanel.ForwardScrollEnabled = true;232            scrollPanel.ForwardScroller.fadeIn();233        }234        else {235            // Set the flag indicating whether the forward scroll is enabled236            scrollPanel.ForwardScrollEnabled = false;237            scrollPanel.ForwardScroller.fadeOut();238        }239    }240}241// Scroll back by predefined step242function spScrollBack(scrollContainer) {243    var scrollPanel = scrollPanels[scrollContainer];244    if (!scrollPanel.IsVerticalLayout) {245        if (scrollPanel.Container.scrollLeft() != 0) {246            var scroll = scrollPanel.Container.scrollLeft() - scrollPanel.ForwardScrollStep;247            scrollGlobalPosition = scroll;248            scrollPanel.Container.stop().animate({ scrollLeft: scroll }, 300, function () { scrollPanelInit(scrollContainer, false) });249        }250    }251    else {252        if (scrollPanel.Container.scrollTop() != 0) {253            var scroll = scrollPanel.Container.scrollTop() - scrollPanel.ForwardScrollStep;254            scrollGlobalPosition = scroll;255            scrollPanel.Container.stop().animate({ scrollTop: scroll }, 300, function () { scrollPanelInit(scrollContainer, false) });256        }257    }258}259// Scroll to the stored position manually260function spScrollSetPosition(scrollContainer) {261    window.setTimeout(function () {262        var scrollPanel = scrollPanels[scrollContainer];263        if (!scrollPanel.IsVerticalLayout) {264            var bodyElement = $cmsj('body');265            if (bodyElement.hasClass('Chrome') && scrollPanel.IsRTL) {266                var width = scrollPanel.ScrollAreaContainer.outerWidth();267                scrollPanel.Container.scrollLeft(width - scrollPanel.ForwardScrollStep);268            }269            else {270                scrollPanel.Container.scrollLeft(scrollGlobalPosition);271            }272        }273        else {274            scrollPanel.Container.scrollTop(scrollGlobalPosition);275        }276        scrollPanelInit(scrollContainer, false);277    }, 1);278}279// Scroll forward by predefined step280function spScrollForward(scrollContainer) {281    var scrollPanel = scrollPanels[scrollContainer];282    // Enable.disable forward scrolling according to the visibility of the last item283    spSetupForwardScroll(scrollContainer, false);284    if (!scrollPanel.IsVerticalLayout) {285        if (scrollPanel.ForwardScrollEnabled) {286            var scroll = scrollPanel.Container.scrollLeft() + scrollPanel.ForwardScrollStep;287            scrollGlobalPosition = scroll;288            scrollPanel.Container.stop().animate({ scrollLeft: scroll }, 300, function () { scrollPanelInit(scrollContainer, false) });289        }290    }291    else {292        if (scrollPanel.ForwardScrollEnabled) {293            var scroll = scrollPanel.Container.scrollTop() + scrollPanel.ForwardScrollStep;294            scrollGlobalPosition = scroll;295            scrollPanel.Container.stop().animate({ scrollTop: scroll }, 300, function () { scrollPanelInit(scrollContainer, false) });296        }297    }298    // Raise the external OnForwardScroll event299    if (scrollPanel.OnForwardScroll != null) {300        scrollPanel.OnForwardScroll(scrollPanel);301    }302}303// Convert the input string to int. Use defaultValue when the input string is not a number.304function spTryParseInt(str, defaultValue) {305    var retValue = defaultValue;306    if ((typeof (str) != 'undefined') && (str != null) && (str.length > 0)) {307        retValue = parseInt(str, 10);308        if (isNaN(retValue)) {309            retValue = defaultValue;310        }311    }312    return retValue;313}314// Disable selection extender315$cmsj.fn.extend({316    spDisableSelection: function () {317        return this.each(function () {318            this.onselectstart = function () { return false; };319            this.unselectable = "on";320            $cmsj(this)321                .css('user-select', 'none')322                .css('-o-user-select', 'none')323                .css('-moz-user-select', 'none')324                .css('-khtml-user-select', 'none')325                .css('-webkit-user-select', 'none');326        });327    }328});329// Reload all the scrollable panels330$cmsj(window).resize(function () {331    clearTimeout(scrollResizeTimer);332    scrollResizeTimer = setTimeout(function () { spRefreshScrollButtons(); }, 200);333});334// Refresh scroll panel button positions and set container height335function spRefreshScrollButtons() {336    for (var panel in scrollPanels) {337        var scrollPanel = scrollPanels[panel];338        // Proceed only real scroll panels (omit other jQuery system objects)339        if (typeof (scrollPanel.ScrollStep) === 'undefined') {340            continue;341        }342        if (scrollPanel.IsVerticalLayout && window.CKEDITOR) {343            // Refresh scroll panel button positions due to CKToolbar on the page344            // Get forward scroll position345            var forwardScrollerPosition = scrollPanel.ForwardScroller.position().top;346            if (!scrollPanel.ForwardScroller.is(":visible")) {347                scrollPanel.ForwardScroller.show();348                forwardScrollerPosition = scrollPanel.ForwardScroller.position().top;349                scrollPanel.ForwardScroller.hide();350            }351            // Set the container height according to the displayed area (context menus)352            if (!spIsAbsuluteOrFixed(scrollPanel.Container.parent())) {353                scrollPanel.Container.height(forwardScrollerPosition + scrollPanel.ForwardScroller.outerHeight() - scrollPanel.Container.position().top);354            }355            // Move the back scroll button to the corrected top position356            scrollPanel.BackwardScroller.css("top", scrollPanel.Container.position().top);357        }358        // Reload panel properties359        scrollPanelInit(panel, true);360    }361}362// Indicates whether the given object has absolute or fixed position (is context menu)363function spIsAbsuluteOrFixed(jObj) {364    var position = jObj.css('position');365    return ((position == 'absolute') || (position == 'fixed'));...jquery.lazyscrollloading.js
Source:jquery.lazyscrollloading.js  
1/**2 * @preserve jQuery Lazy Scroll Loading Plugin %Revision%3 * 4 * http://plugins.jquery.com/jQueryLazyScrollLoading/5 * https://code.google.com/p/jquerylazyscrollloading/6 * 7 * Apache License 2.0 - http://www.apache.org/licenses/LICENSE-2.08 * 9 * @author Dreamltf10 * @date %BuiltDate%11 * 12 * Depends: jquery.js (1.2+)13 */14(function($) {15	/* static variables */16	var PLUGIN_NAMESPACE = "LazyScrollLoading";17	var PLUGIN_LAZYIMAGE_ATTR = "data-lazyimg";18	/* default options */19	var defaultOptions = {20		"isDefaultLazyImageMode" : false,21		"lazyItemSelector" : null,22		"delay" : 500,23		"resetScrollBarPositionAfterEventTriggered" : true,24		/* callback function */25		"onCreate" : null,26		"onScroll" : null,27		"onLazyItemFirstVisible" : null,28		"onLazyItemVisible" : null,29		"onLazyItemInvisible" : null,30		"onScrollVertically" : null,31		"onScrollHorizontally" : null,32		"onScrollUp" : null,33		"onScrollDown" : null,34		"onScrollLeft" : null,35		"onScrollRight" : null,36		"onScrollToTop" : null,37		"onScrollToBottom" : null,38		"onScrollToLeftmost" : null,39		"onScrollToRightmost" : null40	};41	/* others variables */42	var userAgentStr = navigator.userAgent.toLowerCase();43	var isIE = /msie/.test(userAgentStr);44	var IEVersion = (isIE ? parseFloat((userAgentStr.match(/.*(?:rv|ie)[\/: ](.+?)([ \);]|$)/) || [])[1]) : -1);45	var scrollBarSize = 16;46	/**47	 * Public Method48	 */49	$.extend($.fn, {50		/**51		 * Public : Main method52		 * 53		 * @param options54		 *            Object55		 * @return jQuery56		 */57		"lazyScrollLoading" : function(options) {58			options = $.extend({}, defaultOptions, options);59			/* correct options */60			if (options.isDefaultLazyImageMode && options.lazyItemSelector == null) {61				options.lazyItemSelector = "img[" + PLUGIN_LAZYIMAGE_ATTR + "]:not([src])";62			}63			/* starting */64			return this.each(function() {65				var $container = $(this);66				/* destroy */67				$container.destroyLazyScrollLoading();68				/* prepare options */69				$container.data("options." + PLUGIN_NAMESPACE, options);70				/* initialize */71				initializeLazyScrollLoading($container, options);72				/* trigger event */73				if (options.onCreate != null) {74					options.onCreate.apply($container[0]);75				}76			});77		},78		/**79		 * Public : Get container's options80		 * 81		 * @return Object82		 */83		"getLazyScrollLoadingOptions" : function() {84			return this.data("options." + PLUGIN_NAMESPACE);85		},86		/**87		 * Public : Get container's scroll history88		 * 89		 * @return Object90		 */91		"getLazyScrollLoadingScrollHistory" : function() {92			return this.data("scrollHistory." + PLUGIN_NAMESPACE);93		},94		/**95		 * Public : Clear container's scroll history96		 * 97		 * @return jQuery98		 */99		"clearLazyScrollLoadingScrollHistory" : function() {100			return this.removeData("scrollHistory." + PLUGIN_NAMESPACE);101		},102		/**103		 * Public : Get container or lazyItem's viewport104		 * 105		 * @return Object106		 */107		"getLazyScrollLoadingViewport" : function() {108			var $container = this;109			var containerViewport = $container.data("viewport." + PLUGIN_NAMESPACE);110			if (containerViewport == null) {111				var container = $container[0];112				var isRoot = isRootContainer(container);113				var $window = $(window);114				var $document = $(document);115				var $body = $(document.body);116				containerViewport = {117					"getOffset" : function() {118						return (isRoot ? $body.offset() : $container.offset());119					},120					"getScrollLeft" : function() {121						return (isRoot ? $window : $container).scrollLeft();122					},123					"getScrollTop" : function() {124						return (isRoot ? $window : $container).scrollTop();125					},126					"getScrollBindTarget" : function() {127						return (isRoot ? $window : $container);128					},129					"getWidth" : function(isOuter) {130						return (isRoot ? $window.width() : (isOuter ? $container.outerWidth() : $container.innerWidth()));131					},132					"getHeight" : function(isOuter) {133						return (isRoot ? $window.height() : (isOuter ? $container.outerHeight() : $container.innerHeight()));134					},135					"getScrollWidth" : function(includeScrollBarSize) {136						return (isRoot ? $document.width() : container.scrollWidth) + (includeScrollBarSize && this.isVerticalScrollBarVisible() ? scrollBarSize : 0);137					},138					"getScrollHeight" : function(includeScrollBarSize) {139						return (isRoot ? $document.height() : container.scrollHeight) + (includeScrollBarSize && this.isHorizontalScrollBarVisible() ? scrollBarSize : 0);140					},141					"getLeftPos" : function() {142						return (isRoot ? this.getScrollLeft() : this.getOffset().left);143					},144					"getTopPos" : function() {145						return (isRoot ? this.getScrollTop() : this.getOffset().top);146					},147					"getRightPos" : function() {148						return this.getLeftPos() + this.getWidth(true);149					},150					"getBottomPos" : function() {151						return this.getTopPos() + this.getHeight(true);152					},153					"isVerticalScrollBarVisible" : function() {154						return (this.getHeight(false) < this.getScrollHeight(false));155					},156					"isHorizontalScrollBarVisible" : function() {157						return (this.getWidth(false) < this.getScrollWidth(false));158					},159					"isVerticalScrollBarScrolling" : function() {160						if (!this.isVerticalScrollBarVisible()) {161							return false;162						}163						var containerScrollHistory = $container.getLazyScrollLoadingScrollHistory();164						return (containerScrollHistory != null && containerScrollHistory.scrollTop != this.getScrollTop());165					},166					"isHorizontalScrollBarScrolling" : function() {167						if (!this.isHorizontalScrollBarVisible()) {168							return false;169						}170						var containerScrollHistory = $container.getLazyScrollLoadingScrollHistory();171						return (containerScrollHistory != null && containerScrollHistory.scrollLeft != this.getScrollLeft());172					},173					"isScrollUp" : function() {174						if (!this.isVerticalScrollBarVisible()) {175							return false;176						}177						var containerScrollHistory = $container.getLazyScrollLoadingScrollHistory();178						return (containerScrollHistory != null && containerScrollHistory.scrollTop > this.getScrollTop());179					},180					"isScrollDown" : function() {181						if (!this.isVerticalScrollBarVisible()) {182							return false;183						}184						var containerScrollHistory = $container.getLazyScrollLoadingScrollHistory();185						return (containerScrollHistory != null && containerScrollHistory.scrollTop < this.getScrollTop());186					},187					"isScrollLeft" : function() {188						if (!this.isHorizontalScrollBarVisible()) {189							return false;190						}191						var containerScrollHistory = $container.getLazyScrollLoadingScrollHistory();192						return (containerScrollHistory != null && containerScrollHistory.scrollLeft > this.getScrollLeft());193					},194					"isScrollRight" : function() {195						if (!this.isHorizontalScrollBarVisible()) {196							return false;197						}198						var containerScrollHistory = $container.getLazyScrollLoadingScrollHistory();199						return (containerScrollHistory != null && containerScrollHistory.scrollLeft < this.getScrollLeft());200					},201					"isScrollToTop" : function() {202						if (!this.isVerticalScrollBarVisible()) {203							return false;204						}205						return (this.getScrollTop() <= 0);206					},207					"isScrollToBottom" : function() {208						if (!this.isVerticalScrollBarVisible()) {209							return false;210						}211						return (this.getScrollTop() + this.getHeight(true) >= this.getScrollHeight(true));212					},213					"isScrollToLeftmost" : function() {214						if (!this.isHorizontalScrollBarVisible()) {215							return false;216						}217						return (this.getScrollLeft() <= 0);218					},219					"isScrollToRightmost" : function() {220						if (!this.isHorizontalScrollBarVisible()) {221							return false;222						}223						return (this.getScrollLeft() + this.getWidth(true) >= this.getScrollWidth(true));224					}225				};226			}227			$container.data("viewport." + PLUGIN_NAMESPACE, containerViewport)228			return containerViewport;229		},230		/**231		 * Public : Get container's cached lazy items232		 * 233		 * @param selector234		 *            String235		 * @return jQuery236		 */237		"getLazyScrollLoadingCachedLazyItems" : function(selector) {238			return this.pushStack($.map(this, function(container) {239				var $container = $(container);240				var options = $container.getLazyScrollLoadingOptions();241				var $lazyItems = $container.data("items." + PLUGIN_NAMESPACE);242				if (options != null && options.lazyItemSelector != null && $lazyItems == null) {243					/* cache lazy items if necessary */244					$lazyItems = $(options.lazyItemSelector, (isRootContainer(container) ? undefined : $container));245					$container.data("items." + PLUGIN_NAMESPACE, $lazyItems);246				}247				if ($lazyItems != null && selector != null) {248					$lazyItems = $lazyItems.filter(selector);249				}250				return ($lazyItems != null ? $lazyItems.get() : null);251			}));252		},253		/**254		 * Public : Clear container's cached lazy items255		 * 256		 * @return jQuery257		 */258		"clearLazyScrollLoadingCachedLazyItems" : function() {259			return this.removeData("items." + PLUGIN_NAMESPACE);260		},261		/**262		 * Public : Refresh container263		 * 264		 * @return jQuery265		 */266		"refreshLazyScrollLoading" : function() {267			return this.clearLazyScrollLoadingCachedLazyItems();268		},269		/**270		 * Public : Destroy LazyScrollLoading271		 * 272		 * @return jQuery273		 */274		"destroyLazyScrollLoading" : function() {275			/* yield event handler */276			return this.each(function() {277				var $container = $(this);278				/* reset event handler */279				$container.getLazyScrollLoadingViewport().getScrollBindTarget().unbind("scroll." + PLUGIN_NAMESPACE);280				/* clear cache */281				$container.getLazyScrollLoadingCachedLazyItems().removeData("isLoaded." + PLUGIN_NAMESPACE);282				$container.clearLazyScrollLoadingCachedLazyItems().clearLazyScrollLoadingScrollHistory().removeData("viewport." + PLUGIN_NAMESPACE).removeData("options." + PLUGIN_NAMESPACE);283			});284		},285		/**286		 * Public : Is lazy item loaded287		 * 288		 * @return boolean289		 */290		"isLazyScrollLoadingLazyItemLoaded" : function() {291			return this.data("isLoaded." + PLUGIN_NAMESPACE);292		},293		/**294		 * Public : Is lazy item loading295		 * 296		 * @return boolean297		 */298		"isLazyScrollLoadingLazyItemLoading" : function() {299			return this.data("isLoading." + PLUGIN_NAMESPACE);300		},301		/**302		 * Public : Is lazy item visible303		 * 304		 * @param $container305		 *            jQuery306		 * @return boolean307		 */308		"isLazyScrollLoadingLazyItemVisible" : function($container) {309			var lazyItemViewport = this.getLazyScrollLoadingViewport();310			var containerViewport = $container.getLazyScrollLoadingViewport();311			/* calculate isVisible by position */312			return (lazyItemViewport.getBottomPos() > containerViewport.getTopPos() && lazyItemViewport.getLeftPos() < containerViewport.getRightPos() && lazyItemViewport.getTopPos() < containerViewport.getBottomPos() && lazyItemViewport.getRightPos() > containerViewport.getLeftPos());313		}314	});315	/**316	 * Private : Is Root Container317	 */318	function isRootContainer(container) {319		return (container == window || container == document || container == document.body);320	}321	/**322	 * Private : Initialize LazyScrollLoading323	 */324	function initializeLazyScrollLoading($container, options) {325		var containerViewport = $container.getLazyScrollLoadingViewport();326		var $scrollBindTarget = containerViewport.getScrollBindTarget();327		/* starting */328		var isTimerOn = false;329		var timer = null;330		$scrollBindTarget.bind("scroll." + PLUGIN_NAMESPACE, function(e) {331			if (options.delay <= 0) {332				fireOnScrollEvent(e, $container, options);333			} else if (!isTimerOn) {334				isTimerOn = true;335				if (timer != null) {336					clearTimeout(timer);337				}338				timer = setTimeout(function() {339					fireOnScrollEvent(e, $container, options);340					/* clear timer */341					clearTimeout(timer);342					isTimerOn = false;343				}, options.delay);344			}345		});346		/* on first window loaded, for visible element only */347		/* IE version < 9 would not be triggered the onscroll event */348		if ((containerViewport.getScrollTop() <= 0 && containerViewport.getScrollLeft() <= 0) || (isIE && IEVersion < 9)) {349			$scrollBindTarget.trigger("scroll." + PLUGIN_NAMESPACE);350		}351	}352	/**353	 * Private : Fire OnScroll Event354	 */355	function fireOnScrollEvent(e, $container, options) {356		var $lazyItems = $container.getLazyScrollLoadingCachedLazyItems();357		var lazyItemVisibleArray = [];358		var lazyItemFirstVisibleArray = [];359		var lazyItemInvisibleArray = [];360		if (options.lazyItemSelector != null && (options.isDefaultLazyImageMode || options.onLazyItemFirstVisible != null || options.onLazyItemVisible != null || options.onLazyItemInvisible != null)) {361			$lazyItems.each(function() {362				var $lazyItem = $(this);363				/* is lazy item visible */364				if ($lazyItem.isLazyScrollLoadingLazyItemVisible($container)) {365					$lazyItem.data("isLoading." + PLUGIN_NAMESPACE, true);366					lazyItemVisibleArray.push(this);367					if (!$lazyItem.isLazyScrollLoadingLazyItemLoaded()) {368						$lazyItem.data("isLoaded." + PLUGIN_NAMESPACE, true);369						lazyItemFirstVisibleArray.push(this);370					}371				} else if ($lazyItem.isLazyScrollLoadingLazyItemLoading()) {372					$lazyItem.removeData("isLoading." + PLUGIN_NAMESPACE);373					lazyItemInvisibleArray.push(this);374				}375			});376			/* lazy image mode */377			if (options.isDefaultLazyImageMode) {378				for (var i = 0, lazyItemFirstVisibleArraySize = lazyItemFirstVisibleArray.length; i < lazyItemFirstVisibleArraySize; i++) {379					var lazyImageItem = lazyItemFirstVisibleArray[i];380					lazyImageItem.src = lazyImageItem.getAttribute(PLUGIN_LAZYIMAGE_ATTR);381				}382			}383		}384		/* keep the old scrollTop and scrollLeft */385		var containerViewport = $container.getLazyScrollLoadingViewport();386		var scrollTop = containerViewport.getScrollTop();387		var scrollLeft = containerViewport.getScrollLeft();388		var newScrollHistory = {389			"scrollTop" : scrollTop,390			"scrollLeft" : scrollLeft391		};392		triggerCallbackFunctions(e, $container, options, $lazyItems, lazyItemVisibleArray, lazyItemFirstVisibleArray, lazyItemInvisibleArray);393		/* reset the scrollbar after event triggered */394		if (options.resetScrollBarPositionAfterEventTriggered) {395			$container.scrollTop(scrollTop);396			$container.scrollLeft(scrollLeft);397		}398		/* reset history to record previous scroll position */399		$container.data("scrollHistory." + PLUGIN_NAMESPACE, newScrollHistory);400	}401	/**402	 * Private : Trigger Customized OnScroll Event403	 */404	function triggerCallbackFunctions(e, $container, options, $lazyItems, lazyItemVisibleArray, lazyItemFirstVisibleArray, lazyItemInvisibleArray) {405		var container = $container[0];406		/* trigger callback */407		if (options.onScroll != null) {408			options.onScroll.apply(container, [ e ]);409		}410		if (options.onScrollVertically != null || options.onScrollUp != null || options.onScrollDown != null || options.onScrollToTop != null || options.onScrollToBottom != null || options.onScrollHorizontally != null || options.onScrollLeft != null || options.onScrollRight != null411				|| options.onScrollToLeftmost != null || options.onScrollToRightmost != null) {412			var containerViewport = $container.getLazyScrollLoadingViewport();413			var defaultApplyParameter = [ e, $lazyItems ];414			if (containerViewport.isVerticalScrollBarScrolling()) {415				if (options.onScrollVertically != null) {416					options.onScrollVertically.apply(container, defaultApplyParameter);417				}418				if (options.onScrollUp != null && containerViewport.isScrollUp()) {419					options.onScrollUp.apply(container, defaultApplyParameter);420				}421				if (options.onScrollDown != null && containerViewport.isScrollDown()) {422					options.onScrollDown.apply(container, defaultApplyParameter);423				}424				if (options.onScrollToTop != null && containerViewport.isScrollToTop()) {425					options.onScrollToTop.apply(container, defaultApplyParameter);426				}427				if (options.onScrollToBottom != null && containerViewport.isScrollToBottom()) {428					options.onScrollToBottom.apply(container, defaultApplyParameter);429				}430			}431			if (containerViewport.isHorizontalScrollBarScrolling()) {432				if (options.onScrollHorizontally != null) {433					options.onScrollHorizontally.apply(container, defaultApplyParameter);434				}435				if (options.onScrollLeft != null && containerViewport.isScrollLeft()) {436					options.onScrollLeft.apply(container, defaultApplyParameter);437				}438				if (options.onScrollRight != null && containerViewport.isScrollRight()) {439					options.onScrollRight.apply(container, defaultApplyParameter);440				}441				if (options.onScrollToLeftmost != null && containerViewport.isScrollToLeftmost()) {442					options.onScrollToLeftmost.apply(container, defaultApplyParameter);443				}444				if (options.onScrollToRightmost != null && containerViewport.isScrollToRightmost()) {445					options.onScrollToRightmost.apply(container, defaultApplyParameter);446				}447			}448		}449		if (options.onLazyItemFirstVisible != null && lazyItemFirstVisibleArray.length > 0) {450			options.onLazyItemFirstVisible.apply(container, [ e, $lazyItems, $container.pushStack(lazyItemFirstVisibleArray) ]);451		}452		if (options.onLazyItemVisible != null && lazyItemVisibleArray.length > 0) {453			options.onLazyItemVisible.apply(container, [ e, $lazyItems, $container.pushStack(lazyItemVisibleArray) ]);454		}455		if (options.onLazyItemInvisible != null && lazyItemInvisibleArray.length > 0) {456			options.onLazyItemInvisible.apply(container, [ e, $lazyItems, $container.pushStack(lazyItemInvisibleArray) ]);457		}458	}...index.js
Source:index.js  
1'use strict';2exports.__esModule = true;3var _off = require('dom-helpers/events/off');4var _off2 = _interopRequireDefault(_off);5var _on = require('dom-helpers/events/on');6var _on2 = _interopRequireDefault(_on);7var _scrollLeft = require('dom-helpers/query/scrollLeft');8var _scrollLeft2 = _interopRequireDefault(_scrollLeft);9var _scrollTop = require('dom-helpers/query/scrollTop');10var _scrollTop2 = _interopRequireDefault(_scrollTop);11var _requestAnimationFrame = require('dom-helpers/util/requestAnimationFrame');12var _requestAnimationFrame2 = _interopRequireDefault(_requestAnimationFrame);13var _invariant = require('invariant');14var _invariant2 = _interopRequireDefault(_invariant);15var _utils = require('./utils');16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }17function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /* eslint-disable no-underscore-dangle */18// Try at most this many times to scroll, to avoid getting stuck.19var MAX_SCROLL_ATTEMPTS = 2;20var ScrollBehavior = function () {21  function ScrollBehavior(_ref) {22    var _this = this;23    var addTransitionHook = _ref.addTransitionHook,24        stateStorage = _ref.stateStorage,25        getCurrentLocation = _ref.getCurrentLocation,26        shouldUpdateScroll = _ref.shouldUpdateScroll;27    _classCallCheck(this, ScrollBehavior);28    this._restoreScrollRestoration = function () {29      /* istanbul ignore if: not supported by any browsers on Travis */30      if (_this._oldScrollRestoration) {31        try {32          window.history.scrollRestoration = _this._oldScrollRestoration;33        } catch (e) {34          /* silence */35        }36      }37    };38    this._onWindowScroll = function () {39      // It's possible that this scroll operation was triggered by what will be a40      // `POP` transition. Instead of updating the saved location immediately, we41      // have to enqueue the update, then potentially cancel it if we observe a42      // location update.43      if (!_this._saveWindowPositionHandle) {44        _this._saveWindowPositionHandle = (0, _requestAnimationFrame2.default)(_this._saveWindowPosition);45      }46      if (_this._windowScrollTarget) {47        var _windowScrollTarget = _this._windowScrollTarget,48            xTarget = _windowScrollTarget[0],49            yTarget = _windowScrollTarget[1];50        var x = (0, _scrollLeft2.default)(window);51        var y = (0, _scrollTop2.default)(window);52        if (x === xTarget && y === yTarget) {53          _this._windowScrollTarget = null;54          _this._cancelCheckWindowScroll();55        }56      }57    };58    this._saveWindowPosition = function () {59      _this._saveWindowPositionHandle = null;60      _this._savePosition(null, window);61    };62    this._checkWindowScrollPosition = function () {63      _this._checkWindowScrollHandle = null;64      // We can only get here if scrollTarget is set. Every code path that unsets65      // scroll target also cancels the handle to avoid calling this handler.66      // Still, check anyway just in case.67      /* istanbul ignore if: paranoid guard */68      if (!_this._windowScrollTarget) {69        return;70      }71      _this.scrollToTarget(window, _this._windowScrollTarget);72      ++_this._numWindowScrollAttempts;73      /* istanbul ignore if: paranoid guard */74      if (_this._numWindowScrollAttempts >= MAX_SCROLL_ATTEMPTS) {75        _this._windowScrollTarget = null;76        return;77      }78      _this._checkWindowScrollHandle = (0, _requestAnimationFrame2.default)(_this._checkWindowScrollPosition);79    };80    this._stateStorage = stateStorage;81    this._getCurrentLocation = getCurrentLocation;82    this._shouldUpdateScroll = shouldUpdateScroll;83    // This helps avoid some jankiness in fighting against the browser's84    // default scroll behavior on `POP` transitions.85    /* istanbul ignore else: Travis browsers all support this */86    if ('scrollRestoration' in window.history &&87    // Unfortunately, Safari on iOS freezes for 2-6s after the user swipes to88    // navigate through history with scrollRestoration being 'manual', so we89    // need to detect this browser and exclude it from the following code90    // until this bug is fixed by Apple.91    !(0, _utils.isMobileSafari)()) {92      this._oldScrollRestoration = window.history.scrollRestoration;93      try {94        window.history.scrollRestoration = 'manual';95        // Scroll restoration persists across page reloads. We want to reset96        // this to the original value, so that we can let the browser handle97        // restoring the initial scroll position on server-rendered pages.98        (0, _on2.default)(window, 'beforeunload', this._restoreScrollRestoration);99      } catch (e) {100        this._oldScrollRestoration = null;101      }102    } else {103      this._oldScrollRestoration = null;104    }105    this._saveWindowPositionHandle = null;106    this._checkWindowScrollHandle = null;107    this._windowScrollTarget = null;108    this._numWindowScrollAttempts = 0;109    this._scrollElements = {};110    // We have to listen to each window scroll update rather than to just111    // location updates, because some browsers will update scroll position112    // before emitting the location change.113    (0, _on2.default)(window, 'scroll', this._onWindowScroll);114    this._removeTransitionHook = addTransitionHook(function () {115      _requestAnimationFrame2.default.cancel(_this._saveWindowPositionHandle);116      _this._saveWindowPositionHandle = null;117      Object.keys(_this._scrollElements).forEach(function (key) {118        var scrollElement = _this._scrollElements[key];119        _requestAnimationFrame2.default.cancel(scrollElement.savePositionHandle);120        scrollElement.savePositionHandle = null;121        // It's fine to save element scroll positions here, though; the browser122        // won't modify them.123        _this._saveElementPosition(key);124      });125    });126  }127  ScrollBehavior.prototype.registerElement = function registerElement(key, element, shouldUpdateScroll, context) {128    var _this2 = this;129    !!this._scrollElements[key] ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'ScrollBehavior: There is already an element registered for `%s`.', key) : (0, _invariant2.default)(false) : void 0;130    var saveElementPosition = function saveElementPosition() {131      _this2._saveElementPosition(key);132    };133    var scrollElement = {134      element: element,135      shouldUpdateScroll: shouldUpdateScroll,136      savePositionHandle: null,137      onScroll: function onScroll() {138        if (!scrollElement.savePositionHandle) {139          scrollElement.savePositionHandle = (0, _requestAnimationFrame2.default)(saveElementPosition);140        }141      }142    };143    this._scrollElements[key] = scrollElement;144    (0, _on2.default)(element, 'scroll', scrollElement.onScroll);145    this._updateElementScroll(key, null, context);146  };147  ScrollBehavior.prototype.unregisterElement = function unregisterElement(key) {148    !this._scrollElements[key] ? process.env.NODE_ENV !== 'production' ? (0, _invariant2.default)(false, 'ScrollBehavior: There is no element registered for `%s`.', key) : (0, _invariant2.default)(false) : void 0;149    var _scrollElements$key = this._scrollElements[key],150        element = _scrollElements$key.element,151        onScroll = _scrollElements$key.onScroll,152        savePositionHandle = _scrollElements$key.savePositionHandle;153    (0, _off2.default)(element, 'scroll', onScroll);154    _requestAnimationFrame2.default.cancel(savePositionHandle);155    delete this._scrollElements[key];156  };157  ScrollBehavior.prototype.updateScroll = function updateScroll(prevContext, context) {158    var _this3 = this;159    this._updateWindowScroll(prevContext, context);160    Object.keys(this._scrollElements).forEach(function (key) {161      _this3._updateElementScroll(key, prevContext, context);162    });163  };164  ScrollBehavior.prototype.stop = function stop() {165    this._restoreScrollRestoration();166    (0, _off2.default)(window, 'scroll', this._onWindowScroll);167    this._cancelCheckWindowScroll();168    this._removeTransitionHook();169  };170  ScrollBehavior.prototype._cancelCheckWindowScroll = function _cancelCheckWindowScroll() {171    _requestAnimationFrame2.default.cancel(this._checkWindowScrollHandle);172    this._checkWindowScrollHandle = null;173  };174  ScrollBehavior.prototype._saveElementPosition = function _saveElementPosition(key) {175    var scrollElement = this._scrollElements[key];176    scrollElement.savePositionHandle = null;177    this._savePosition(key, scrollElement.element);178  };179  ScrollBehavior.prototype._savePosition = function _savePosition(key, element) {180    this._stateStorage.save(this._getCurrentLocation(), key, [(0, _scrollLeft2.default)(element), (0, _scrollTop2.default)(element)]);181  };182  ScrollBehavior.prototype._updateWindowScroll = function _updateWindowScroll(prevContext, context) {183    // Whatever we were doing before isn't relevant any more.184    this._cancelCheckWindowScroll();185    this._windowScrollTarget = this._getScrollTarget(null, this._shouldUpdateScroll, prevContext, context);186    // Updating the window scroll position is really flaky. Just trying to187    // scroll it isn't enough. Instead, try to scroll a few times until it188    // works.189    this._numWindowScrollAttempts = 0;190    this._checkWindowScrollPosition();191  };192  ScrollBehavior.prototype._updateElementScroll = function _updateElementScroll(key, prevContext, context) {193    var _scrollElements$key2 = this._scrollElements[key],194        element = _scrollElements$key2.element,195        shouldUpdateScroll = _scrollElements$key2.shouldUpdateScroll;196    var scrollTarget = this._getScrollTarget(key, shouldUpdateScroll, prevContext, context);197    if (!scrollTarget) {198      return;199    }200    // Unlike with the window, there shouldn't be any flakiness to deal with201    // here.202    this.scrollToTarget(element, scrollTarget);203  };204  ScrollBehavior.prototype._getDefaultScrollTarget = function _getDefaultScrollTarget(location) {205    var hash = location.hash;206    if (hash && hash !== '#') {207      return hash.charAt(0) === '#' ? hash.slice(1) : hash;208    }209    return [0, 0];210  };211  ScrollBehavior.prototype._getScrollTarget = function _getScrollTarget(key, shouldUpdateScroll, prevContext, context) {212    var scrollTarget = shouldUpdateScroll ? shouldUpdateScroll.call(this, prevContext, context) : true;213    if (!scrollTarget || Array.isArray(scrollTarget) || typeof scrollTarget === 'string') {214      return scrollTarget;215    }216    var location = this._getCurrentLocation();217    return this._getSavedScrollTarget(key, location) || this._getDefaultScrollTarget(location);218  };219  ScrollBehavior.prototype._getSavedScrollTarget = function _getSavedScrollTarget(key, location) {220    if (location.action === 'PUSH') {221      return null;222    }223    return this._stateStorage.read(location, key);224  };225  ScrollBehavior.prototype.scrollToTarget = function scrollToTarget(element, target) {226    if (typeof target === 'string') {227      var targetElement = document.getElementById(target) || document.getElementsByName(target)[0];228      if (targetElement) {229        targetElement.scrollIntoView();230        return;231      }232      // Fallback to scrolling to top when target fragment doesn't exist.233      target = [0, 0]; // eslint-disable-line no-param-reassign234    }235    var _target = target,236        left = _target[0],237        top = _target[1];238    (0, _scrollLeft2.default)(element, left);239    (0, _scrollTop2.default)(element, top);240  };241  return ScrollBehavior;242}();243exports.default = ScrollBehavior;...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
