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 part of polymer; | 5 part of polymer; |
6 | 6 |
7 /// Use this annotation to publish a field as an attribute. For example: | 7 /// Use this annotation to publish a field as an attribute. For example: |
8 /// | 8 /// |
9 /// class MyPlaybackElement extends PolymerElement { | 9 /// class MyPlaybackElement extends PolymerElement { |
10 /// // This will be available as an HTML attribute, for example: | 10 /// // This will be available as an HTML attribute, for example: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 | 46 |
47 const ObserveProperty(this._names); | 47 const ObserveProperty(this._names); |
48 } | 48 } |
49 | 49 |
50 /// The mixin class for Polymer elements. It provides convenience features on | 50 /// The mixin class for Polymer elements. It provides convenience features on |
51 /// top of the custom elements web standard. | 51 /// top of the custom elements web standard. |
52 /// | 52 /// |
53 /// If this class is used as a mixin, | 53 /// If this class is used as a mixin, |
54 /// you must call `polymerCreated()` from the body of your constructor. | 54 /// you must call `polymerCreated()` from the body of your constructor. |
55 abstract class Polymer implements Element, Observable, NodeBindExtension { | 55 abstract class Polymer implements Element, Observable, NodeBindExtension { |
56 // Fully ported from revision: | |
57 // https://github.com/Polymer/polymer/blob/37eea00e13b9f86ab21c85a955585e8e423
7e3d2 | |
58 // | |
59 // src/boot.js (static APIs on "Polymer" object) | |
60 // src/instance/attributes.js | |
61 // src/instance/base.js | |
62 // src/instance/events.js | |
63 // src/instance/mdv.js | |
64 // src/instance/properties.js | |
65 // src/instance/style.js | |
66 // src/instance/utils.js | |
67 | 56 |
68 // TODO(jmesserly): should this really be public? | 57 // TODO(jmesserly): should this really be public? |
69 /// Regular expression that matches data-bindings. | 58 /// Regular expression that matches data-bindings. |
70 static final bindPattern = new RegExp(r'\{\{([^{}]*)}}'); | 59 static final bindPattern = new RegExp(r'\{\{([^{}]*)}}'); |
71 | 60 |
72 /// Like [document.register] but for Polymer elements. | 61 /// Like [document.register] but for Polymer elements. |
73 /// | 62 /// |
74 /// Use the [name] to specify custom elment's tag name, for example: | 63 /// Use the [name] to specify custom elment's tag name, for example: |
75 /// "fancy-button" if the tag is used as `<fancy-button>`. | 64 /// "fancy-button" if the tag is used as `<fancy-button>`. |
76 /// | 65 /// |
77 /// The [type] is the type to construct. If not supplied, it defaults to | 66 /// The [type] is the type to construct. If not supplied, it defaults to |
78 /// [PolymerElement]. | 67 /// [PolymerElement]. |
79 // NOTE: this is called "element" in src/declaration/polymer-element.js, and | 68 // NOTE: this is called "element" in src/declaration/polymer-element.js, and |
80 // exported as "Polymer". | 69 // exported as "Polymer". |
81 static void register(String name, [Type type]) { | 70 static void register(String name, [Type type]) { |
82 //console.log('registering [' + name + ']'); | 71 //console.log('registering [' + name + ']'); |
83 if (type == null) type = PolymerElement; | 72 if (type == null) type = PolymerElement; |
84 | 73 |
85 _typesByName[name] = type; | 74 _typesByName[name] = type; |
86 // notify the registrar waiting for 'name', if any | 75 |
87 _notifyType(name); | 76 // Dart note: here we notify JS of the element registration. We don't pass |
| 77 // the Dart type because we will handle that in PolymerDeclaration. |
| 78 // See _hookJsPolymerDeclaration for how this is done. |
| 79 (js.context['Polymer'] as JsFunction).apply([name]); |
88 } | 80 } |
89 | 81 |
90 /// The one syntax to rule them all. | 82 /// The one syntax to rule them all. |
91 static final BindingDelegate _polymerSyntax = | 83 static final BindingDelegate _polymerSyntax = |
92 new _PolymerExpressionsWithEventDelegate(); | 84 new _PolymerExpressionsWithEventDelegate(); |
93 | 85 |
94 static int _preparingElements = 0; | 86 static int _preparingElements = 0; |
95 | 87 |
96 static final Completer _ready = new Completer(); | 88 static final Completer _ready = new Completer(); |
97 | 89 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } | 185 } |
194 | 186 |
195 void leftView() { | 187 void leftView() { |
196 if (!preventDispose) asyncUnbindAll(); | 188 if (!preventDispose) asyncUnbindAll(); |
197 } | 189 } |
198 | 190 |
199 /// Recursive ancestral <element> initialization, oldest first. | 191 /// Recursive ancestral <element> initialization, oldest first. |
200 void parseDeclarations(PolymerDeclaration declaration) { | 192 void parseDeclarations(PolymerDeclaration declaration) { |
201 if (declaration != null) { | 193 if (declaration != null) { |
202 parseDeclarations(declaration.superDeclaration); | 194 parseDeclarations(declaration.superDeclaration); |
203 parseDeclaration(declaration); | 195 parseDeclaration(declaration.element); |
204 } | 196 } |
205 } | 197 } |
206 | 198 |
207 /// Parse input `<polymer-element>` as needed, override for custom behavior. | 199 /// Parse input `<polymer-element>` as needed, override for custom behavior. |
208 void parseDeclaration(Element elementElement) { | 200 void parseDeclaration(Element elementElement) { |
209 var template = fetchTemplate(elementElement); | 201 var template = fetchTemplate(elementElement); |
210 | 202 |
211 var root = null; | 203 var root = null; |
212 if (template != null) { | 204 if (template != null) { |
213 if (_declaration.attributes.containsKey('lightdom')) { | 205 if (_declaration.element.attributes.containsKey('lightdom')) { |
214 lightFromTemplate(template); | 206 lightFromTemplate(template); |
215 } else { | 207 } else { |
216 root = shadowFromTemplate(template); | 208 root = shadowFromTemplate(template); |
217 } | 209 } |
218 } | 210 } |
219 | 211 |
220 // Dart note: the following code is to support the getShadowRoot method. | 212 // Dart note: the following code is to support the getShadowRoot method. |
221 if (root is! ShadowRoot) return; | 213 if (root is! ShadowRoot) return; |
222 | 214 |
223 var name = elementElement.attributes['name']; | 215 var name = elementElement.attributes['name']; |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 var style = decl.cssTextToScopeStyle(cssText.toString(), | 852 var style = decl.cssTextToScopeStyle(cssText.toString(), |
861 _STYLE_CONTROLLER_SCOPE); | 853 _STYLE_CONTROLLER_SCOPE); |
862 // TODO(sorvell): for now these styles are not shimmed | 854 // TODO(sorvell): for now these styles are not shimmed |
863 // but we may need to shim them | 855 // but we may need to shim them |
864 Polymer.applyStyleToScope(style, scope); | 856 Polymer.applyStyleToScope(style, scope); |
865 } | 857 } |
866 } | 858 } |
867 } | 859 } |
868 | 860 |
869 Node findStyleController() { | 861 Node findStyleController() { |
870 if (js.context != null && js.context['ShadowDOMPolyfill'] != null) { | 862 if (js.context.hasProperty('ShadowDOMPolyfill')) { |
871 return document.querySelector('head'); // get wrapped <head>. | 863 return document.querySelector('head'); // get wrapped <head>. |
872 } else { | 864 } else { |
873 // find the shadow root that contains this element | 865 // find the shadow root that contains this element |
874 var n = this; | 866 var n = this; |
875 while (n.parentNode != null) { | 867 while (n.parentNode != null) { |
876 n = n.parentNode; | 868 n = n.parentNode; |
877 } | 869 } |
878 return identical(n, document) ? document.head : n; | 870 return identical(n, document) ? document.head : n; |
879 } | 871 } |
880 } | 872 } |
(...skipping 13 matching lines...) Expand all Loading... |
894 // var clone = style.cloneNode(true); | 886 // var clone = style.cloneNode(true); |
895 var clone = new StyleElement()..text = style.text; | 887 var clone = new StyleElement()..text = style.text; |
896 | 888 |
897 var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE]; | 889 var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE]; |
898 if (attr != null) { | 890 if (attr != null) { |
899 clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr; | 891 clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr; |
900 } | 892 } |
901 | 893 |
902 scope.append(clone); | 894 scope.append(clone); |
903 } | 895 } |
904 | |
905 /// Prevents flash of unstyled content | |
906 /// This is the list of selectors for veiled elements | |
907 static List<Element> veiledElements = ['body']; | |
908 | |
909 /// Apply unveil class. | |
910 static void unveilElements() { | |
911 window.requestAnimationFrame((_) { | |
912 var nodes = document.querySelectorAll('.$_VEILED_CLASS'); | |
913 for (var node in nodes) { | |
914 (node.classes)..add(_UNVEIL_CLASS)..remove(_VEILED_CLASS); | |
915 } | |
916 // NOTE: depends on transition end event to remove 'unveil' class. | |
917 if (nodes.isNotEmpty) { | |
918 window.onTransitionEnd.first.then((_) { | |
919 for (var node in nodes) { | |
920 node.classes.remove(_UNVEIL_CLASS); | |
921 } | |
922 }); | |
923 } | |
924 }); | |
925 } | |
926 } | 896 } |
927 | 897 |
928 // Dart note: Polymer addresses n-way bindings by metaprogramming: redefine | 898 // Dart note: Polymer addresses n-way bindings by metaprogramming: redefine |
929 // the property on the PolymerElement instance to always get its value from the | 899 // the property on the PolymerElement instance to always get its value from the |
930 // model@path. We can't replicate this in Dart so we do the next best thing: | 900 // model@path. We can't replicate this in Dart so we do the next best thing: |
931 // listen to changes on both sides and update the values. | 901 // listen to changes on both sides and update the values. |
932 // TODO(jmesserly): our approach leads to race conditions in the bindings. | 902 // TODO(jmesserly): our approach leads to race conditions in the bindings. |
933 // See http://code.google.com/p/dart/issues/detail?id=13567 | 903 // See http://code.google.com/p/dart/issues/detail?id=13567 |
934 class _PolymerBinding extends Bindable { | 904 class _PolymerBinding extends Bindable { |
935 final Polymer _target; | 905 final Polymer _target; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 if (_sub != null) { | 1017 if (_sub != null) { |
1048 if (_eventsLog.isLoggable(Level.FINE)) { | 1018 if (_eventsLog.isLoggable(Level.FINE)) { |
1049 _eventsLog.fine( | 1019 _eventsLog.fine( |
1050 'event.remove: [$_node].$_eventName => [$_model].$_path())'); | 1020 'event.remove: [$_node].$_eventName => [$_model].$_path())'); |
1051 } | 1021 } |
1052 _sub.cancel(); | 1022 _sub.cancel(); |
1053 _sub = null; | 1023 _sub = null; |
1054 } | 1024 } |
1055 } | 1025 } |
1056 } | 1026 } |
OLD | NEW |