This repository has been archived by the owner on Apr 27, 2019. It is now read-only.
/
single.js
97 lines (75 loc) · 2.04 KB
/
single.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
89
90
91
92
93
94
95
96
97
var NO_TRANSACTION = {}
var Observ = require('@mmckegg/mutant/value')
var Event = require('geval')
var resolveNode = require('./resolve')
module.exports = ObservNode
function ObservNode(context){
// context: nodes, nodeKey
var obs = Observ()
obs.node = null
var lastDescriptor = null
var currentTransaction = NO_TRANSACTION
var removeListener = null
var broadcastNode = null
obs.onNode = Event(function(broadcast){
broadcastNode = broadcast
})
obs(function(descriptor){
if (currentTransaction === NO_TRANSACTION){
currentTransaction = descriptor
updateNode(descriptor)
currentTransaction = NO_TRANSACTION
}
lastDescriptor = descriptor
})
obs.destroy = function () {
if (obs.node) {
removeListener&&removeListener()
if (obs.node.destroy){
obs.node.destroy()
}
obs.node = removeListener = null
}
}
return obs
// scoped
function updateNode(descriptor){
var nodeName = getNode(descriptor)
var ctor = descriptor && resolveNode(context.nodes, nodeName)
if (obs.node && nodeName === getNode(lastDescriptor)){
obs.node.set(descriptor)
} else {
var lastNode = obs.node
if (obs.node){
removeListener&&removeListener()
if (obs.node.destroy){
obs.node.destroy()
}
obs.node = removeListener = null
}
if (descriptor){
if (typeof ctor === 'function'){
obs.node = ctor(context)
obs.node.nodeName = nodeName
obs.node.set(descriptor)
removeListener = obs.node(onUpdate)
}
}
broadcastNode(obs.node)
}
}
function onUpdate(){
if (currentTransaction === NO_TRANSACTION){
var descriptor = obs.node()
currentTransaction = descriptor
if (getNode(descriptor) !== getNode(lastDescriptor)){
updateNode(descriptor)
}
obs.set(descriptor)
currentTransaction = NO_TRANSACTION
}
}
function getNode(value){
return value && value[context.nodeKey||'node'] || null
}
}