From c5fc7295a40b7318ebb6ecd2768c156c0d5c7623 Mon Sep 17 00:00:00 2001 From: winkidney Date: Fri, 29 Nov 2019 00:16:28 +0800 Subject: [PATCH] Feature: LoadMore in Pins view done --- pinry-spa/src/components/Pins.vue | 35 +++++++++++++++++++++++++++---- pinry-spa/src/components/api.js | 2 +- pinry-spa/src/components/utils/browser.js | 15 +++++++++++++ pinry-spa/src/components/utils/scroll.js | 27 ++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 pinry-spa/src/components/utils/browser.js create mode 100644 pinry-spa/src/components/utils/scroll.js diff --git a/pinry-spa/src/components/Pins.vue b/pinry-spa/src/components/Pins.vue index 24d6e62..f4757be 100644 --- a/pinry-spa/src/components/Pins.vue +++ b/pinry-spa/src/components/Pins.vue @@ -60,6 +60,7 @@ import API from './api'; import pinHandler from './utils/PinHandler'; import PinPreview from './PinPreview.vue'; import loadingSpinner from './loadingSpinner.vue'; +import scroll from './utils/scroll'; function createImageItem(pin) { const image = {}; @@ -101,6 +102,17 @@ export default { }, }, methods: { + registerScrollEvent() { + const self = this; + scroll.bindScroll2Bottom( + () => { + if (self.status.loading || !self.status.hasNext) { + return; + } + self.fetchMore(); + }, + ); + }, buildBlocks(results) { const blocks = []; results.forEach( @@ -125,14 +137,23 @@ export default { }, ); }, - fetchMore(created) { - let promise; + shouldFetchMore(created) { if (!created) { if (this.status.loading) { - return; + return false; + } + if (!this.status.hasNext) { + return false; } } + return true; + }, + fetchMore(created) { + if (!this.shouldFetchMore(created)) { + return; + } this.status.loading = true; + let promise; if (this.pinFilters.tagFilter) { promise = API.fetchPins(this.status.offset, this.pinFilters.tagFilter); } else if (this.pinFilters.userFilter) { @@ -144,7 +165,12 @@ export default { } promise.then( (resp) => { - this.blocks = this.buildBlocks(resp.data.results); + const { results, next } = resp.data; + let newBlocks = this.buildBlocks(results); + newBlocks = this.blocks.concat(newBlocks); + this.blocks = newBlocks; + this.status.offset = newBlocks.length; + this.status.hasNext = !(next === null); this.status.loading = false; }, () => { this.status.loading = false; }, @@ -152,6 +178,7 @@ export default { }, }, created() { + this.registerScrollEvent(); this.fetchMore(true); }, }; diff --git a/pinry-spa/src/components/api.js b/pinry-spa/src/components/api.js index d4dc40d..9bea45d 100644 --- a/pinry-spa/src/components/api.js +++ b/pinry-spa/src/components/api.js @@ -24,7 +24,7 @@ function fetchPinsForBoard(boardId) { (resolve, reject) => { axios.get(url).then( (resp) => { - resolve({ data: { results: resp.data.pins_detail } }); + resolve({ data: { results: resp.data.pins_detail, next: null } }); }, error => reject(error), ); diff --git a/pinry-spa/src/components/utils/browser.js b/pinry-spa/src/components/utils/browser.js new file mode 100644 index 0000000..396fced --- /dev/null +++ b/pinry-spa/src/components/utils/browser.js @@ -0,0 +1,15 @@ +const utils = { + getDocumentHeight() { + const html = document.documentElement; + return Math.max( + document.body.scrollHeight, document.body.offsetHeight, + html.clientHeight, html.scrollHeight, + html.offsetHeight, + ); + }, + getWindowHeight() { + return window.innerHeight; + }, +}; + +export default utils; diff --git a/pinry-spa/src/components/utils/scroll.js b/pinry-spa/src/components/utils/scroll.js new file mode 100644 index 0000000..f68a54c --- /dev/null +++ b/pinry-spa/src/components/utils/scroll.js @@ -0,0 +1,27 @@ +import utils from './browser'; + +function getDocumentScrollTop() { + const doc = document.documentElement; + return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0); +} + +function onScroll2Bottom(callback) { + const windowPosition = getDocumentScrollTop() + window.innerHeight; + const bottom = utils.getDocumentHeight() - 100; + if (windowPosition > bottom) { + callback(); + } +} + +function bindScroll2Bottom(callback) { + window.addEventListener( + 'scroll', + () => { + onScroll2Bottom(callback); + }, + ); +} + +export default { + bindScroll2Bottom, +};