refactor VirtualList to be more self-contained

This commit is contained in:
Nolan Lawson 2018-02-12 22:06:05 -08:00
parent 24e8bdbd86
commit acc1ce396d
12 changed files with 65 additions and 77 deletions

View file

@ -1,19 +1,11 @@
<:Window bind:online /> <:Window bind:online />
<Nav :page /> <Nav :page />
{{#if virtual}} <div class="container">
<VirtualListContainer realm="{{$currentInstance + '/' + virtualRealm}}"> <main>
<main> <slot></slot>
<slot></slot> </main>
</main> </div>
</VirtualListContainer>
{{else}}
<div class="container">
<main>
<slot></slot>
</main>
</div>
{{/if}}
<script> <script>
import Nav from './Nav.html'; import Nav from './Nav.html';
import VirtualListContainer from './virtualList/VirtualListContainer.html' import VirtualListContainer from './virtualList/VirtualListContainer.html'

View file

@ -43,7 +43,7 @@
this.store.setForRealm({intersectionStates: intersectionStates}) this.store.setForRealm({intersectionStates: intersectionStates})
this.set({intersectionObserver: new IntersectionObserver(this.onIntersection.bind(this), { this.set({intersectionObserver: new IntersectionObserver(this.onIntersection.bind(this), {
root: document.getElementsByClassName('container')[0], // TODO: fix this root: document.querySelector('.container'),
rootMargin: '300% 0px' rootMargin: '300% 0px'
})}) })})
this.observe('allItemsHaveHeight', allItemsHaveHeight => { this.observe('allItemsHaveHeight', allItemsHaveHeight => {
@ -80,8 +80,7 @@
} }
this.set({scrolledToPosition: true}) this.set({scrolledToPosition: true})
console.log('scrollToPosition', rect.top) console.log('scrollToPosition', rect.top)
// TODO: there should be some cleaner way to grab the container element let container = document.querySelector('.container')
let container = document.getElementsByClassName('container')[0]
if (!container) { if (!container) {
return return
} }

View file

@ -1,19 +1,21 @@
<div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;"> <VirtualListContainer :realm >
<VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/> <div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;">
{{#if $visibleItems}} <VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/>
{{#each $visibleItems as visibleItem @key}} {{#if $visibleItems}}
<VirtualListLazyItem :component {{#each $visibleItems as visibleItem @key}}
offset="{{visibleItem.offset}}" <VirtualListLazyItem :component
makeProps="{{makeProps}}" offset="{{visibleItem.offset}}"
key="{{visibleItem.key}}" makeProps="{{makeProps}}"
index="{{visibleItem.index}}" key="{{visibleItem.key}}"
/> index="{{visibleItem.index}}"
{{/each}} />
{{/if}} {{/each}}
{{#if $showFooter}} {{/if}}
<VirtualListFooter component="{{footerComponent}}"/> {{#if $showFooter}}
{{/if}} <VirtualListFooter component="{{footerComponent}}" />
</div> {{/if}}
</div>
</VirtualListContainer>
<style> <style>
.virtual-list { .virtual-list {
position: relative; position: relative;
@ -21,6 +23,7 @@
} }
</style> </style>
<script> <script>
import VirtualListContainer from './VirtualListContainer.html'
import VirtualListLazyItem from './VirtualListLazyItem' import VirtualListLazyItem from './VirtualListLazyItem'
import VirtualListFooter from './VirtualListFooter.html' import VirtualListFooter from './VirtualListFooter.html'
import VirtualListHeader from './VirtualListHeader.html' import VirtualListHeader from './VirtualListHeader.html'
@ -86,6 +89,7 @@
}), }),
store: () => virtualListStore, store: () => virtualListStore,
components: { components: {
VirtualListContainer,
VirtualListLazyItem, VirtualListLazyItem,
VirtualListFooter, VirtualListFooter,
VirtualListHeader VirtualListHeader

View file

@ -1,12 +1,6 @@
<div class="container" <slot></slot>
on:scroll="onScroll(event)"
on:fullscreen="onFullscreenChange()"
ref:node>
<slot></slot>
</div>
<script> <script>
import { virtualListStore } from './virtualListStore' import { virtualListStore } from './virtualListStore'
import throttle from 'lodash/throttle' import throttle from 'lodash/throttle'
import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen' import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen'
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
@ -16,7 +10,9 @@
export default { export default {
oncreate() { oncreate() {
mark('onCreate VirtualListContainer') mark('onCreate VirtualListContainer')
let node = this.refs.node let node = document.querySelector('.container')
this.setupScroll(node)
this.setupFullscreen()
this.store.setCurrentRealm(this.get('realm')) this.store.setCurrentRealm(this.get('realm'))
let scrollTop = this.store.get('scrollTop') let scrollTop = this.store.get('scrollTop')
if (scrollTop > 0) { if (scrollTop > 0) {
@ -40,46 +36,47 @@
} }
stop('onCreate VirtualListContainer') stop('onCreate VirtualListContainer')
}, },
ondestroy() {
this.teardownScroll()
this.teardownFullscreen()
},
store: () => virtualListStore, store: () => virtualListStore,
events: { methods: {
scroll(node, callback) { setupScroll(node) {
const onScroll = throttle(event => { if (!node) {
mark('onScroll') return
}
this.scrollListener = throttle(event => {
if (this.get('fullscreen')) { if (this.get('fullscreen')) {
return return
} }
callback(event) this.onScroll(event)
stop('onScroll')
}, SCROLL_EVENT_DELAY, { }, SCROLL_EVENT_DELAY, {
leading: true, leading: true,
trailing: true trailing: true
}) })
node.addEventListener('scroll', onScroll) node.addEventListener('scroll', this.scrollListener)
},
return { teardownScroll() {
teardown() { let node = document.querySelector('.container')
node.removeEventListener('scroll', onScroll) if (node) {
} node.removeEventListener('scroll', this.scrollListener)
} }
}, },
fullscreen(node, callback) { setupFullscreen() {
const onFullscreen = (() => { this.onFullscreenChange = this.onFullscreenChange.bind(this)
callback() attachFullscreenListener(this.onFullscreenChange)
}) },
attachFullscreenListener(onFullscreen) teardownFullscreen() {
return { detachFullscreenListener(this.onFullscreenChange)
teardown() { },
detachFullscreenListener(onFullscreen)
}
}
}
},
methods: {
onScroll(event) { onScroll(event) {
mark('onScroll')
this.store.setForRealm({ this.store.setForRealm({
scrollTop: event.target.scrollTop, scrollTop: event.target.scrollTop,
scrollHeight: event.target.scrollHeight scrollHeight: event.target.scrollHeight
}) })
stop('onScroll')
}, },
onFullscreenChange() { onFullscreenChange() {
mark('onFullscreenChange') mark('onFullscreenChange')

View file

@ -2,9 +2,7 @@
<title>Pinafore {{profileName}}</title> <title>Pinafore {{profileName}}</title>
</:Head> </:Head>
<Layout page='tags' <Layout page='tags'>
virtual="true"
virtualRealm='account/{{params.accountId}}' >
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
<DynamicPageBanner title="{{profileName}}" /> <DynamicPageBanner title="{{profileName}}" />
{{#if $currentAccountProfile}} {{#if $currentAccountProfile}}

View file

@ -2,7 +2,7 @@
<title>Pinafore Favorites</title> <title>Pinafore Favorites</title>
</:Head> </:Head>
<Layout page='favorites' virtual="true" virtualRealm="favorites"> <Layout page='favorites'>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
{{#if $pinnedPage !== '/favorites'}} {{#if $pinnedPage !== '/favorites'}}
<DynamicPageBanner title="Favorites" icon="#fa-star"/> <DynamicPageBanner title="Favorites" icon="#fa-star"/>

View file

@ -2,7 +2,7 @@
<title>Pinafore Federated</title> <title>Pinafore Federated</title>
</:Head> </:Head>
<Layout page='federated' virtual="true" virtualRealm="federated"> <Layout page='federated'>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
{{#if $pinnedPage !== '/federated'}} {{#if $pinnedPage !== '/federated'}}
<DynamicPageBanner title="Federated Timeline" icon="#fa-globe"/> <DynamicPageBanner title="Federated Timeline" icon="#fa-globe"/>

View file

@ -2,7 +2,7 @@
<title>Pinafore Home</title> <title>Pinafore Home</title>
</:Head> </:Head>
<Layout page='home' virtual="true" virtualRealm="home"> <Layout page='home'>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
<LazyTimeline timeline='home' /> <LazyTimeline timeline='home' />
{{else}} {{else}}

View file

@ -2,7 +2,7 @@
<title>Pinafore {{listTitle}}</title> <title>Pinafore {{listTitle}}</title>
</:Head> </:Head>
<Layout page='lists' virtual="true" virtualRealm="list/{{params.listId}}"> <Layout page='lists'>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
{{#if $pinnedPage !== `/lists/${params.listId}`}} {{#if $pinnedPage !== `/lists/${params.listId}`}}
<DynamicPageBanner title="{{listTitle}}" icon="#fa-bars"/> <DynamicPageBanner title="{{listTitle}}" icon="#fa-bars"/>

View file

@ -2,7 +2,7 @@
<title>Pinafore Local</title> <title>Pinafore Local</title>
</:Head> </:Head>
<Layout page='local' virtual="true" virtualRealm="local"> <Layout page='local'>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
{{#if $pinnedPage !== '/local'}} {{#if $pinnedPage !== '/local'}}
<DynamicPageBanner title="Local Timeline" icon="#fa-users"/> <DynamicPageBanner title="Local Timeline" icon="#fa-users"/>

View file

@ -2,7 +2,7 @@
<title>Pinafore Notifications</title> <title>Pinafore Notifications</title>
</:Head> </:Head>
<Layout page='notifications' virtual="true" virtualRealm="notifications"> <Layout page='notifications'>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
<LazyTimeline timeline='notifications' /> <LazyTimeline timeline='notifications' />
{{else}} {{else}}

View file

@ -2,9 +2,7 @@
<title>Pinafore #{{params.tagName}}</title> <title>Pinafore #{{params.tagName}}</title>
</:Head> </:Head>
<Layout page='tags' <Layout page='tags'>
virtual="true"
virtualRealm='tag/{{params.tagName}}' >
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
<DynamicPageBanner title="{{'#' + params.tagName}}"/> <DynamicPageBanner title="{{'#' + params.tagName}}"/>
<LazyTimeline timeline='tag/{{params.tagName}}' /> <LazyTimeline timeline='tag/{{params.tagName}}' />