git ssb

1+

Matt McKegg / mutant



Tree: e75defac47630de9da141ca0ca89cba54a030464

Files: e75defac47630de9da141ca0ca89cba54a030464 / lib / apply-properties.js

3444 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(value)) {
58 value.forEach(function (v) {
59 classList.add(v)
60 })
61 } else {
62 classList.add(valueOrObs)
63 }
64 } else {
65 target[key] = value
66 }
67
68 var obs = isObservable(valueOrObs) ? valueOrObs : null
69 if (obs) {
70 data.releases.push(bind(target, obs, key, namespace))
71 }
72 }
73
74 watch(classList, function (value) {
75 value = [].concat.apply([], value).filter(present).join(' ')
76 if (value || target.className) {
77 target.className = value
78 }
79 })
80}
81
82applyProperties.destroy = function (target) {
83 var data = caches.get(target)
84 if (data) {
85 while (data.releases.length) {
86 data.releases.pop()()
87 }
88 caches.delete(target)
89 }
90}
91
92function bindStyle (target, styleObs, key) {
93 return styleObs(function (value) {
94 target.style.setProperty(key, value)
95 })
96}
97
98function bindAttr (target, attrObs, key, namespace) {
99 return attrObs(function (value) {
100 if (value == null) {
101 if (namespace) {
102 target.removeAttributeNS(namespace, key)
103 } else {
104 target.removeAttribute(key)
105 }
106 } else {
107 if (namespace) {
108 target.setAttributeNS(namespace, key, value)
109 } else {
110 target.setAttribute(key, value)
111 }
112 }
113 })
114}
115
116function bind (target, obs, key, namespace) {
117 return obs(function (toValue) {
118 var fromValue = namespace
119 ? target.getAttributeNS(namespace, key)
120 : target.getAttribute(key)
121
122 if (fromValue !== toValue) {
123 if (namespace) {
124 target.setAttributeNS(namespace, key, toValue)
125 } else {
126 target.setAttribute(key, toValue)
127 }
128 }
129 })
130}
131
132function present (val) {
133 return val != null
134}
135
136function resolve (source) {
137 return typeof source === 'function' ? source() : source
138}
139

Built with git-ssb-web