git ssb

1+

Matt McKegg / mutant



Tree: 536c388f797d23a553f63806d14459218037fd1a

Files: 536c388f797d23a553f63806d14459218037fd1a / lib / apply-properties.js

3450 bytesRaw
1var isObservable = require('../is-observable')
2var Set = require('../set')
3var watch = require('../watch')
4var caches = new global.WeakMap()
5
6module.exports = applyProperties
7
8function applyProperties (target, properties, namespace) {
9 var data = caches.get(target)
10 if (!data) {
11 data = { releases: [] }
12 caches.set(target, data)
13 }
14
15 var classList = Set()
16 if (target.className) {
17 classList.add(target.className)
18 }
19
20 for (var key in properties) {
21 var valueOrObs = properties[key]
22 var value = resolve(valueOrObs)
23
24 if (key === 'style') {
25 // TODO: handle observable at root for style objects
26 for (var k in value) {
27 var styleValue = resolve(value[k])
28 var styleObs = isObservable(value[k]) ? value[k] : null
29 target.style.setProperty(k, styleValue)
30
31 if (styleObs) {
32 data.releases.push(bindStyle(target, styleObs, k))
33 }
34 }
35 } else if (key === 'attributes') {
36 for (var k in value) {
37 var attrValue = resolve(value[k])
38 var attrObs = isObservable(value[k]) ? value[k] : null
39
40 if (namespace) {
41 target.setAttributeNS(namespace, k, attrValue)
42 } else {
43 target.setAttribute(k, attrValue)
44 }
45
46 if (attrObs) {
47 data.releases.push(bindAttr(target, attrObs, k, namespace))
48 }
49 }
50 } else if (key === 'events') {
51 for (var name in value) {
52 target.addEventListener(name, value[name], true)
53 }
54 } else if (key.slice(0, 3) === 'ev-') {
55 target.addEventListener(key.slice(3), value, true)
56 } else if (key === 'className' || key === 'classList') {
57 if (Array.isArray(valueOrObs)) {
58 valueOrObs.forEach(function (v) {
59 classList.add(v)
60 })
61 } else {
62 classList.add(valueOrObs)
63 }
64 } else {
65 target[key] = value
66 var obs = isObservable(valueOrObs) ? valueOrObs : null
67 if (obs) {
68 data.releases.push(bind(target, obs, key))
69 }
70 }
71 }
72
73 watch(classList, function (value) {
74 value = [].concat.apply([], value).filter(present).join(' ')
75 if (value || target.className) {
76 target.className = value
77 }
78 })
79}
80
81applyProperties.destroy = function (target) {
82 var data = caches.get(target)
83 if (data) {
84 while (data.releases.length) {
85 data.releases.pop()()
86 }
87 caches.delete(target)
88 }
89}
90
91function bindStyle (target, styleObs, key) {
92 return styleObs(function (value) {
93 target.style.setProperty(key, value)
94 })
95}
96
97function bindAttr (target, attrObs, key, namespace) {
98 return attrObs(function (value) {
99 if (value == null) {
100 if (namespace) {
101 target.removeAttributeNS(namespace, key)
102 } else {
103 target.removeAttribute(key)
104 }
105 } else {
106 if (namespace) {
107 target.setAttributeNS(namespace, key, value)
108 } else {
109 target.setAttribute(key, value)
110 }
111 }
112 })
113}
114
115function bind (target, obs, key, namespace) {
116 return obs(function (toValue) {
117 var fromValue = namespace
118 ? target.getAttributeNS(namespace, key)
119 : target.getAttribute(key)
120
121 if (fromValue !== toValue) {
122 if (namespace) {
123 target.setAttributeNS(namespace, key, toValue)
124 } else {
125 target.setAttribute(key, toValue)
126 }
127 }
128 })
129}
130
131function present (val) {
132 return val != null
133}
134
135function resolve (source) {
136 return typeof source === 'function' ? source() : source
137}
138

Built with git-ssb-web