| 
									
										
										
										
											2018-01-23 21:08:56 -08:00
										 |  |  |  | <div class="container" | 
					
						
							|  |  |  |  |      on:scroll="onScroll(event)" | 
					
						
							|  |  |  |  |      on:fullscreen="onFullscreenChange()" | 
					
						
							|  |  |  |  |      ref:node> | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  |   <slot></slot> | 
					
						
							|  |  |  |  | </div> | 
					
						
							|  |  |  |  | <script> | 
					
						
							| 
									
										
										
										
											2018-01-25 08:23:14 -08:00
										 |  |  |  |   import { virtualListStore } from './virtualListStore' | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   import throttle from 'lodash/throttle' | 
					
						
							| 
									
										
										
										
											2018-01-25 08:23:14 -08:00
										 |  |  |  |   import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen' | 
					
						
							|  |  |  |  |   import { mark, stop } from '../../_utils/marks' | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   const SCROLL_EVENT_DELAY = 300 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 09:47:31 -08:00
										 |  |  |  |   const cachedVirtualStores = {} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   if (process.browser && process.env.NODE_ENV !== 'production') { | 
					
						
							|  |  |  |  |     window.cachedVirtualStores = cachedVirtualStores | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  |   export default { | 
					
						
							|  |  |  |  |     oncreate() { | 
					
						
							|  |  |  |  |       mark('onCreate VirtualListContainer') | 
					
						
							|  |  |  |  |       let node = this.refs.node | 
					
						
							| 
									
										
										
										
											2018-01-24 09:47:31 -08:00
										 |  |  |  |       let storeKey = this.get('storeKey') | 
					
						
							|  |  |  |  |       let cachedStore | 
					
						
							|  |  |  |  |       if (storeKey && (cachedStore = cachedVirtualStores[storeKey])) { | 
					
						
							|  |  |  |  |         this.store.set({ | 
					
						
							|  |  |  |  |           scrollTop: cachedStore.state.scrollTop, | 
					
						
							|  |  |  |  |           scrollHeight: cachedStore.state.scrollHeight, | 
					
						
							|  |  |  |  |           offsetHeight: cachedStore.state.offsetHeight | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |         this.store.set(cachedStore.state) | 
					
						
							| 
									
										
										
										
											2018-01-24 18:58:10 -08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         // rehydrate scroll top | 
					
						
							|  |  |  |  |         let cachedScrollTop = cachedStore.state.scrollTop || 0 | 
					
						
							|  |  |  |  |         if (cachedScrollTop === 0) { | 
					
						
							|  |  |  |  |           if (process.env.NODE_ENV !== 'production') { | 
					
						
							|  |  |  |  |             console.log('no need to force scroll top') | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |           return | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |         let initializedScrollTop = false | 
					
						
							|  |  |  |  |         let node = this.refs.node | 
					
						
							|  |  |  |  |         this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => { | 
					
						
							|  |  |  |  |           if (process.env.NODE_ENV !== 'production') { | 
					
						
							|  |  |  |  |             console.log('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight) | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |           if (!initializedScrollTop && allVisibleItemsHaveHeight && node) { | 
					
						
							|  |  |  |  |             initializedScrollTop = true | 
					
						
							|  |  |  |  |             requestAnimationFrame(() => { | 
					
						
							|  |  |  |  |               mark('set scrollTop') | 
					
						
							|  |  |  |  |               if (process.env.NODE_ENV !== 'production') { | 
					
						
							|  |  |  |  |                 console.log('forcing scroll top to ', cachedScrollTop) | 
					
						
							|  |  |  |  |               } | 
					
						
							|  |  |  |  |               node.scrollTop = cachedScrollTop | 
					
						
							|  |  |  |  |               stop('set scrollTop') | 
					
						
							|  |  |  |  |             }) | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2018-01-24 09:47:31 -08:00
										 |  |  |  |       } else { | 
					
						
							|  |  |  |  |         this.store.set({ | 
					
						
							|  |  |  |  |           scrollTop: 0, | 
					
						
							|  |  |  |  |           scrollHeight: node.scrollHeight, | 
					
						
							|  |  |  |  |           offsetHeight: node.offsetHeight | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  |       stop('onCreate VirtualListContainer') | 
					
						
							|  |  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2018-01-24 09:47:31 -08:00
										 |  |  |  |     ondestroy() { | 
					
						
							|  |  |  |  |       let storeKey = this.get('storeKey') | 
					
						
							|  |  |  |  |       if (storeKey) { | 
					
						
							| 
									
										
										
										
											2018-01-24 18:04:25 -08:00
										 |  |  |  |         let clonedState = this.store.cloneState() | 
					
						
							|  |  |  |  |         if (process.env.NODE_ENV !== 'production') { | 
					
						
							|  |  |  |  |           console.log('caching scroll top', clonedState.scrollTop) | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-24 09:47:31 -08:00
										 |  |  |  |         cachedVirtualStores[storeKey] = { | 
					
						
							| 
									
										
										
										
											2018-01-24 18:04:25 -08:00
										 |  |  |  |           state: clonedState | 
					
						
							| 
									
										
										
										
											2018-01-24 09:47:31 -08:00
										 |  |  |  |         } | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  |     store: () => virtualListStore, | 
					
						
							|  |  |  |  |     events: { | 
					
						
							|  |  |  |  |       scroll(node, callback) { | 
					
						
							|  |  |  |  |         const onScroll = throttle(event => { | 
					
						
							|  |  |  |  |           mark('onScroll') | 
					
						
							|  |  |  |  |           if (this.get('fullscreen')) { | 
					
						
							|  |  |  |  |             return | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |           callback(event) | 
					
						
							|  |  |  |  |           stop('onScroll') | 
					
						
							|  |  |  |  |         }, SCROLL_EVENT_DELAY, { | 
					
						
							|  |  |  |  |           leading: true, | 
					
						
							|  |  |  |  |           trailing: true | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |         node.addEventListener('scroll', onScroll) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         return { | 
					
						
							|  |  |  |  |           teardown() { | 
					
						
							|  |  |  |  |             node.removeEventListener('scroll', onScroll) | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       }, | 
					
						
							|  |  |  |  |       fullscreen(node, callback) { | 
					
						
							|  |  |  |  |         const onFullscreen = (() => { | 
					
						
							|  |  |  |  |           callback() | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |         attachFullscreenListener(onFullscreen) | 
					
						
							|  |  |  |  |         return { | 
					
						
							|  |  |  |  |           teardown() { | 
					
						
							|  |  |  |  |             detachFullscreenListener(onFullscreen) | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |       } | 
					
						
							|  |  |  |  |     }, | 
					
						
							|  |  |  |  |     methods: { | 
					
						
							|  |  |  |  |       onScroll(event) { | 
					
						
							|  |  |  |  |         this.store.set({ | 
					
						
							|  |  |  |  |           scrollTop: event.target.scrollTop, | 
					
						
							|  |  |  |  |           scrollHeight: event.target.scrollHeight | 
					
						
							|  |  |  |  |         }) | 
					
						
							|  |  |  |  |       }, | 
					
						
							|  |  |  |  |       onFullscreenChange() { | 
					
						
							|  |  |  |  |         mark('onFullscreenChange') | 
					
						
							| 
									
										
										
										
											2018-01-24 18:04:25 -08:00
										 |  |  |  |         if (process.env.NODE_ENV !== 'production') { | 
					
						
							|  |  |  |  |           console.log('is fullscreen? ', isFullscreen()) | 
					
						
							|  |  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  |         this.set({ fullscreen: isFullscreen() }) | 
					
						
							|  |  |  |  |         stop('onFullscreenChange') | 
					
						
							|  |  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-01-24 18:58:10 -08:00
										 |  |  |  |     }, | 
					
						
							|  |  |  |  |     computed: { | 
					
						
							|  |  |  |  |       // TODO: bug in svelte/store – the observer in oncreate() never get removed without this hack | 
					
						
							|  |  |  |  |       allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight | 
					
						
							| 
									
										
										
										
											2018-01-22 21:30:14 -08:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |   }; | 
					
						
							|  |  |  |  | </script> |