src/cm/media/js/lib/yui/yui3-3.15.0/build/node-scroll-info/node-scroll-info.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('node-scroll-info', function (Y, NAME) {
       
     2 
       
     3 /*jshint onevar:false */
       
     4 
       
     5 /**
       
     6 Provides the ScrollInfo Node plugin, which exposes convenient events and methods
       
     7 related to scrolling.
       
     8 
       
     9 @module node-scroll-info
       
    10 @since 3.7.0
       
    11 **/
       
    12 
       
    13 /**
       
    14 Provides convenient events and methods related to scrolling. This could be used,
       
    15 for example, to implement infinite scrolling, or to lazy-load content based on
       
    16 the current scroll position.
       
    17 
       
    18 ### Example
       
    19 
       
    20     var body = Y.one('body');
       
    21 
       
    22     body.plug(Y.Plugin.ScrollInfo);
       
    23 
       
    24     body.scrollInfo.on('scrollToBottom', function (e) {
       
    25         // Load more content when the user scrolls to the bottom of the page.
       
    26     });
       
    27 
       
    28 @class Plugin.ScrollInfo
       
    29 @extends Plugin.Base
       
    30 @since 3.7.0
       
    31 **/
       
    32 
       
    33 var doc = Y.config.doc,
       
    34     win = Y.config.win;
       
    35 
       
    36 /**
       
    37 Fired when the user scrolls within the host node.
       
    38 
       
    39 This event (like all scroll events exposed by ScrollInfo) is throttled and fired
       
    40 only after the number of milliseconds specified by the `scrollDelay` attribute
       
    41 have passed in order to prevent thrashing.
       
    42 
       
    43 This event passes along the event facade for the standard DOM `scroll` event and
       
    44 mixes in the following additional properties.
       
    45 
       
    46 @event scroll
       
    47 @param {Boolean} atBottom Whether the current scroll position is at the bottom
       
    48     of the scrollable region.
       
    49 @param {Boolean} atLeft Whether the current scroll position is at the extreme
       
    50     left of the scrollable region.
       
    51 @param {Boolean} atRight Whether the current scroll position is at the extreme
       
    52     right of the scrollable region.
       
    53 @param {Boolean} atTop Whether the current scroll position is at the top of the
       
    54     scrollable region.
       
    55 @param {Boolean} isScrollDown `true` if the user scrolled down.
       
    56 @param {Boolean} isScrollLeft `true` if the user scrolled left.
       
    57 @param {Boolean} isScrollRight `true` if the user scrolled right.
       
    58 @param {Boolean} isScrollUp `true` if the user scrolled up.
       
    59 @param {Number} scrollBottom Y value of the bottom-most onscreen pixel of the
       
    60     scrollable region.
       
    61 @param {Number} scrollHeight Total height in pixels of the scrollable region,
       
    62     including offscreen pixels.
       
    63 @param {Number} scrollLeft X value of the left-most onscreen pixel of the
       
    64     scrollable region.
       
    65 @param {Number} scrollRight X value of the right-most onscreen pixel of the
       
    66     scrollable region.
       
    67 @param {Number} scrollTop Y value of the top-most onscreen pixel of the
       
    68     scrollable region.
       
    69 @param {Number} scrollWidth Total width in pixels of the scrollable region,
       
    70     including offscreen pixels.
       
    71 @see scrollDelay
       
    72 @see scrollMargin
       
    73 **/
       
    74 var EVT_SCROLL = 'scroll',
       
    75 
       
    76     /**
       
    77     Fired when the user scrolls down within the host node.
       
    78 
       
    79     This event provides the same event facade as the `scroll` event. See that
       
    80     event for details.
       
    81 
       
    82     @event scrollDown
       
    83     @see scroll
       
    84     **/
       
    85     EVT_SCROLL_DOWN = 'scrollDown',
       
    86 
       
    87     /**
       
    88     Fired when the user scrolls left within the host node.
       
    89 
       
    90     This event provides the same event facade as the `scroll` event. See that
       
    91     event for details.
       
    92 
       
    93     @event scrollLeft
       
    94     @see scroll
       
    95     **/
       
    96     EVT_SCROLL_LEFT = 'scrollLeft',
       
    97 
       
    98     /**
       
    99     Fired when the user scrolls right within the host node.
       
   100 
       
   101     This event provides the same event facade as the `scroll` event. See that
       
   102     event for details.
       
   103 
       
   104     @event scrollRight
       
   105     @see scroll
       
   106     **/
       
   107     EVT_SCROLL_RIGHT = 'scrollRight',
       
   108 
       
   109     /**
       
   110     Fired when the user scrolls up within the host node.
       
   111 
       
   112     This event provides the same event facade as the `scroll` event. See that
       
   113     event for details.
       
   114 
       
   115     @event scrollUp
       
   116     @see scroll
       
   117     **/
       
   118     EVT_SCROLL_UP = 'scrollUp',
       
   119 
       
   120     /**
       
   121     Fired when the user scrolls to the bottom of the scrollable region within
       
   122     the host node.
       
   123 
       
   124     This event provides the same event facade as the `scroll` event. See that
       
   125     event for details.
       
   126 
       
   127     @event scrollToBottom
       
   128     @see scroll
       
   129     **/
       
   130     EVT_SCROLL_TO_BOTTOM = 'scrollToBottom',
       
   131 
       
   132     /**
       
   133     Fired when the user scrolls to the extreme left of the scrollable region
       
   134     within the host node.
       
   135 
       
   136     This event provides the same event facade as the `scroll` event. See that
       
   137     event for details.
       
   138 
       
   139     @event scrollToLeft
       
   140     @see scroll
       
   141     **/
       
   142     EVT_SCROLL_TO_LEFT = 'scrollToLeft',
       
   143 
       
   144     /**
       
   145     Fired when the user scrolls to the extreme right of the scrollable region
       
   146     within the host node.
       
   147 
       
   148     This event provides the same event facade as the `scroll` event. See that
       
   149     event for details.
       
   150 
       
   151     @event scrollToRight
       
   152     @see scroll
       
   153     **/
       
   154     EVT_SCROLL_TO_RIGHT = 'scrollToRight',
       
   155 
       
   156     /**
       
   157     Fired when the user scrolls to the top of the scrollable region within the
       
   158     host node.
       
   159 
       
   160     This event provides the same event facade as the `scroll` event. See that
       
   161     event for details.
       
   162 
       
   163     @event scrollToTop
       
   164     @see scroll
       
   165     **/
       
   166     EVT_SCROLL_TO_TOP = 'scrollToTop';
       
   167 
       
   168 Y.Plugin.ScrollInfo = Y.Base.create('scrollInfoPlugin', Y.Plugin.Base, [], {
       
   169     // -- Protected Properties -------------------------------------------------
       
   170 
       
   171     /**
       
   172     Height of the visible region of the host node in pixels. If the host node is
       
   173     the body, this will be the same as `_winHeight`.
       
   174 
       
   175     @property {Number} _height
       
   176     @protected
       
   177     **/
       
   178 
       
   179     /**
       
   180     Whether or not the host node is the `<body>` element.
       
   181 
       
   182     @property {Boolean} _hostIsBody
       
   183     @protected
       
   184     **/
       
   185 
       
   186     /**
       
   187     Width of the visible region of the host node in pixels. If the host node is
       
   188     the body, this will be the same as `_winWidth`.
       
   189 
       
   190     @property {Number} _width
       
   191     @protected
       
   192     **/
       
   193 
       
   194     /**
       
   195     Height of the viewport in pixels.
       
   196 
       
   197     @property {Number} _winHeight
       
   198     @protected
       
   199     **/
       
   200 
       
   201     /**
       
   202     Width of the viewport in pixels.
       
   203 
       
   204     @property {Number} _winWidth
       
   205     @protected
       
   206     **/
       
   207 
       
   208     // -- Lifecycle Methods ----------------------------------------------------
       
   209     initializer: function (config) {
       
   210         // Cache for quicker lookups in the critical path.
       
   211         this._host                  = config.host;
       
   212         this._hostIsBody            = this._host.get('nodeName').toLowerCase() === 'body';
       
   213         this._scrollDelay           = this.get('scrollDelay');
       
   214         this._scrollMargin          = this.get('scrollMargin');
       
   215         this._scrollNode            = this._getScrollNode();
       
   216 
       
   217         this.refreshDimensions();
       
   218 
       
   219         this._lastScroll = this.getScrollInfo();
       
   220 
       
   221         this._bind();
       
   222     },
       
   223 
       
   224     destructor: function () {
       
   225         new Y.EventHandle(this._events).detach();
       
   226         this._events = null;
       
   227     },
       
   228 
       
   229     // -- Public Methods -------------------------------------------------------
       
   230 
       
   231     /**
       
   232     Returns a NodeList containing all offscreen nodes inside the host node that
       
   233     match the given CSS selector. An offscreen node is any node that is entirely
       
   234     outside the visible (onscreen) region of the host node based on the current
       
   235     scroll location.
       
   236 
       
   237     @method getOffscreenNodes
       
   238     @param {String} [selector] CSS selector. If omitted, all offscreen nodes
       
   239         will be returned.
       
   240     @param {Number} [margin] Additional margin in pixels beyond the actual
       
   241         onscreen region that should be considered "onscreen" for the purposes of
       
   242         this query. Defaults to the value of the `scrollMargin` attribute.
       
   243     @return {NodeList} Offscreen nodes matching _selector_.
       
   244     @see scrollMargin
       
   245     **/
       
   246     getOffscreenNodes: function (selector, margin) {
       
   247         if (typeof margin === 'undefined') {
       
   248             margin = this._scrollMargin;
       
   249         }
       
   250 
       
   251         var elements = Y.Selector.query(selector || '*', this._host._node);
       
   252 
       
   253         return new Y.NodeList(Y.Array.filter(elements, function (el) {
       
   254             return !this._isElementOnscreen(el, margin);
       
   255         }, this));
       
   256     },
       
   257 
       
   258     /**
       
   259     Returns a NodeList containing all onscreen nodes inside the host node that
       
   260     match the given CSS selector. An onscreen node is any node that is fully or
       
   261     partially within the visible (onscreen) region of the host node based on the
       
   262     current scroll location.
       
   263 
       
   264     @method getOnscreenNodes
       
   265     @param {String} [selector] CSS selector. If omitted, all onscreen nodes will
       
   266         be returned.
       
   267     @param {Number} [margin] Additional margin in pixels beyond the actual
       
   268         onscreen region that should be considered "onscreen" for the purposes of
       
   269         this query. Defaults to the value of the `scrollMargin` attribute.
       
   270     @return {NodeList} Onscreen nodes matching _selector_.
       
   271     @see scrollMargin
       
   272     **/
       
   273     getOnscreenNodes: function (selector, margin) {
       
   274         if (typeof margin === 'undefined') {
       
   275             margin = this._scrollMargin;
       
   276         }
       
   277 
       
   278         var elements = Y.Selector.query(selector || '*', this._host._node);
       
   279 
       
   280         return new Y.NodeList(Y.Array.filter(elements, function (el) {
       
   281             return this._isElementOnscreen(el, margin);
       
   282         }, this));
       
   283     },
       
   284 
       
   285     /**
       
   286     Returns an object hash containing information about the current scroll
       
   287     position of the host node. This is the same information that's mixed into
       
   288     the event facade of the `scroll` event and other scroll-related events.
       
   289 
       
   290     @method getScrollInfo
       
   291     @return {Object} Object hash containing information about the current scroll
       
   292         position. See the `scroll` event for details on what properties this
       
   293         object contains.
       
   294     @see scroll
       
   295     **/
       
   296     getScrollInfo: function () {
       
   297         var domNode    = this._scrollNode,
       
   298             lastScroll = this._lastScroll,
       
   299             margin     = this._scrollMargin,
       
   300 
       
   301             scrollLeft   = domNode.scrollLeft,
       
   302             scrollHeight = domNode.scrollHeight,
       
   303             scrollTop    = domNode.scrollTop,
       
   304             scrollWidth  = domNode.scrollWidth,
       
   305 
       
   306             scrollBottom = scrollTop + this._height,
       
   307             scrollRight  = scrollLeft + this._width;
       
   308 
       
   309         return {
       
   310             atBottom: scrollBottom > (scrollHeight - margin),
       
   311             atLeft  : scrollLeft < margin,
       
   312             atRight : scrollRight > (scrollWidth - margin),
       
   313             atTop   : scrollTop < margin,
       
   314 
       
   315             isScrollDown : lastScroll && scrollTop > lastScroll.scrollTop,
       
   316             isScrollLeft : lastScroll && scrollLeft < lastScroll.scrollLeft,
       
   317             isScrollRight: lastScroll && scrollLeft > lastScroll.scrollLeft,
       
   318             isScrollUp   : lastScroll && scrollTop < lastScroll.scrollTop,
       
   319 
       
   320             scrollBottom: scrollBottom,
       
   321             scrollHeight: scrollHeight,
       
   322             scrollLeft  : scrollLeft,
       
   323             scrollRight : scrollRight,
       
   324             scrollTop   : scrollTop,
       
   325             scrollWidth : scrollWidth
       
   326         };
       
   327     },
       
   328 
       
   329     /**
       
   330     Returns `true` if _node_ is at least partially onscreen within the host
       
   331     node, `false` otherwise.
       
   332 
       
   333     @method isNodeOnscreen
       
   334     @param {HTMLElement|Node|String} node Node or selector to check.
       
   335     @param {Number} [margin] Additional margin in pixels beyond the actual
       
   336         onscreen region that should be considered "onscreen" for the purposes of
       
   337         this query. Defaults to the value of the `scrollMargin` attribute.
       
   338     @return {Boolean} `true` if _node_ is at least partially onscreen within the
       
   339         host node, `false` otherwise.
       
   340     @since 3.11.0
       
   341     **/
       
   342     isNodeOnscreen: function (node, margin) {
       
   343         node = Y.one(node);
       
   344         return !!(node && this._isElementOnscreen(node._node, margin));
       
   345     },
       
   346 
       
   347     /**
       
   348     Refreshes cached position, height, and width dimensions for the host node.
       
   349     If the host node is the body, then the viewport height and width will be
       
   350     used.
       
   351 
       
   352     This info is cached to improve performance during scroll events, since it's
       
   353     expensive to touch the DOM for these values. Dimensions are automatically
       
   354     refreshed whenever the browser is resized, but if you change the dimensions
       
   355     or position of the host node in JS, you may need to call
       
   356     `refreshDimensions()` manually to cache the new dimensions.
       
   357 
       
   358     @method refreshDimensions
       
   359     **/
       
   360     refreshDimensions: function () {
       
   361         var docEl = doc.documentElement;
       
   362 
       
   363         // On iOS devices and on Chrome for Android,
       
   364         // documentElement.clientHeight/Width aren't reliable, but
       
   365         // window.innerHeight/Width are. The dom-screen module's viewport size
       
   366         // methods don't account for this, which is why we do it here.
       
   367         if (Y.UA.ios || (Y.UA.android && Y.UA.chrome)) {
       
   368             this._winHeight = win.innerHeight;
       
   369             this._winWidth  = win.innerWidth;
       
   370         } else {
       
   371             this._winHeight = docEl.clientHeight;
       
   372             this._winWidth  = docEl.clientWidth;
       
   373         }
       
   374 
       
   375         if (this._hostIsBody) {
       
   376             this._height = this._winHeight;
       
   377             this._width  = this._winWidth;
       
   378         } else {
       
   379             this._height = this._scrollNode.clientHeight;
       
   380             this._width  = this._scrollNode.clientWidth;
       
   381         }
       
   382 
       
   383         this._refreshHostBoundingRect();
       
   384     },
       
   385 
       
   386     // -- Protected Methods ----------------------------------------------------
       
   387 
       
   388     /**
       
   389     Binds event handlers.
       
   390 
       
   391     @method _bind
       
   392     @protected
       
   393     **/
       
   394     _bind: function () {
       
   395         var winNode = Y.one('win');
       
   396 
       
   397         this._events = [
       
   398             this.after({
       
   399                 scrollDelayChange : this._afterScrollDelayChange,
       
   400                 scrollMarginChange: this._afterScrollMarginChange
       
   401             }),
       
   402 
       
   403             winNode.on('windowresize', this._afterResize, this)
       
   404         ];
       
   405 
       
   406         // If the host node is the body, listen for the scroll event on the
       
   407         // window, since <body> doesn't have a scroll event.
       
   408         if (this._hostIsBody) {
       
   409             this._events.push(winNode.after('scroll', this._afterHostScroll, this));
       
   410         } else {
       
   411             // The host node is not the body, but we still need to listen for
       
   412             // window scroll events so we can determine whether nodes are
       
   413             // onscreen.
       
   414             this._events.push(
       
   415                 winNode.after('scroll', this._afterWindowScroll, this),
       
   416                 this._host.after('scroll', this._afterHostScroll, this)
       
   417             );
       
   418         }
       
   419     },
       
   420 
       
   421     /**
       
   422     Returns the DOM node that should be used to lookup scroll coordinates. In
       
   423     some browsers, the `<body>` element doesn't return scroll coordinates, and
       
   424     the documentElement must be used instead; this method takes care of
       
   425     determining which node should be used.
       
   426 
       
   427     @method _getScrollNode
       
   428     @return {HTMLElement} DOM node.
       
   429     @protected
       
   430     **/
       
   431     _getScrollNode: function () {
       
   432         // WebKit returns scroll coordinates on the body element, but other
       
   433         // browsers don't, so we have to use the documentElement.
       
   434         return this._hostIsBody && !Y.UA.webkit ? doc.documentElement :
       
   435                 Y.Node.getDOMNode(this._host);
       
   436     },
       
   437 
       
   438     /**
       
   439     Underlying element-based implementation for `isNodeOnscreen()`.
       
   440 
       
   441     @method _isElementOnscreen
       
   442     @param {HTMLElement} el HTML element.
       
   443     @param {Number} [margin] Additional margin in pixels beyond the actual
       
   444         onscreen region that should be considered "onscreen" for the purposes of
       
   445         this query. Defaults to the value of the `scrollMargin` attribute.
       
   446     @return {Boolean} `true` if _el_ is at least partially onscreen within the
       
   447         host node, `false` otherwise.
       
   448     @protected
       
   449     @since 3.11.0
       
   450     **/
       
   451     _isElementOnscreen: function (el, margin) {
       
   452         var hostRect = this._hostRect,
       
   453             rect     = el.getBoundingClientRect();
       
   454 
       
   455         if (typeof margin === 'undefined') {
       
   456             margin = this._scrollMargin;
       
   457         }
       
   458 
       
   459         // Determine whether any part of _el_ is within the visible region of
       
   460         // the host element or the specified margin around the visible region of
       
   461         // the host element.
       
   462         return !(rect.top > hostRect.bottom + margin
       
   463                     || rect.bottom < hostRect.top - margin
       
   464                     || rect.right < hostRect.left - margin
       
   465                     || rect.left > hostRect.right + margin);
       
   466     },
       
   467 
       
   468     /**
       
   469     Caches the bounding rect of the host node.
       
   470 
       
   471     If the host node is the body, the bounding rect will be faked to represent
       
   472     the dimensions of the viewport, since the actual body dimensions may extend
       
   473     beyond the viewport and we only care about the visible region.
       
   474 
       
   475     @method _refreshHostBoundingRect
       
   476     @protected
       
   477     **/
       
   478     _refreshHostBoundingRect: function () {
       
   479         var winHeight = this._winHeight,
       
   480             winWidth  = this._winWidth,
       
   481 
       
   482             hostRect;
       
   483 
       
   484         if (this._hostIsBody) {
       
   485             hostRect = {
       
   486                 bottom: winHeight,
       
   487                 height: winHeight,
       
   488                 left  : 0,
       
   489                 right : winWidth,
       
   490                 top   : 0,
       
   491                 width : winWidth
       
   492             };
       
   493 
       
   494             this._isHostOnscreen = true;
       
   495         } else {
       
   496             hostRect = this._scrollNode.getBoundingClientRect();
       
   497         }
       
   498 
       
   499         this._hostRect = hostRect;
       
   500     },
       
   501 
       
   502     /**
       
   503     Mixes detailed scroll information into the given DOM `scroll` event facade
       
   504     and fires appropriate local events.
       
   505 
       
   506     @method _triggerScroll
       
   507     @param {EventFacade} e Event facade from the DOM `scroll` event.
       
   508     @protected
       
   509     **/
       
   510     _triggerScroll: function (e) {
       
   511         var info       = this.getScrollInfo(),
       
   512             facade     = Y.merge(e, info),
       
   513             lastScroll = this._lastScroll;
       
   514 
       
   515         this._lastScroll = info;
       
   516 
       
   517         this.fire(EVT_SCROLL, facade);
       
   518 
       
   519         if (info.isScrollLeft) {
       
   520             this.fire(EVT_SCROLL_LEFT, facade);
       
   521         } else if (info.isScrollRight) {
       
   522             this.fire(EVT_SCROLL_RIGHT, facade);
       
   523         }
       
   524 
       
   525         if (info.isScrollUp) {
       
   526             this.fire(EVT_SCROLL_UP, facade);
       
   527         } else if (info.isScrollDown) {
       
   528             this.fire(EVT_SCROLL_DOWN, facade);
       
   529         }
       
   530 
       
   531         if (info.atBottom && (!lastScroll.atBottom ||
       
   532                 info.scrollHeight > lastScroll.scrollHeight)) {
       
   533 
       
   534             this.fire(EVT_SCROLL_TO_BOTTOM, facade);
       
   535         }
       
   536 
       
   537         if (info.atLeft && !lastScroll.atLeft) {
       
   538             this.fire(EVT_SCROLL_TO_LEFT, facade);
       
   539         }
       
   540 
       
   541         if (info.atRight && (!lastScroll.atRight ||
       
   542                 info.scrollWidth > lastScroll.scrollWidth)) {
       
   543 
       
   544             this.fire(EVT_SCROLL_TO_RIGHT, facade);
       
   545         }
       
   546 
       
   547         if (info.atTop && !lastScroll.atTop) {
       
   548             this.fire(EVT_SCROLL_TO_TOP, facade);
       
   549         }
       
   550     },
       
   551 
       
   552     // -- Protected Event Handlers ---------------------------------------------
       
   553 
       
   554     /**
       
   555     Handles DOM `scroll` events on the host node.
       
   556 
       
   557     @method _afterHostScroll
       
   558     @param {EventFacade} e
       
   559     @protected
       
   560     **/
       
   561     _afterHostScroll: function (e) {
       
   562         var self = this;
       
   563 
       
   564         clearTimeout(this._scrollTimeout);
       
   565 
       
   566         this._scrollTimeout = setTimeout(function () {
       
   567             self._triggerScroll(e);
       
   568         }, this._scrollDelay);
       
   569     },
       
   570 
       
   571     /**
       
   572     Handles browser resize events.
       
   573 
       
   574     @method _afterResize
       
   575     @protected
       
   576     **/
       
   577     _afterResize: function () {
       
   578         this.refreshDimensions();
       
   579     },
       
   580 
       
   581     /**
       
   582     Caches the `scrollDelay` value after that attribute changes to allow
       
   583     quicker lookups in critical path code.
       
   584 
       
   585     @method _afterScrollDelayChange
       
   586     @param {EventFacade} e
       
   587     @protected
       
   588     **/
       
   589     _afterScrollDelayChange: function (e) {
       
   590         this._scrollDelay = e.newVal;
       
   591     },
       
   592 
       
   593     /**
       
   594     Caches the `scrollMargin` value after that attribute changes to allow
       
   595     quicker lookups in critical path code.
       
   596 
       
   597     @method _afterScrollMarginChange
       
   598     @param {EventFacade} e
       
   599     @protected
       
   600     **/
       
   601     _afterScrollMarginChange: function (e) {
       
   602         this._scrollMargin = e.newVal;
       
   603     },
       
   604 
       
   605     /**
       
   606     Handles DOM `scroll` events on the window.
       
   607 
       
   608     @method _afterWindowScroll
       
   609     @param {EventFacade} e
       
   610     @protected
       
   611     **/
       
   612     _afterWindowScroll: function () {
       
   613         this._refreshHostBoundingRect();
       
   614     }
       
   615 }, {
       
   616     NS: 'scrollInfo',
       
   617 
       
   618     ATTRS: {
       
   619         /**
       
   620         Number of milliseconds to wait after a native `scroll` event before
       
   621         firing local scroll events. If another native scroll event occurs during
       
   622         this time, previous events will be ignored. This ensures that we don't
       
   623         fire thousands of events when the user is scrolling quickly.
       
   624 
       
   625         @attribute scrollDelay
       
   626         @type Number
       
   627         @default 50
       
   628         **/
       
   629         scrollDelay: {
       
   630             value: 50
       
   631         },
       
   632 
       
   633         /**
       
   634         Additional margin in pixels beyond the onscreen region of the host node
       
   635         that should be considered "onscreen".
       
   636 
       
   637         For example, if set to 50, then a `scrollToBottom` event would be fired
       
   638         when the user scrolls to within 50 pixels of the bottom of the
       
   639         scrollable region, even if they don't actually scroll completely to the
       
   640         very bottom pixel.
       
   641 
       
   642         This margin also applies to the `getOffscreenNodes()` and
       
   643         `getOnscreenNodes()` methods by default.
       
   644 
       
   645         @attribute scrollMargin
       
   646         @type Number
       
   647         @default 50
       
   648         **/
       
   649         scrollMargin: {
       
   650             value: 50
       
   651         }
       
   652     }
       
   653 });
       
   654 
       
   655 
       
   656 }, '@VERSION@', {"requires": ["array-extras", "base-build", "event-resize", "node-pluginhost", "plugin", "selector"]});