1 // Call the content module's getMoreItems() action whenever the bottom
2 // edge of the content view is [within pxThreshold of being] visible.
4 // If getMoreItems() returns a promise, bottom edge visibility will be
5 // tested again when that promise is resolved. This should be used
6 // whenever getMoreItems() adds any new items, to cover the case where
7 // the bottom of the content view is still visible after a new page of
10 // It is the responsibility of getMoreItems() to ignore subsequent
11 // calls while it's busy retrieving or preparing additional content.
12 module.exports = InfiniteScroll;
14 var m = require('mithril')
15 , jQuery = require('jquery');
17 function InfiniteScroll(contentCtrl, contentView, opts) {
20 scroller.controller = function() {
21 this.contentCtrl = contentCtrl;
22 this.getMoreItems = this.contentCtrl.getMoreItems.bind(this.contentCtrl);
23 this.pxThreshold = opts.pxThreshold || 0;
24 this.onunload = onunload.bind(this);
25 function onunload () {
27 InfiniteScroll.controllers().map(function(ctrl) {
29 InfiniteScroll.elements().splice(i, 1);
30 InfiniteScroll.controllers().splice(i, 1);
37 scroller.view = function(ctrl) {
38 return m('.container', {config: function(el, isInit, ctx) {
39 return scroller.configEl(el, isInit, ctx, ctrl);
41 contentView(ctrl.contentCtrl)
44 scroller.configEl = function(el, isInit, ctx, ctrl) {
46 if (InfiniteScroll.elements().indexOf(el) < 0) {
47 InfiniteScroll.elements().push(el);
48 InfiniteScroll.controllers().push(ctrl);
53 InfiniteScroll.elements = m.prop([]);
54 InfiniteScroll.controllers = m.prop([]);
57 function scrollHandler(event) {
58 InfiniteScroll.elements().map(function(el, i) {
59 var ctrl = InfiniteScroll.controllers()[i];
61 el.getBoundingClientRect().bottom -
62 document.documentElement.clientHeight;
64 if (pxBeforeEnd > ctrl.pxThreshold)
66 if ((promised = ctrl.getMoreItems()) && promised.then)
67 promised.then(scrollHandler);
70 jQuery(window).on('DOMContentLoaded load resize scroll', scrollHandler);