Initial components implementation with custom attributes and scope inflections.
Showing
1 changed file
with
41 additions
and
2 deletions
... | @@ -178,6 +178,10 @@ class Rivets.View | ... | @@ -178,6 +178,10 @@ class Rivets.View |
178 | prefix = @config.prefix | 178 | prefix = @config.prefix |
179 | if prefix then new RegExp("^data-#{prefix}-") else /^data-/ | 179 | if prefix then new RegExp("^data-#{prefix}-") else /^data-/ |
180 | 180 | ||
181 | # Regular expression used to match component nodes. | ||
182 | componentRegExp: => | ||
183 | new RegExp "^#{@config.prefix?.toUpperCase() ? 'RV'}-" | ||
184 | |||
181 | # Parses the DOM tree and builds `Rivets.Binding` instances for every matched | 185 | # Parses the DOM tree and builds `Rivets.Binding` instances for every matched |
182 | # binding declaration. Subsequent calls to build will replace the previous | 186 | # binding declaration. Subsequent calls to build will replace the previous |
183 | # `Rivets.Binding` instances with new ones, so be sure to unbind them first. | 187 | # `Rivets.Binding` instances with new ones, so be sure to unbind them first. |
... | @@ -185,6 +189,8 @@ class Rivets.View | ... | @@ -185,6 +189,8 @@ class Rivets.View |
185 | @bindings = [] | 189 | @bindings = [] |
186 | skipNodes = [] | 190 | skipNodes = [] |
187 | bindingRegExp = @bindingRegExp() | 191 | bindingRegExp = @bindingRegExp() |
192 | componentRegExp = @componentRegExp() | ||
193 | |||
188 | 194 | ||
189 | buildBinding = (node, type, declaration) => | 195 | buildBinding = (node, type, declaration) => |
190 | options = {} | 196 | options = {} |
... | @@ -208,7 +214,7 @@ class Rivets.View | ... | @@ -208,7 +214,7 @@ class Rivets.View |
208 | options.dependencies = dependencies.split /\s+/ | 214 | options.dependencies = dependencies.split /\s+/ |
209 | 215 | ||
210 | @bindings.push new Rivets.Binding @, node, type, key, keypath, options | 216 | @bindings.push new Rivets.Binding @, node, type, key, keypath, options |
211 | 217 | ||
212 | parse = (node) => | 218 | parse = (node) => |
213 | unless node in skipNodes | 219 | unless node in skipNodes |
214 | if node.nodeType is Node.TEXT_NODE | 220 | if node.nodeType is Node.TEXT_NODE |
... | @@ -227,7 +233,29 @@ class Rivets.View | ... | @@ -227,7 +233,29 @@ class Rivets.View |
227 | for token in restTokens | 233 | for token in restTokens |
228 | node.parentNode.appendChild (text = document.createTextNode token.value) | 234 | node.parentNode.appendChild (text = document.createTextNode token.value) |
229 | buildBinding text, 'textNode', token.value if token.type is 1 | 235 | buildBinding text, 'textNode', token.value if token.type is 1 |
230 | 236 | else if componentRegExp.test node.tagName | |
237 | type = node.tagName.replace(componentRegExp, '').toLowerCase() | ||
238 | |||
239 | if component = Rivets.components[type] | ||
240 | attributes = {} | ||
241 | inflections = {} | ||
242 | |||
243 | for attribute in node.attributes or [] | ||
244 | if attribute.name in component.attributes | ||
245 | attributes[attribute.name] = attribute.value | ||
246 | else | ||
247 | model = @models | ||
248 | model = model[key] for key in attribute.value.split('.') | ||
249 | inflections[attribute.name] = model | ||
250 | |||
251 | el = component.build.call(attributes) | ||
252 | |||
253 | models = {} | ||
254 | models[key] = model for key, model of inflections | ||
255 | models[key] ?= model for key, model of @models | ||
256 | |||
257 | (view = new Rivets.View(el, models, @options)).bind() | ||
258 | node.parentNode.replaceChild el, node | ||
231 | else if node.attributes? | 259 | else if node.attributes? |
232 | for attribute in node.attributes | 260 | for attribute in node.attributes |
233 | if bindingRegExp.test attribute.name | 261 | if bindingRegExp.test attribute.name |
... | @@ -591,6 +619,14 @@ Rivets.internalBinders = | ... | @@ -591,6 +619,14 @@ Rivets.internalBinders = |
591 | textNode: (node, value) -> | 619 | textNode: (node, value) -> |
592 | node.data = value ? '' | 620 | node.data = value ? '' |
593 | 621 | ||
622 | # Rivets.components | ||
623 | # ----------------- | ||
624 | |||
625 | # Default components (there aren't any), publicly accessible on | ||
626 | # `module.components`. Can be overridden globally or local to a `Rivets.View` | ||
627 | # instance. | ||
628 | Rivets.components = {} | ||
629 | |||
594 | # Rivets.config | 630 | # Rivets.config |
595 | # ------------- | 631 | # ------------- |
596 | 632 | ||
... | @@ -620,6 +656,9 @@ Rivets.factory = (exports) -> | ... | @@ -620,6 +656,9 @@ Rivets.factory = (exports) -> |
620 | # Exposes the core binding routines that can be extended or stripped down. | 656 | # Exposes the core binding routines that can be extended or stripped down. |
621 | exports.binders = Rivets.binders | 657 | exports.binders = Rivets.binders |
622 | 658 | ||
659 | # Exposes the components object to be extended. | ||
660 | exports.components = Rivets.components | ||
661 | |||
623 | # Exposes the formatters object to be extended. | 662 | # Exposes the formatters object to be extended. |
624 | exports.formatters = Rivets.formatters | 663 | exports.formatters = Rivets.formatters |
625 | 664 | ... | ... |
-
Please register or sign in to post a comment