-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
88 lines (77 loc) · 2.43 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
const onload = require('on-load')
const morph = require('nanomorph')
const util = require('@nx-js/observer-util')
const events = require('events')
const { observable, observe, unobserve, isObservable } = util
const KEY_ATTR = 'data-' + onload.KEY_ID
let id = 1
function morphable (view, opts={}) {
if (typeof view !== 'function') return observable(view)
let { reactiveView=true, observeListeners=false } = opts || {}
let cache = new WeakMap()
let reactions = new WeakMap()
let int = 0
const fn = function () {
let self = this
let args = Array.from(arguments)
let index = isObservable(self) ? self : args[0]
let rawArgs = args.map(state => morphable.raw(state))
let rawSelf = isObservable(self) ? morphable.raw(self) : self
let listenerArgs = observeListeners ? args : rawArgs
let listenerSelf = observeListeners ? self : rawSelf
let element
if (cache.has(index)) {
element = cache.get(index)
} else {
element = view.apply(rawSelf, rawArgs)
if (!element.id) {
if (fn.id) {
if (int == 0) {
element.id = fn.id
int++
} else {
element.id = `${fn.id}-${int++}`
}
} else {
element.id = id++
}
}
}
return onload(element, function (el) {
if (isObservable(index)) {
if (reactions.has(index)) return
cache.set(index, el)
}
let init = false
let old_id = el.id
let reaction = observe(() => {
if (!init || reactiveView) {
fn.emit('premorph', el, ...listenerArgs, listenerSelf)
let update = view.apply(self, args)
update.id = update.id || old_id
update.setAttribute(KEY_ATTR, (cache.get(index) || el).getAttribute(KEY_ATTR))
morph(el, update)
}
if (init) {
fn.emit('morph', el, ...listenerArgs, listenerSelf)
} else {
fn.emit('load', el, ...listenerArgs, listenerSelf)
init = true
}
})
if (isObservable(index)) {
reactions.set(index, reaction)
}
}, el => {
if (document.documentElement.contains(el) || !reactions.has(index)) return
fn.emit('unload', el, ...listenerArgs, listenerSelf)
unobserve(reactions.get(index))
reactions.delete(index)
}, id)
}
events.call(fn)
Object.assign(fn, events.prototype)
return fn
}
Object.assign(morphable, util)
module.exports = morphable