<slot></slot> <script> import { virtualListStore } from './virtualListStore' import throttle from 'lodash/throttle' import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen' import { mark, stop } from '../../_utils/marks' import { scheduleIdleTask } from '../../_utils/scheduleIdleTask' import { isMobile } from '../../_utils/isMobile' const SCROLL_EVENT_DELAY = 300 export default { oncreate() { mark('onCreate VirtualListContainer') this.store.setCurrentRealm(this.get('realm')) let node = document.querySelector(this.get('containerQuery')) this.setupScroll(node) this.setupFullscreen() let scrollTop = this.store.get('scrollTop') if (scrollTop > 0) { this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => { console.log('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight) if (!this.get('initializedScrollTop') && allVisibleItemsHaveHeight && node) { this.set({'initializedScrollTop': true}) mark('set scrollTop') console.log('forcing scroll top to ', scrollTop) node.scrollTop = scrollTop stop('set scrollTop') } }) } else { this.store.setForRealm({ scrollHeight: node.scrollHeight, offsetHeight: node.offsetHeight }) } stop('onCreate VirtualListContainer') }, ondestroy() { this.teardownScroll() this.teardownFullscreen() this.store.setCurrentRealm(null) }, store: () => virtualListStore, methods: { setupScroll(node) { if (!node) { return } this.scrollListener = throttle(event => { if (this.get('fullscreen')) { return } this.onScroll(event) }, SCROLL_EVENT_DELAY, { leading: true, trailing: true }) node.addEventListener('scroll', this.scrollListener) }, teardownScroll() { let node = document.querySelector(this.get('containerQuery')) if (node) { node.removeEventListener('scroll', this.scrollListener) } }, setupFullscreen() { this.onFullscreenChange = this.onFullscreenChange.bind(this) attachFullscreenListener(this.onFullscreenChange) }, teardownFullscreen() { detachFullscreenListener(this.onFullscreenChange) }, onScroll(event) { let { scrollTop, scrollHeight } = event.target // On mobile devices, this can make scrolling more responsive. On // desktop browsers... it's probably overkill, and can lead to a // checkerboarding issue ("I just scrolled, why is it blank for 5 seconds?"). let runTask = isMobile() ? scheduleIdleTask : requestAnimationFrame runTask(() => { mark('onScroll -> setForRealm()') this.store.setForRealm({scrollTop, scrollHeight}) stop('onScroll -> setForRealm()') }) }, onFullscreenChange() { mark('onFullscreenChange') console.log('is fullscreen? ', isFullscreen()) this.set({ fullscreen: isFullscreen() }) stop('onFullscreenChange') } }, computed: { // TODO: bug in svelte/store – the observer in oncreate() never get removed without this hack allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight } }; </script>