binders.coffee
5.58 KB
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# Core binders that are included with Rivets.js.
Rivets.binders.enabled = (el, value) ->
el.disabled = !value
Rivets.binders.disabled = (el, value) ->
el.disabled = !!value
Rivets.binders.checked =
publishes: true
bind: (el) ->
Rivets.Util.bindEvent el, 'change', @publish
unbind: (el) ->
Rivets.Util.unbindEvent el, 'change', @publish
routine: (el, value) ->
if el.type is 'radio'
el.checked = el.value?.toString() is value?.toString()
else
el.checked = !!value
Rivets.binders.unchecked =
publishes: true
bind: (el) ->
Rivets.Util.bindEvent el, 'change', @publish
unbind: (el) ->
Rivets.Util.unbindEvent el, 'change', @publish
routine: (el, value) ->
if el.type is 'radio'
el.checked = el.value?.toString() isnt value?.toString()
else
el.checked = !value
Rivets.binders.show = (el, value) ->
el.style.display = if value then '' else 'none'
Rivets.binders.hide = (el, value) ->
el.style.display = if value then 'none' else ''
Rivets.binders.html = (el, value) ->
el.innerHTML = if value? then value else ''
Rivets.binders.value =
publishes: true
bind: (el) ->
Rivets.Util.bindEvent el, 'change', @publish
unbind: (el) ->
Rivets.Util.unbindEvent el, 'change', @publish
routine: (el, value) ->
if window.jQuery?
el = jQuery el
if value?.toString() isnt el.val()?.toString()
el.val if value? then value else ''
else
if el.type is 'select-multiple'
o.selected = o.value in value for o in el if value?
else if value?.toString() isnt el.value?.toString()
el.value = if value? then value else ''
Rivets.binders.text = (el, value) ->
if el.innerText?
el.innerText = if value? then value else ''
else
el.textContent = if value? then value else ''
Rivets.binders.if =
block: true
bind: (el) ->
unless @marker?
attr = [@view.config.prefix, @type].join('-').replace '--', '-'
declaration = el.getAttribute attr
@marker = document.createComment " rivets: #{@type} #{declaration} "
el.removeAttribute attr
el.parentNode.insertBefore @marker, el
el.parentNode.removeChild el
unbind: ->
@nested?.unbind()
routine: (el, value) ->
if !!value is not @nested?
if value
models = {}
models[key] = model for key, model of @view.models
options =
binders: @view.options.binders
formatters: @view.options.formatters
adapters: @view.options.adapters
config: @view.options.config
(@nested = new Rivets.View(el, models, options)).bind()
@marker.parentNode.insertBefore el, @marker.nextSibling
else
el.parentNode.removeChild el
@nested.unbind()
delete @nested
update: (models) ->
@nested?.update models
Rivets.binders.unless =
block: true
bind: (el) ->
Rivets.binders.if.bind.call @, el
unbind: ->
Rivets.binders.if.unbind.call @
routine: (el, value) ->
Rivets.binders.if.routine.call @, el, not value
update: (models) ->
Rivets.binders.if.update.call @, models
Rivets.binders['on-*'] =
function: true
unbind: (el) ->
Rivets.Util.unbindEvent el, @args[0], @handler if @handler
routine: (el, value) ->
Rivets.Util.unbindEvent el, @args[0], @handler if @handler
Rivets.Util.bindEvent el, @args[0], @handler = @eventHandler value
Rivets.binders['each-*'] =
block: true
bind: (el) ->
unless @marker?
attr = [@view.config.prefix, @type].join('-').replace '--', '-'
@marker = document.createComment " rivets: #{@type} "
@iterated = []
el.removeAttribute attr
el.parentNode.insertBefore @marker, el
el.parentNode.removeChild el
unbind: (el) ->
view.unbind() for view in @iterated if @iterated?
routine: (el, collection) ->
modelName = @args[0]
collection = collection or []
if @iterated.length > collection.length
for i in Array @iterated.length - collection.length
view = @iterated.pop()
view.unbind()
@marker.parentNode.removeChild view.els[0]
for model, index in collection
data = {}
data[modelName] = model
if not @iterated[index]?
for key, model of @view.models
data[key] ?= model
previous = if @iterated.length
@iterated[@iterated.length - 1].els[0]
else
@marker
options =
binders: @view.options.binders
formatters: @view.options.formatters
adapters: @view.options.adapters
config: {}
options.config[k] = v for k, v of @view.options.config
options.config.preloadData = true
template = el.cloneNode true
view = new Rivets.View(template, data, options)
view.bind()
@iterated.push view
@marker.parentNode.insertBefore template, previous.nextSibling
else if @iterated[index].models[modelName] isnt model
@iterated[index].update data
if el.nodeName is 'OPTION'
for binding in @view.bindings
if binding.el is @marker.parentNode and binding.type is 'value'
binding.sync()
update: (models) ->
data = {}
for key, model of models
data[key] = model unless key is @args[0]
view.update data for view in @iterated
Rivets.binders['class-*'] = (el, value) ->
elClass = " #{el.className} "
if !value is (elClass.indexOf(" #{@args[0]} ") isnt -1)
el.className = if value
"#{el.className} #{@args[0]}"
else
elClass.replace(" #{@args[0]} ", ' ').trim()
Rivets.binders['*'] = (el, value) ->
if value
el.setAttribute @type, value
else
el.removeAttribute @type