Update bindings and view parsing logic so that we're working with each individua…
…l section of a keypath (path + interface).
Showing
1 changed file
with
34 additions
and
27 deletions
... | @@ -23,7 +23,12 @@ class Rivets.Binding | ... | @@ -23,7 +23,12 @@ class Rivets.Binding |
23 | # All information about the binding is passed into the constructor; the | 23 | # All information about the binding is passed into the constructor; the |
24 | # containing view, the DOM node, the type of binding, the model object and the | 24 | # containing view, the DOM node, the type of binding, the model object and the |
25 | # keypath at which to listen for changes. | 25 | # keypath at which to listen for changes. |
26 | constructor: (@view, @el, @type, @key, @keypath, @options = {}) -> | 26 | constructor: (@view, @el, @type, @keypath, @options = {}) -> |
27 | @formatters = @options.formatters || [] | ||
28 | @setBinders() | ||
29 | @setModel() | ||
30 | |||
31 | setBinders: => | ||
27 | unless @binder = @view.binders[type] | 32 | unless @binder = @view.binders[type] |
28 | for identifier, value of @view.binders | 33 | for identifier, value of @view.binders |
29 | if identifier isnt '*' and identifier.indexOf('*') isnt -1 | 34 | if identifier isnt '*' and identifier.indexOf('*') isnt -1 |
... | @@ -35,8 +40,17 @@ class Rivets.Binding | ... | @@ -35,8 +40,17 @@ class Rivets.Binding |
35 | 40 | ||
36 | @binder or= @view.binders['*'] | 41 | @binder or= @view.binders['*'] |
37 | @binder = {routine: @binder} if @binder instanceof Function | 42 | @binder = {routine: @binder} if @binder instanceof Function |
38 | @formatters = @options.formatters || [] | 43 | |
39 | @model = if @key then @view.models[@key] else @view.models | 44 | setModel: => |
45 | interfaces = (k for k, v of @view.adapters) | ||
46 | tokens = Rivets.KeypathParser.parse @keypath, interfaces, '.' | ||
47 | |||
48 | @model = @view.models | ||
49 | @rootKey = tokens[0] | ||
50 | @key = tokens.pop() | ||
51 | |||
52 | for token, index in tokens | ||
53 | @model = @view.adapters[token.interface].read(@model, token.path) | ||
40 | 54 | ||
41 | # Applies all the current formatters to the supplied value and returns the | 55 | # Applies all the current formatters to the supplied value and returns the |
42 | # formatted value. | 56 | # formatted value. |
... | @@ -74,7 +88,7 @@ class Rivets.Binding | ... | @@ -74,7 +88,7 @@ class Rivets.Binding |
74 | 88 | ||
75 | # Syncs up the view binding with the model. | 89 | # Syncs up the view binding with the model. |
76 | sync: => | 90 | sync: => |
77 | @set @view.adapters['.'].read @model, @keypath | 91 | @set @view.adapters[@key.interface].read @model, @key.path |
78 | 92 | ||
79 | # Publishes the value currently set on the input element back to the model. | 93 | # Publishes the value currently set on the input element back to the model. |
80 | publish: => | 94 | publish: => |
... | @@ -87,14 +101,14 @@ class Rivets.Binding | ... | @@ -87,14 +101,14 @@ class Rivets.Binding |
87 | if @view.formatters[id]?.publish | 101 | if @view.formatters[id]?.publish |
88 | value = @view.formatters[id].publish value, args... | 102 | value = @view.formatters[id].publish value, args... |
89 | 103 | ||
90 | @view.adapters['.'].publish @model, @keypath, value | 104 | @view.adapters[@key.interface].publish @model, @key.path, value |
91 | 105 | ||
92 | # Subscribes to the model for changes at the specified keypath. Bi-directional | 106 | # Subscribes to the model for changes at the specified keypath. Bi-directional |
93 | # routines will also listen for changes on the element to propagate them back | 107 | # routines will also listen for changes on the element to propagate them back |
94 | # to the model. | 108 | # to the model. |
95 | bind: => | 109 | bind: => |
96 | @binder.bind?.call @, @el | 110 | @binder.bind?.call @, @el |
97 | @view.adapters['.'].subscribe @model, @keypath, @sync | 111 | @view.adapters[@key.interface].subscribe @model, @key.path, @sync |
98 | @sync() if @view.config.preloadData | 112 | @sync() if @view.config.preloadData |
99 | 113 | ||
100 | if @options.dependencies?.length | 114 | if @options.dependencies?.length |
... | @@ -112,7 +126,7 @@ class Rivets.Binding | ... | @@ -112,7 +126,7 @@ class Rivets.Binding |
112 | # Unsubscribes from the model and the element. | 126 | # Unsubscribes from the model and the element. |
113 | unbind: => | 127 | unbind: => |
114 | @binder.unbind?.call @, @el | 128 | @binder.unbind?.call @, @el |
115 | @view.adapters['.'].unsubscribe @model, @keypath, @sync | 129 | @view.adapters[@key.interface].unsubscribe @model, @key.path, @sync |
116 | 130 | ||
117 | if @options.dependencies?.length | 131 | if @options.dependencies?.length |
118 | for dependency in @options.dependencies | 132 | for dependency in @options.dependencies |
... | @@ -129,13 +143,10 @@ class Rivets.Binding | ... | @@ -129,13 +143,10 @@ class Rivets.Binding |
129 | # Updates the binding's model from what is currently set on the view. Unbinds | 143 | # Updates the binding's model from what is currently set on the view. Unbinds |
130 | # the old model first and then re-binds with the new model. | 144 | # the old model first and then re-binds with the new model. |
131 | update: (models = {}) => | 145 | update: (models = {}) => |
132 | if @key | 146 | if models[@rootKey.path] |
133 | if models[@key] | 147 | @view.adapters[@key.interface].unsubscribe @model, @key.path, @sync |
134 | @view.adapters['.'].unsubscribe @model, @keypath, @sync | 148 | @setModel() |
135 | @model = models[@key] | 149 | @view.adapters[@key.interface].subscribe @model, @key.path, @sync |
136 | @view.adapters['.'].subscribe @model, @keypath, @sync | ||
137 | @sync() if @view.config.preloadData | ||
138 | else | ||
139 | @sync() | 150 | @sync() |
140 | 151 | ||
141 | @binder.update?.call @, models | 152 | @binder.update?.call @, models |
... | @@ -199,9 +210,11 @@ class Rivets.ComponentBinding extends Rivets.Binding | ... | @@ -199,9 +210,11 @@ class Rivets.ComponentBinding extends Rivets.Binding |
199 | # differences while avoiding it being overwritten. | 210 | # differences while avoiding it being overwritten. |
200 | class Rivets.TextBinding extends Rivets.Binding | 211 | class Rivets.TextBinding extends Rivets.Binding |
201 | # Initializes a text binding for the specified view and text node. | 212 | # Initializes a text binding for the specified view and text node. |
202 | constructor: (@view, @el, @type, @key, @keypath, @options = {}) -> | 213 | constructor: (@view, @el, @type, @keypath, @options = {}) -> |
214 | interfaces = (k for k, v of @view.adapters) | ||
215 | tokens = Rivets.KeypathParser.parse(@keypath, interfaces, '.') | ||
203 | @formatters = @options.formatters || [] | 216 | @formatters = @options.formatters || [] |
204 | @model = if @key then @view.models[@key] else @view.models | 217 | @setModel() |
205 | 218 | ||
206 | # A standard routine binder used for text node bindings. | 219 | # A standard routine binder used for text node bindings. |
207 | binder: | 220 | binder: |
... | @@ -252,22 +265,14 @@ class Rivets.View | ... | @@ -252,22 +265,14 @@ class Rivets.View |
252 | 265 | ||
253 | pipes = (pipe.trim() for pipe in declaration.split '|') | 266 | pipes = (pipe.trim() for pipe in declaration.split '|') |
254 | context = (ctx.trim() for ctx in pipes.shift().split '<') | 267 | context = (ctx.trim() for ctx in pipes.shift().split '<') |
255 | path = context.shift() | 268 | keypath = context.shift() |
256 | splitPath = path.split '.' | ||
257 | options.formatters = pipes | ||
258 | 269 | ||
259 | if splitPath[0] | 270 | options.formatters = pipes |
260 | key = splitPath.shift() | ||
261 | else | ||
262 | key = null | ||
263 | splitPath.shift() | ||
264 | |||
265 | keypath = splitPath.join '.' | ||
266 | 271 | ||
267 | if dependencies = context.shift() | 272 | if dependencies = context.shift() |
268 | options.dependencies = dependencies.split /\s+/ | 273 | options.dependencies = dependencies.split /\s+/ |
269 | 274 | ||
270 | @bindings.push new Rivets[binding] @, node, type, key, keypath, options | 275 | @bindings.push new Rivets[binding] @, node, type, keypath, options |
271 | 276 | ||
272 | parse = (node) => | 277 | parse = (node) => |
273 | unless node in skipNodes | 278 | unless node in skipNodes |
... | @@ -553,6 +558,7 @@ Rivets.binders = | ... | @@ -553,6 +558,7 @@ Rivets.binders = |
553 | options = | 558 | options = |
554 | binders: @view.options.binders | 559 | binders: @view.options.binders |
555 | formatters: @view.options.formatters | 560 | formatters: @view.options.formatters |
561 | adapters: @view.options.adapters | ||
556 | config: @view.options.config | 562 | config: @view.options.config |
557 | 563 | ||
558 | (@nested = new Rivets.View(el, models, options)).bind() | 564 | (@nested = new Rivets.View(el, models, options)).bind() |
... | @@ -632,6 +638,7 @@ Rivets.binders = | ... | @@ -632,6 +638,7 @@ Rivets.binders = |
632 | options = | 638 | options = |
633 | binders: @view.options.binders | 639 | binders: @view.options.binders |
634 | formatters: @view.options.formatters | 640 | formatters: @view.options.formatters |
641 | adapters: @view.options.adapters | ||
635 | config: {} | 642 | config: {} |
636 | 643 | ||
637 | options.config[k] = v for k, v of @view.options.config | 644 | options.config[k] = v for k, v of @view.options.config | ... | ... |
-
Please register or sign in to post a comment