From dc6133c4c4e67c1403dd98f42c86331b8a2170d8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 26 May 2023 18:05:29 +0100 Subject: [PATCH] Image manager: added ability to trigger load more via scroll --- resources/js/components/image-manager.js | 46 ++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/resources/js/components/image-manager.js b/resources/js/components/image-manager.js index 2c9c1d0cc..dddf6ad8f 100644 --- a/resources/js/components/image-manager.js +++ b/resources/js/components/image-manager.js @@ -41,6 +41,7 @@ export class ImageManager extends Component { } setupListeners() { + // Filter tab click onSelect(this.filterTabs, e => { this.resetAll(); this.filter = e.target.dataset.filter; @@ -48,31 +49,32 @@ export class ImageManager extends Component { this.loadGallery(); }); + // Search submit this.searchForm.addEventListener('submit', event => { this.resetListView(); this.loadGallery(); event.preventDefault(); }); + // Cancel search button onSelect(this.cancelSearch, () => { this.resetListView(); this.resetSearchView(); this.loadGallery(); }); - onChildEvent(this.container, '.load-more button', 'click', async event => { - const wrapper = event.target.closest('.load-more'); - showLoading(wrapper); - this.page += 1; - await this.loadGallery(); - }); + // Load more button click + onChildEvent(this.container, '.load-more button', 'click', this.runLoadMore.bind(this)); + // Select image event this.listContainer.addEventListener('event-emit-select-image', this.onImageSelectEvent.bind(this)); + // Image load error handling this.listContainer.addEventListener('error', event => { event.target.src = window.baseUrl('loading_error.png'); }, true); + // Footer select button click onSelect(this.selectButton, () => { if (this.callback) { this.callback(this.lastSelected); @@ -80,17 +82,39 @@ export class ImageManager extends Component { this.hide(); }); + // Delete button click onChildEvent(this.formContainer, '#image-manager-delete', 'click', () => { if (this.lastSelected) { this.loadImageEditForm(this.lastSelected.id, true); } }); + // Edit form submit this.formContainer.addEventListener('ajax-form-success', () => { this.refreshGallery(); this.resetEditForm(); }); + + // Image upload success this.container.addEventListener('dropzone-upload-success', this.refreshGallery.bind(this)); + + // Auto load-more on scroll + const scrollZone = this.listContainer.parentElement; + let scrollEvents = []; + scrollZone.addEventListener('wheel', event => { + const scrollOffset = Math.ceil(scrollZone.scrollHeight - scrollZone.scrollTop); + const bottomedOut = scrollOffset === scrollZone.clientHeight; + if (!bottomedOut || event.deltaY < 1) { + return; + } + + const secondAgo = Date.now() - 1000; + scrollEvents.push(Date.now()); + scrollEvents = scrollEvents.filter(d => d >= secondAgo); + if (scrollEvents.length > 5 && this.canLoadMore()) { + this.runLoadMore(); + } + }); } show(callback, type = 'gallery') { @@ -232,4 +256,14 @@ export class ImageManager extends Component { window.$components.init(this.formContainer); } + runLoadMore() { + showLoading(this.loadMore); + this.page += 1; + this.loadGallery(); + } + + canLoadMore() { + return this.loadMore.querySelector('button') && !this.loadMore.hasAttribute('hidden'); + } + }