f7c291b5 by Michael Richards

Rewrite the DOM template parser in Rivets.View#build to include text template parsing. [#181]

1 parent 6cb9af1e
...@@ -173,54 +173,71 @@ class Rivets.View ...@@ -173,54 +173,71 @@ class Rivets.View
173 skipNodes = [] 173 skipNodes = []
174 bindingRegExp = @bindingRegExp() 174 bindingRegExp = @bindingRegExp()
175 175
176 buildBinding = (node, type, declaration) =>
177 options = {}
178
179 pipes = (pipe.trim() for pipe in declaration.split '|')
180 context = (ctx.trim() for ctx in pipes.shift().split '<')
181 path = context.shift()
182 splitPath = path.split /\.|:/
183 options.formatters = pipes
184 options.bypass = path.indexOf(':') != -1
185
186 if splitPath[0]
187 key = splitPath.shift()
188 else
189 key = null
190 splitPath.shift()
191
192 keypath = splitPath.join '.'
193
194 if dependencies = context.shift()
195 options.dependencies = dependencies.split /\s+/
196
197 @bindings.push new Rivets.Binding @, node, type, key, keypath, options
198
176 parse = (node) => 199 parse = (node) =>
177 unless node in skipNodes 200 unless node in skipNodes
178 for attribute in node.attributes 201 if node.nodeType is Node.TEXT_NODE
179 if bindingRegExp.test attribute.name 202 if (tokens = Rivets.TextTemplateParser.parse node.data).length
180 type = attribute.name.replace bindingRegExp, '' 203 unless tokens.length is 1 and tokens[0].type is 0
181 unless binder = @binders[type] 204 [startToken, restTokens...] = tokens
182 for identifier, value of @binders 205
183 if identifier isnt '*' and identifier.indexOf('*') isnt -1 206 node.data = startToken.value
184 regexp = new RegExp "^#{identifier.replace('*', '.+')}$" 207
185 if regexp.test type 208 switch startToken.type
186 binder = value 209 when 0 then node.data = startToken.value
187 210 when 1 then buildBinding node, 'textNode', startToken.value
188 binder or= @binders['*'] 211
189 212 for token in restTokens
190 if binder.block 213 node.parentNode.appendChild (text = document.createTextNode token.value)
191 skipNodes.push n for n in node.getElementsByTagName '*' 214 buildBinding text, 'textNode', token.value if token.type is 1
192 attributes = [attribute] 215
193 216 else if node.attributes?
194 for attribute in attributes or node.attributes 217 for attribute in node.attributes
195 if bindingRegExp.test attribute.name 218 if bindingRegExp.test attribute.name
196 options = {} 219 type = attribute.name.replace bindingRegExp, ''
197 type = attribute.name.replace bindingRegExp, '' 220 unless binder = @binders[type]
198 pipes = (pipe.trim() for pipe in attribute.value.split '|') 221 for identifier, value of @binders
199 context = (ctx.trim() for ctx in pipes.shift().split '<') 222 if identifier isnt '*' and identifier.indexOf('*') isnt -1
200 path = context.shift() 223 regexp = new RegExp "^#{identifier.replace('*', '.+')}$"
201 splitPath = path.split /\.|:/ 224 if regexp.test type
202 options.formatters = pipes 225 binder = value
203 options.bypass = path.indexOf(':') != -1 226
204 if splitPath[0] 227 binder or= @binders['*']
205 key = splitPath.shift() 228
206 else 229 if binder.block
207 key = null 230 skipNodes.push n for n in node.childNodes
208 splitPath.shift() 231 attributes = [attribute]
209 keypath = splitPath.join '.' 232
210 233 for attribute in attributes or node.attributes
211 if not key or @models[key]? 234 if bindingRegExp.test attribute.name
212 if dependencies = context.shift() 235 type = attribute.name.replace bindingRegExp, ''
213 options.dependencies = dependencies.split /\s+/ 236 buildBinding node, type, attribute.value
214 237
215 @bindings.push new Rivets.Binding @, node, type, key, keypath, options 238 parse childNode for childNode in node.childNodes
216 239
217 attributes = null if attributes 240 parse el for el in @els
218
219 return
220
221 for el in @els
222 parse el
223 parse node for node in el.getElementsByTagName '*' when node.attributes?
224 241
225 return 242 return
226 243
......