diff options
Diffstat (limited to 'client/components/lists/listBody.js')
-rw-r--r-- | client/components/lists/listBody.js | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 1001f3bc..501459d9 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -1,6 +1,34 @@ const subManager = new SubsManager(); +const InfiniteScrollIter = 10; BlazeComponent.extendComponent({ + onCreated() { + // for infinite scrolling + this.cardlimit = new ReactiveVar(InfiniteScrollIter); + }, + + onRendered() { + const domElement = this.find('.js-perfect-scrollbar'); + + this.$(domElement).on('scroll', () => this.updateList(domElement)); + $(window).on(`resize.${this.data().listId}`, () => this.updateList(domElement)); + + // we add a Mutation Observer to allow propagations of cardlimit + // when the spinner stays in the current view (infinite scrolling) + this.mutationObserver = new MutationObserver(() => this.updateList(domElement)); + + this.mutationObserver.observe(domElement, { + childList: true, + }); + + this.updateList(domElement); + }, + + onDestroyed() { + $(window).off(`resize.${this.data().listId}`); + this.mutationObserver.disconnect(); + }, + mixins() { return [Mixins.PerfectScrollbar]; }, @@ -60,6 +88,13 @@ BlazeComponent.extendComponent({ type: 'cardType-card', }); + // if the displayed card count is less than the total cards in the list, + // we need to increment the displayed card count to prevent the spinner + // to appear + const cardCount = this.data().cards(this.idOrNull(swimlaneId)).count(); + if (pthis.cardlimit.get() < cardCount) { + this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter); + } // In case the filter is active we need to add the newly inserted card in // the list of exceptions -- cards that are not filtered. Otherwise the @@ -119,6 +154,52 @@ BlazeComponent.extendComponent({ return undefined; }, + cardsWithLimit(swimlaneId) { + const limit = this.cardlimit.get(); + const selector = { + listId: this.currentData()._id, + archived: false, + }; + if (swimlaneId) + selector.swimlaneId = swimlaneId; + return Cards.find(Filter.mongoSelector(selector), { + sort: ['sort'], + limit, + }); + }, + + spinnerInView(container) { + const parentViewHeight = container.clientHeight; + const bottomViewPosition = container.scrollTop + parentViewHeight; + + const spinner = this.find('.sk-spinner-list'); + + const threshold = spinner.offsetTop; + + return bottomViewPosition > threshold; + }, + + showSpinner(swimlaneId) { + const list = Template.currentData(); + return list.cards(swimlaneId).count() > this.cardlimit.get(); + }, + + updateList(container) { + // first, if the spinner is not rendered, we have reached the end of + // the list of cards, so skip and disable firing the events + const target = this.find('.sk-spinner-list'); + if (!target) { + this.$(container).off('scroll'); + $(window).off(`resize.${this.data().listId}`); + return; + } + + if (this.spinnerInView(container)) { + this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter); + Ps.update(container); + } + }, + canSeeAddCard() { return !this.reachedWipLimit() && Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); }, |