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