OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library polymer.polymer_element; | 5 library polymer.polymer_element; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:html'; | 8 import 'dart:html'; |
9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
10 | 10 |
11 import 'package:mdv/mdv.dart' as mdv; | |
11 import 'package:observe/observe.dart'; | 12 import 'package:observe/observe.dart'; |
12 | 13 |
13 import 'custom_element.dart'; | 14 import 'custom_element.dart'; |
14 import 'observe.dart'; | 15 import 'observe.dart'; |
15 import 'src/utils_observe.dart' show toCamelCase, toHyphenedName; | 16 import 'src/utils_observe.dart' show toCamelCase, toHyphenedName; |
16 | 17 |
17 /** | 18 /** |
18 * Registers a [PolymerElement]. This is similar to [registerCustomElement] | 19 * Registers a [PolymerElement]. This is similar to [registerCustomElement] |
19 * but it is designed to work with the `<element>` element and adds additional | 20 * but it is designed to work with the `<element>` element and adds additional |
20 * features. | 21 * features. |
21 */ | 22 */ |
22 // TODO(sigmund): change this to take the 'localName' (recent polymer change) | 23 void registerPolymerElement(String localName, PolymerElement create()) { |
23 void registerPolymerElement(Element elementElement, CustomElement create()) { | 24 registerCustomElement(localName, () => create().._initialize(localName)); |
24 // Creates the CustomElement and then publish attributes. | |
25 createElement() { | |
26 final CustomElement element = create(); | |
27 // TODO(jmesserly): to simplify the DWC compiler, we always emit calls to | |
28 // registerPolymerElement, regardless of the base class type. | |
29 if (element is PolymerElement) { | |
30 PolymerElement pElement = element; | |
31 pElement._parseHostEvents(elementElement); | |
32 pElement._parseLocalEvents(elementElement); | |
33 pElement._publishAttributes(elementElement); | |
34 } | |
35 return element; | |
36 } | |
37 | |
38 registerCustomElement(elementElement.attributes['name'], createElement); | |
39 } | 25 } |
40 | 26 |
41 /** | 27 /** |
42 * *Warning*: many features of this class are not fully implemented. | 28 * *Warning*: many features of this class are not fully implemented. |
43 * | 29 * |
44 * The base class for Polymer elements. It provides convience features on top | 30 * The base class for Polymer elements. It provides convience features on top |
45 * of the custom elements web standard. | 31 * of the custom elements web standard. |
46 * | 32 * |
47 * Currently it supports publishing attributes via: | 33 * Currently it supports publishing attributes via: |
48 * | 34 * |
(...skipping 11 matching lines...) Expand all Loading... | |
60 // This is a partial port of: | 46 // This is a partial port of: |
61 // https://github.com/Polymer/polymer/blob/stable/src/attrs.js | 47 // https://github.com/Polymer/polymer/blob/stable/src/attrs.js |
62 // https://github.com/Polymer/polymer/blob/stable/src/bindProperties.js | 48 // https://github.com/Polymer/polymer/blob/stable/src/bindProperties.js |
63 // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js | 49 // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js |
64 // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js | 50 // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js |
65 // TODO(jmesserly): we still need to port more of the functionality | 51 // TODO(jmesserly): we still need to port more of the functionality |
66 | 52 |
67 // TODO(sigmund): delete. The next line is only added to avoid warnings from | 53 // TODO(sigmund): delete. The next line is only added to avoid warnings from |
68 // the analyzer (see http://dartbug.com/11672) | 54 // the analyzer (see http://dartbug.com/11672) |
69 Element get host => super.host; | 55 Element get host => super.host; |
56 | |
57 bool get applyAuthorStyles => false; | |
58 bool get resetStyleInheritance => false; | |
59 | |
60 /** | |
61 * The declaration of this polymer-element, used to extract template contents | |
62 * and other information. | |
63 */ | |
64 static Map<String, Element> _declarations = {}; | |
65 static Element getDeclaration(String localName) { | |
66 if (localName == null) return null; | |
67 var element = _declarations[localName]; | |
68 if (element == null) { | |
69 element = document.query('polymer-element[name="$localName"]'); | |
70 _declarations[localName] = element; | |
71 } | |
72 return element; | |
73 } | |
74 | |
70 Map<String, PathObserver> _publishedAttrs; | 75 Map<String, PathObserver> _publishedAttrs; |
71 Map<String, StreamSubscription> _bindings; | 76 Map<String, StreamSubscription> _bindings; |
77 final List<String> _localNames = []; | |
72 | 78 |
73 void _publishAttributes(Element elementElement) { | 79 void _initialize(String localName) { |
80 if (localName == null) return; | |
81 | |
82 var declaration = getDeclaration(localName); | |
83 if (declaration == null) return; | |
84 | |
85 if (declaration.attributes['extends'] != null) { | |
86 var base = declaration.attributes['extends']; | |
87 // Skip normal tags, only initialize parent custom elements. | |
88 if (base.contains('-')) _initialize(base); | |
89 } | |
90 | |
91 _parseHostEvents(declaration); | |
92 _parseLocalEvents(declaration); | |
93 _publishAttributes(declaration); | |
94 _localNames.add(localName); | |
95 } | |
96 | |
97 void _publishAttributes(elementElement) { | |
74 _bindings = {}; | 98 _bindings = {}; |
75 _publishedAttrs = {}; | 99 _publishedAttrs = {}; |
76 | 100 |
77 var attrs = elementElement.attributes['attributes']; | 101 var attrs = elementElement.attributes['attributes']; |
78 if (attrs != null) { | 102 if (attrs != null) { |
79 // attributes='a b c' or attributes='a,b,c' | 103 // attributes='a b c' or attributes='a,b,c' |
80 for (var name in attrs.split(attrs.contains(',') ? ',' : ' ')) { | 104 for (var name in attrs.split(attrs.contains(',') ? ',' : ' ')) { |
81 name = name.trim(); | 105 name = name.trim(); |
82 | 106 |
83 // TODO(jmesserly): PathObserver is overkill here; it helps avoid | 107 // TODO(jmesserly): PathObserver is overkill here; it helps avoid |
84 // "new Symbol" and other mirrors-related warnings. | 108 // "new Symbol" and other mirrors-related warnings. |
85 _publishedAttrs[name] = new PathObserver(this, toCamelCase(name)); | 109 _publishedAttrs[name] = new PathObserver(this, toCamelCase(name)); |
86 } | 110 } |
87 } | 111 } |
88 } | 112 } |
89 | 113 |
90 void created() { | 114 void created() { |
91 // TODO(jmesserly): this breaks until we get some kind of type conversion. | 115 // TODO(jmesserly): this breaks until we get some kind of type conversion. |
92 // _publishedAttrs.forEach((name, propObserver) { | 116 // _publishedAttrs.forEach((name, propObserver) { |
93 // var value = attributes[name]; | 117 // var value = attributes[name]; |
94 // if (value != null) propObserver.value = value; | 118 // if (value != null) propObserver.value = value; |
95 // }); | 119 // }); |
96 | 120 _initShadowRoot(); |
97 _addHostListeners(); | 121 _addHostListeners(); |
98 } | 122 } |
99 | 123 |
100 // TODO(sigmund): make this private once we create the shadow root directly | 124 void _initShadowRoot() { |
101 // here in polymer element. | 125 for (var localName in _localNames) { |
102 void shadowRootReady(ShadowRoot root, String elementName) { | 126 var declaration = getDeclaration(localName); |
103 _addInstanceListeners(root, elementName); | 127 var root = createShadowRoot(localName); |
128 _addInstanceListeners(root, localName); | |
129 | |
130 root.applyAuthorStyles = applyAuthorStyles; | |
131 root.resetStyleInheritance = resetStyleInheritance; | |
132 | |
133 var templateNode = declaration.children.firstWhere( | |
134 (n) => n.localName == 'template', orElse: () => null); | |
135 if (templateNode == null) return; | |
136 | |
137 root.nodes.add(cloneTemplate(templateNode.content)); | |
138 // TODO(sigmund): use fancy-syntax as the default. | |
139 var syntax = templateNode.attributes['syntax']; | |
140 | |
141 // TODO(sigmund,jmesserly): mdv.bindModel should be async internally | |
142 Timer.run(() => mdv.bindModel(root, this, | |
Siggi Cherem (dart-lang)
2013/07/19 22:52:52
so this was the fix after all. Seems to work ok fo
Jennifer Messerly
2013/07/19 23:16:24
not sure... it depends on how Timer.run is impleme
| |
143 syntax != null ? TemplateElement.syntax[syntax] : null)); | |
144 } | |
104 } | 145 } |
105 | 146 |
106 void bind(String name, model, String path) { | 147 void bind(String name, model, String path) { |
107 var propObserver = _publishedAttrs[name]; | 148 var propObserver = _publishedAttrs[name]; |
108 if (propObserver != null) { | 149 if (propObserver != null) { |
109 unbind(name); | 150 unbind(name); |
110 | 151 |
111 _bindings[name] = new PathObserver(model, path).bindSync((value) { | 152 _bindings[name] = new PathObserver(model, path).bindSync((value) { |
112 propObserver.value = value; | 153 propObserver.value = value; |
113 }); | 154 }); |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 'onKeyMessage': MediaElement.keyMessageEvent, | 511 'onKeyMessage': MediaElement.keyMessageEvent, |
471 'onNeedKey': MediaElement.needKeyEvent, | 512 'onNeedKey': MediaElement.needKeyEvent, |
472 'onWebGlContextLost': CanvasElement.webGlContextLostEvent, | 513 'onWebGlContextLost': CanvasElement.webGlContextLostEvent, |
473 'onWebGlContextRestored': CanvasElement.webGlContextRestoredEvent, | 514 'onWebGlContextRestored': CanvasElement.webGlContextRestoredEvent, |
474 'onPointerLockChange': Document.pointerLockChangeEvent, | 515 'onPointerLockChange': Document.pointerLockChangeEvent, |
475 'onPointerLockError': Document.pointerLockErrorEvent, | 516 'onPointerLockError': Document.pointerLockErrorEvent, |
476 'onReadyStateChange': Document.readyStateChangeEvent, | 517 'onReadyStateChange': Document.readyStateChangeEvent, |
477 'onSelectionChange': Document.selectionChangeEvent, | 518 'onSelectionChange': Document.selectionChangeEvent, |
478 'onSecurityPolicyViolation': Document.securityPolicyViolationEvent, | 519 'onSecurityPolicyViolation': Document.securityPolicyViolationEvent, |
479 }; | 520 }; |
OLD | NEW |