OLD | NEW |
1 <!-- | 1 <!-- |
2 // Copyright 2014 The Chromium Authors. All rights reserved. | 2 // Copyright 2014 The Chromium Authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 --> | 5 --> |
6 <import src="observe.sky" as="observe" /> | 6 <import src="observe.sky" as="observe" /> |
7 <import src="element-registry.sky" as="registry" /> | 7 <import src="element-registry.sky" as="registry" /> |
8 | 8 |
9 <script> | 9 <script> |
10 var stagingDocument = new Document(); | 10 var stagingDocument = new Document(); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 directives.eventHandlers.push(name.substring(3)); | 170 directives.eventHandlers.push(name.substring(3)); |
171 continue; | 171 continue; |
172 } | 172 } |
173 | 173 |
174 if (!registry.checkAttribute(tagName, name)) { | 174 if (!registry.checkAttribute(tagName, name)) { |
175 console.error('Element "'+ tagName + | 175 console.error('Element "'+ tagName + |
176 '" has unknown attribute "' + name + '".'); | 176 '" has unknown attribute "' + name + '".'); |
177 } | 177 } |
178 | 178 |
179 var property = parsePropertyDirective(value, name); | 179 var property = parsePropertyDirective(value, name); |
180 if (!property) | 180 if (property) |
181 continue; | 181 directives.properties.push(property); |
182 | |
183 directives.properties.push(property); | |
184 } | 182 } |
185 } | 183 } |
186 | 184 |
| 185 function createCloneSource(element, properties) { |
| 186 if (!properties.length) |
| 187 return element; |
| 188 |
| 189 // Leave attributes alone on template so you can see the if/repeat statements |
| 190 // in the inspector. |
| 191 if (element instanceof HTMLTemplateElement) |
| 192 return element; |
| 193 |
| 194 var result = element.cloneNode(false); |
| 195 |
| 196 for (var i = 0; i < properties.length; ++i) { |
| 197 result.removeAttribute(properties[i].name); |
| 198 } |
| 199 |
| 200 return result; |
| 201 } |
| 202 |
187 function eventHandlerCallback(event) { | 203 function eventHandlerCallback(event) { |
188 var element = event.currentTarget; | 204 var element = event.currentTarget; |
189 var method = element.getAttribute('on-' + event.type); | 205 var method = element.getAttribute('on-' + event.type); |
190 var scope = element.ownerScope; | 206 var scope = element.ownerScope; |
191 var host = scope.host; | 207 var host = scope.host; |
192 var handler = host && host[method]; | 208 var handler = host && host[method]; |
193 if (handler instanceof Function) | 209 if (handler instanceof Function) |
194 return handler.call(host, event); | 210 return handler.call(host, event); |
195 } | 211 } |
196 | 212 |
197 class NodeDirectives { | 213 class NodeDirectives { |
198 constructor(node) { | 214 constructor(node) { |
199 this.eventHandlers = []; | 215 this.eventHandlers = []; |
200 this.children = []; | 216 this.children = []; |
201 this.properties = []; | 217 this.properties = []; |
202 this.node = node; | 218 this.node = node; |
| 219 this.cloneSourceNode = node; |
203 Object.preventExtensions(this); | 220 Object.preventExtensions(this); |
204 | 221 |
205 if (node instanceof Element) { | 222 if (node instanceof Element) { |
206 parseAttributeDirectives(node, this); | 223 parseAttributeDirectives(node, this); |
| 224 this.cloneSourceNode = createCloneSource(node, this.properties); |
207 } else if (node instanceof Text) { | 225 } else if (node instanceof Text) { |
208 var property = parsePropertyDirective(node.data, 'textContent'); | 226 var property = parsePropertyDirective(node.data, 'textContent'); |
209 if (property) | 227 if (property) |
210 this.properties.push(property); | 228 this.properties.push(property); |
211 } | 229 } |
212 | 230 |
213 for (var child = node.firstChild; child; child = child.nextSibling) { | 231 for (var child = node.firstChild; child; child = child.nextSibling) { |
214 this.children.push(new NodeDirectives(child)); | 232 this.children.push(new NodeDirectives(child)); |
215 } | 233 } |
216 } | 234 } |
217 findProperty(name) { | 235 findProperty(name) { |
218 for (var i = 0; i < this.properties.length; ++i) { | 236 for (var i = 0; i < this.properties.length; ++i) { |
219 if (this.properties[i].name === name) | 237 if (this.properties[i].name === name) |
220 return this.properties[i]; | 238 return this.properties[i]; |
221 } | 239 } |
222 return null; | 240 return null; |
223 } | 241 } |
224 createBoundClone(parent, model, bindings) { | 242 createBoundClone(parent, model, bindings) { |
225 // TODO(esprehn): In sky instead of needing to use a staging docuemnt per | 243 // TODO(esprehn): In sky instead of needing to use a staging docuemnt per |
226 // custom element registry we're going to need to use the current module's | 244 // custom element registry we're going to need to use the current module's |
227 // registry. | 245 // registry. |
228 var clone = stagingDocument.importNode(this.node, false); | 246 var clone = stagingDocument.importNode(this.cloneSourceNode, false); |
229 | 247 |
230 for (var i = 0; i < this.eventHandlers.length; ++i) { | 248 for (var i = 0; i < this.eventHandlers.length; ++i) { |
231 clone.addEventListener(this.eventHandlers[i], eventHandlerCallback); | 249 clone.addEventListener(this.eventHandlers[i], eventHandlerCallback); |
232 } | 250 } |
233 | 251 |
234 var clone = parent.appendChild(clone); | |
235 | |
236 for (var i = 0; i < this.children.length; ++i) { | |
237 this.children[i].createBoundClone(clone, model, bindings); | |
238 } | |
239 | |
240 for (var i = 0; i < this.properties.length; ++i) { | 252 for (var i = 0; i < this.properties.length; ++i) { |
241 bindings.push(this.properties[i].bindProperty(clone, model)); | 253 bindings.push(this.properties[i].bindProperty(clone, model)); |
242 } | 254 } |
243 | 255 |
| 256 parent.appendChild(clone); |
| 257 |
| 258 for (var i = 0; i < this.children.length; ++i) { |
| 259 this.children[i].createBoundClone(clone, model, bindings); |
| 260 } |
| 261 |
244 if (clone instanceof HTMLTemplateElement) { | 262 if (clone instanceof HTMLTemplateElement) { |
245 var iterator = new TemplateIterator(clone); | 263 var iterator = new TemplateIterator(clone); |
246 iterator.updateDependencies(this, model); | 264 iterator.updateDependencies(this, model); |
247 bindings.push(iterator); | 265 bindings.push(iterator); |
248 } | 266 } |
249 | 267 |
250 return clone; | 268 return clone; |
251 } | 269 } |
252 } | 270 } |
253 | 271 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 | 489 |
472 iterators.delete(this.template); | 490 iterators.delete(this.template); |
473 this.closed = true; | 491 this.closed = true; |
474 } | 492 } |
475 } | 493 } |
476 | 494 |
477 module.exports = { | 495 module.exports = { |
478 createInstance: createInstance, | 496 createInstance: createInstance, |
479 }; | 497 }; |
480 </script> | 498 </script> |
OLD | NEW |