| 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 |