|
// scaffolded with content state fetch |
|
|
|
var Nanocomponent = require('nanocomponent') |
|
var html = require('nanohtml') |
|
var onIntersect = require('on-intersect') |
|
|
|
module.exports = class LazyComponent extends Nanocomponent { |
|
constructor (id, state, emit) { |
|
super(id) |
|
this.state = state || {components:{}} |
|
this.local = this.state.components[id] = { |
|
view: 'placeholder', |
|
visible: false, |
|
url: undefined |
|
} |
|
|
|
this.onEnter = this.onEnter.bind(this) |
|
this.onLeave = this.onLeave.bind(this) |
|
} |
|
|
|
load (element) { |
|
this.stopObserving = onIntersect(element, this.onEnter, this.onLeave) |
|
} |
|
|
|
unload () { |
|
if (this.stopObserving) this.stopObserving() |
|
} |
|
|
|
onEnter () { |
|
console.log('enter') |
|
this.local.visible = true |
|
if (this.local.view !== 'loaded') { |
|
this.fetchData() |
|
} |
|
} |
|
|
|
onLeave () { |
|
console.log('exit') |
|
this.local.visible = false |
|
} |
|
|
|
fetchData () { |
|
console.log('fetch data') |
|
var p = this.state.content[this.local.url] |
|
|
|
if (p) { |
|
console.log('loaded') |
|
this.local.view = 'loaded' |
|
if (this && this.element) this.rerender() |
|
} else { |
|
console.log('loading') |
|
this.local.view = 'loading' |
|
if (this && this.element) this.rerender() |
|
|
|
// fetch into content state |
|
this.contentStateFetch() |
|
} |
|
} |
|
|
|
contentStateFetch () { |
|
fetch(this.state.constants.API + this.local.url) |
|
.then(response => response.json()) |
|
.then(json => { |
|
Object.keys(json).forEach(key => { |
|
var p = this.state.content[key] |
|
if (!p || (p && !p._loaded)) { |
|
this.state.content[key] = json[key] |
|
} |
|
}) |
|
|
|
console.log('loaded') |
|
this.local.view = 'loaded' |
|
if (this && this.element) this.rerender() |
|
}) |
|
} |
|
|
|
onLoaded () { |
|
this.init() |
|
} |
|
|
|
init () { |
|
console.log('do init stuff') |
|
} |
|
|
|
destroy () { |
|
console.log('do teardown stuff') |
|
} |
|
|
|
afterupdate () { |
|
console.log(this.local) |
|
if (this.local.view === 'loaded') { |
|
this.onLoaded() |
|
} |
|
} |
|
|
|
viewPlaceholder () { |
|
return html`<div>Not yet in view</div>` |
|
} |
|
|
|
viewLoading () { |
|
return html`<div>Loading data</div>` |
|
} |
|
|
|
viewError () { |
|
return html`<div>Error loading data</div>` |
|
} |
|
|
|
viewLoaded () { |
|
return html`<div>Loaded</div>` |
|
} |
|
|
|
createElement (props = {}) { |
|
Object.assign(this.local, props) |
|
|
|
return this.local.view === 'loaded' |
|
? this.viewLoaded() |
|
: this.local.view === 'loading' |
|
? this.viewLoading() |
|
: this.local.view === 'error' |
|
? this.viewError() |
|
: this.viewPlaceholder() |
|
} |
|
|
|
update (props = {}) { |
|
if (props.url !== this.local.url) { |
|
this.local.view = 'placeholder' |
|
this.destroy() |
|
Object.assign(this.local, props) |
|
return true |
|
} |
|
} |
|
} |