Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: pkg/polymer/lib/src/instance.dart

Issue 26051002: Updating Polymer to derive from custom elements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 /** 7 /**
8 * Use this annotation to publish a field as an attribute. For example: 8 * Use this annotation to publish a field as an attribute. For example:
9 * 9 *
10 * class MyPlaybackElement extends PolymerElement { 10 * class MyPlaybackElement extends PolymerElement {
11 * // This will be available as an HTML attribute, for example: 11 * // This will be available as an HTML attribute, for example:
12 * // <my-playback volume="11"> 12 * // <my-playback volume="11">
13 * @published double volume; 13 * @published double volume;
14 * } 14 * }
15 */ 15 */
16 // TODO(jmesserly): does @published imply @observable or vice versa? 16 // TODO(jmesserly): does @published imply @observable or vice versa?
17 const published = const PublishedProperty(); 17 const published = const PublishedProperty();
18 18
19 /** An annotation used to publish a field as an attribute. See [published]. */ 19 /** An annotation used to publish a field as an attribute. See [published]. */
20 class PublishedProperty extends ObservableProperty { 20 class PublishedProperty extends ObservableProperty {
21 const PublishedProperty(); 21 const PublishedProperty();
22 } 22 }
23 23
24 // TODO(jmesserly): make this the mixin so we can have Polymer type extensions, 24 /**
25 // and move the implementation of PolymerElement in here. Once done it will look 25 * The mixin class for Polymer elements. It provides convenience features on top
26 // like: 26 * of the custom elements web standard.
27 // abstract class Polymer { ... all the things ... } 27 */
28 // typedef PolymerElement = HtmlElement with Polymer, Observable; 28 abstract class Polymer implements Element {
29 abstract class Polymer { 29 // Fully ported from revision:
30 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212 67779
31 //
32 // src/instance/attributes.js
33 // src/instance/base.js
34 // src/instance/events.js
35 // src/instance/mdv.js
36 // src/instance/properties.js
37 // src/instance/utils.js
38 //
39 // Not yet ported:
40 // src/instance/style.js -- blocked on ShadowCSS.shimPolyfillDirectives
41
42
30 // TODO(jmesserly): should this really be public? 43 // TODO(jmesserly): should this really be public?
31 /** Regular expression that matches data-bindings. */ 44 /** Regular expression that matches data-bindings. */
32 static final bindPattern = new RegExp(r'\{\{([^{}]*)}}'); 45 static final bindPattern = new RegExp(r'\{\{([^{}]*)}}');
33 46
34 /** 47 /**
35 * Like [document.register] but for Polymer elements. 48 * Like [document.register] but for Polymer elements.
36 * 49 *
37 * Use the [name] to specify custom elment's tag name, for example: 50 * Use the [name] to specify custom elment's tag name, for example:
38 * "fancy-button" if the tag is used as `<fancy-button>`. 51 * "fancy-button" if the tag is used as `<fancy-button>`.
39 * 52 *
40 * The [type] is the type to construct. If not supplied, it defaults to 53 * The [type] is the type to construct. If not supplied, it defaults to
41 * [PolymerElement]. 54 * [PolymerElement].
42 */ 55 */
43 // NOTE: this is called "element" in src/declaration/polymer-element.js, and 56 // NOTE: this is called "element" in src/declaration/polymer-element.js, and
44 // exported as "Polymer". 57 // exported as "Polymer".
45 static void register(String name, [Type type]) { 58 static void register(String name, [Type type]) {
46 //console.log('registering [' + name + ']'); 59 //console.log('registering [' + name + ']');
47 if (type == null) type = PolymerElement; 60 if (type == null) type = PolymerElement;
48 _registerClassMirror(name, reflectClass(type));
49 }
50 61
51 // TODO(jmesserly): we use ClassMirror internall for now, until it is possible
52 // to get from ClassMirror -> Type.
53 static void _registerClassMirror(String name, ClassMirror type) {
54 _typesByName[name] = type; 62 _typesByName[name] = type;
55 // notify the registrar waiting for 'name', if any 63 // notify the registrar waiting for 'name', if any
56 _notifyType(name); 64 _notifyType(name);
57 } 65 }
58 }
59
60 /**
61 * The base class for Polymer elements. It provides convience features on top
62 * of the custom elements web standard.
63 */
64 class PolymerElement extends CustomElement with ObservableMixin {
65 // Fully ported from revision:
66 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212 67779
67 //
68 // src/instance/attributes.js
69 // src/instance/base.js
70 // src/instance/events.js
71 // src/instance/mdv.js
72 // src/instance/properties.js
73 // src/instance/utils.js
74 //
75 // Not yet ported:
76 // src/instance/style.js -- blocked on ShadowCSS.shimPolyfillDirectives
77 66
78 /// The one syntax to rule them all. 67 /// The one syntax to rule them all.
79 static final BindingDelegate _polymerSyntax = new PolymerExpressions(); 68 static final BindingDelegate _polymerSyntax = new PolymerExpressions();
80 69
81 static int _preparingElements = 0; 70 static int _preparingElements = 0;
82 71
83 PolymerDeclaration _declaration; 72 PolymerDeclaration _declaration;
84 73
85 /** The most derived `<polymer-element>` declaration for this element. */ 74 /** The most derived `<polymer-element>` declaration for this element. */
86 PolymerDeclaration get declaration => _declaration; 75 PolymerDeclaration get declaration => _declaration;
(...skipping 26 matching lines...) Expand all
113 * Gets the shadow root associated with the corresponding custom element. 102 * Gets the shadow root associated with the corresponding custom element.
114 * 103 *
115 * This is identical to [shadowRoot], unless there are multiple levels of 104 * This is identical to [shadowRoot], unless there are multiple levels of
116 * inheritance and they each have their own shadow root. For example, 105 * inheritance and they each have their own shadow root. For example,
117 * this can happen if the base class and subclass both have `<template>` tags 106 * this can happen if the base class and subclass both have `<template>` tags
118 * in their `<polymer-element>` tags. 107 * in their `<polymer-element>` tags.
119 */ 108 */
120 // TODO(jmesserly): Polymer does not have this feature. Reconcile. 109 // TODO(jmesserly): Polymer does not have this feature. Reconcile.
121 ShadowRoot getShadowRoot(String customTagName) => _shadowRoots[customTagName]; 110 ShadowRoot getShadowRoot(String customTagName) => _shadowRoots[customTagName];
122 111
123 ShadowRoot createShadowRoot([name]) {
124 if (name != null) {
125 throw new ArgumentError('name argument must not be supplied.');
126 }
127
128 // Provides ability to traverse from ShadowRoot to the host.
129 // TODO(jmessery): remove once we have this ability on the DOM.
130 final root = super.createShadowRoot();
131 _shadowHost[root] = host;
132 return root;
133 }
134
135 /** 112 /**
136 * Invoke [callback] in [wait], unless the job is re-registered, 113 * Invoke [callback] in [wait], unless the job is re-registered,
137 * which resets the timer. For example: 114 * which resets the timer. For example:
138 * 115 *
139 * _myJob = job(_myJob, callback, const Duration(milliseconds: 100)); 116 * _myJob = job(_myJob, callback, const Duration(milliseconds: 100));
140 * 117 *
141 * Returns a job handle which can be used to re-register a job. 118 * Returns a job handle which can be used to re-register a job.
142 */ 119 */
143 Job job(Job job, void callback(), Duration wait) => 120 Job job(Job job, void callback(), Duration wait) =>
144 runJob(job, callback, wait); 121 runJob(job, callback, wait);
145 122
146 // TODO(jmesserly): I am not sure if we should have the 123 // TODO(jmesserly): I am not sure if we should have the
147 // created/createdCallback distinction. See post here: 124 // created/createdCallback distinction. See post here:
148 // https://groups.google.com/d/msg/polymer-dev/W0ZUpU5caIM/v5itFnvnehEJ 125 // https://groups.google.com/d/msg/polymer-dev/W0ZUpU5caIM/v5itFnvnehEJ
149 // Same issue with inserted and removed. 126 // Same issue with inserted and removed.
150 void created() { 127 void initialize() {
151 if (document.window != null || alwaysPrepare || _preparingElements > 0) { 128 if (document.window != null || alwaysPrepare || _preparingElements > 0) {
152 prepareElement(); 129 prepareElement();
153 } 130 }
154 } 131 }
155 132
156 void prepareElement() { 133 void prepareElement() {
157 // Dart note: get the _declaration, which also marks _elementPrepared 134 // Dart note: get the _declaration, which also marks _elementPrepared
158 _declaration = _getDeclaration(reflect(this).type); 135 _declaration = _getDeclaration(this.runtimeType);
159 // do this first so we can observe changes during initialization 136 // do this first so we can observe changes during initialization
160 observeProperties(); 137 observeProperties();
161 // install boilerplate attributes 138 // install boilerplate attributes
162 copyInstanceAttributes(); 139 copyInstanceAttributes();
163 // process input attributes 140 // process input attributes
164 takeAttributes(); 141 takeAttributes();
165 // add event listeners 142 // add event listeners
166 addHostListeners(); 143 addHostListeners();
167 // guarantees that while preparing, any sub-elements will also be prepared 144 // guarantees that while preparing, any sub-elements will also be prepared
168 _preparingElements++; 145 _preparingElements++;
169 // process declarative resources 146 // process declarative resources
170 parseDeclarations(_declaration); 147 parseDeclarations(_declaration);
171 _preparingElements--; 148 _preparingElements--;
172 // user entry point 149 // user entry point
173 ready(); 150 ready();
174 } 151 }
175 152
176 /** Called when [prepareElement] is finished. */ 153 /** Called when [prepareElement] is finished. */
177 void ready() {} 154 void ready() {}
178 155
179 void inserted() { 156 void enteredView() {
180 if (!_elementPrepared) { 157 if (!_elementPrepared) {
181 prepareElement(); 158 prepareElement();
182 } 159 }
183 cancelUnbindAll(preventCascade: true); 160 cancelUnbindAll(preventCascade: true);
184 } 161 }
185 162
186 void removed() { 163 void leftView() {
187 asyncUnbindAll(); 164 asyncUnbindAll();
188 } 165 }
189 166
190 /** Recursive ancestral <element> initialization, oldest first. */ 167 /** Recursive ancestral <element> initialization, oldest first. */
191 void parseDeclarations(PolymerDeclaration declaration) { 168 void parseDeclarations(PolymerDeclaration declaration) {
192 if (declaration != null) { 169 if (declaration != null) {
193 parseDeclarations(declaration.superDeclaration); 170 parseDeclarations(declaration.superDeclaration);
194 parseDeclaration(declaration.host); 171 parseDeclaration(declaration);
195 } 172 }
196 } 173 }
197 174
198 /** 175 /**
199 * Parse input `<polymer-element>` as needed, override for custom behavior. 176 * Parse input `<polymer-element>` as needed, override for custom behavior.
200 */ 177 */
201 void parseDeclaration(Element elementElement) { 178 void parseDeclaration(Element elementElement) {
202 var root = shadowFromTemplate(fetchTemplate(elementElement)); 179 var root = shadowFromTemplate(fetchTemplate(elementElement));
203 180
204 // Dart note: this is extra code compared to Polymer to support 181 // Dart note: this is extra code compared to Polymer to support
(...skipping 11 matching lines...) Expand all
216 Element fetchTemplate(Element elementElement) => 193 Element fetchTemplate(Element elementElement) =>
217 elementElement.query('template'); 194 elementElement.query('template');
218 195
219 /** Utility function that creates a shadow root from a `<template>`. */ 196 /** Utility function that creates a shadow root from a `<template>`. */
220 ShadowRoot shadowFromTemplate(Element template) { 197 ShadowRoot shadowFromTemplate(Element template) {
221 if (template == null) return null; 198 if (template == null) return null;
222 // cache elder shadow root (if any) 199 // cache elder shadow root (if any)
223 var elderRoot = this.shadowRoot; 200 var elderRoot = this.shadowRoot;
224 // make a shadow root 201 // make a shadow root
225 var root = createShadowRoot(); 202 var root = createShadowRoot();
203
204 // Provides ability to traverse from ShadowRoot to the host.
205 // TODO(jmessery): remove once we have this ability on the DOM.
206 _shadowHost[root] = this;
207
226 // migrate flag(s)( 208 // migrate flag(s)(
227 root.applyAuthorStyles = applyAuthorStyles; 209 root.applyAuthorStyles = applyAuthorStyles;
228 root.resetStyleInheritance = resetStyleInheritance; 210 root.resetStyleInheritance = resetStyleInheritance;
229 // stamp template 211 // stamp template
230 // which includes parsing and applying MDV bindings before being 212 // which includes parsing and applying MDV bindings before being
231 // inserted (to avoid {{}} in attribute values) 213 // inserted (to avoid {{}} in attribute values)
232 // e.g. to prevent <img src="images/{{icon}}"> from generating a 404. 214 // e.g. to prevent <img src="images/{{icon}}"> from generating a 404.
233 var dom = instanceTemplate(template); 215 var dom = instanceTemplate(template);
234 // append to shadow dom 216 // append to shadow dom
235 root.append(dom); 217 root.append(dom);
(...skipping 14 matching lines...) Expand all
250 } 232 }
251 233
252 /** Locate nodes with id and store references to them in [$] hash. */ 234 /** Locate nodes with id and store references to them in [$] hash. */
253 void marshalNodeReferences(ShadowRoot root) { 235 void marshalNodeReferences(ShadowRoot root) {
254 if (root == null) return; 236 if (root == null) return;
255 for (var n in root.queryAll('[id]')) { 237 for (var n in root.queryAll('[id]')) {
256 $[n.id] = n; 238 $[n.id] = n;
257 } 239 }
258 } 240 }
259 241
260 void attributeChanged(String name, String oldValue) { 242 void attributeChanged(String name, String oldValue, String newValue) {
blois 2013/10/11 22:40:12 Note that this is a new breaking change for Polyme
261 if (name != 'class' && name != 'style') { 243 if (name != 'class' && name != 'style') {
262 attributeToProperty(name, attributes[name]); 244 attributeToProperty(name, newValue);
263 } 245 }
264 } 246 }
265 247
266 // TODO(jmesserly): use stream or future here? 248 // TODO(jmesserly): use stream or future here?
267 /** 249 /**
268 * Run the `listener` callback *once* 250 * Run the `listener` callback *once*
269 * when `node` changes, or when its children or subtree changes. 251 * when `node` changes, or when its children or subtree changes.
270 * 252 *
271 * 253 *
272 * See [MutationObserver] if you want to listen to a stream of 254 * See [MutationObserver] if you want to listen to a stream of
273 * changes. 255 * changes.
274 */ 256 */
275 void onMutation(Node node, void listener(MutationObserver obs)) { 257 void onMutation(Node node, void listener(MutationObserver obs)) {
276 new MutationObserver((records, MutationObserver observer) { 258 new MutationObserver((records, MutationObserver observer) {
277 listener(observer); 259 listener(observer);
278 observer.disconnect(); 260 observer.disconnect();
279 })..observe(node, childList: true, subtree: true); 261 })..observe(node, childList: true, subtree: true);
280 } 262 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 if (property != null) { 381 if (property != null) {
400 unbind(name); 382 unbind(name);
401 // use n-way Polymer binding 383 // use n-way Polymer binding
402 var observer = bindProperty(property.simpleName, model, path); 384 var observer = bindProperty(property.simpleName, model, path);
403 // reflect bound property to attribute when binding 385 // reflect bound property to attribute when binding
404 // to ensure binding is not left on attribute if property 386 // to ensure binding is not left on attribute if property
405 // does not update due to not changing. 387 // does not update due to not changing.
406 reflectPropertyToAttribute(name); 388 reflectPropertyToAttribute(name);
407 return bindings[name] = observer; 389 return bindings[name] = observer;
408 } else { 390 } else {
409 return super.bind(name, model, path); 391 // Cannot call super.bind because of
392 // https://code.google.com/p/dart/issues/detail?id=13156
393 // https://code.google.com/p/dart/issues/detail?id=12456
394 return TemplateElement.mdvPackage(this).bind(name, model, path);
410 } 395 }
411 } 396 }
412 397
413 void asyncUnbindAll() { 398 void asyncUnbindAll() {
414 if (_unbound == true) return; 399 if (_unbound == true) return;
415 _unbindLog.info('[$localName] asyncUnbindAll'); 400 _unbindLog.info('[$localName] asyncUnbindAll');
416 _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0)); 401 _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0));
417 } 402 }
418 403
419 void unbindAll() { 404 void unbindAll() {
420 if (_unbound == true) return; 405 if (_unbound == true) return;
421 406
422 unbindAllProperties(); 407 unbindAllProperties();
423 super.unbindAll(); 408 // Cannot call super.bind because of
409 // https://code.google.com/p/dart/issues/detail?id=13156
410 // https://code.google.com/p/dart/issues/detail?id=12456
411 TemplateElement.mdvPackage(this).unbindAll();
412
424 _unbindNodeTree(shadowRoot); 413 _unbindNodeTree(shadowRoot);
425 // TODO(sjmiles): must also unbind inherited shadow roots 414 // TODO(sjmiles): must also unbind inherited shadow roots
426 _unbound = true; 415 _unbound = true;
427 } 416 }
428 417
429 void cancelUnbindAll({bool preventCascade}) { 418 void cancelUnbindAll({bool preventCascade}) {
430 if (_unbound == true) { 419 if (_unbound == true) {
431 _unbindLog.warning( 420 _unbindLog.warning(
432 '[$localName] already unbound, cannot cancel unbindAll'); 421 '[$localName] already unbound, cannot cancel unbindAll');
433 return; 422 return;
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 } 658 }
670 self.invoke(methodName, args); 659 self.invoke(methodName, args);
671 660
672 if (log) _eventsLog.info('<<< [$localName]: dispatch $methodName'); 661 if (log) _eventsLog.info('<<< [$localName]: dispatch $methodName');
673 662
674 // TODO(jmesserly): workaround for HTML events not supporting zones. 663 // TODO(jmesserly): workaround for HTML events not supporting zones.
675 performMicrotaskCheckpoint(); 664 performMicrotaskCheckpoint();
676 } 665 }
677 666
678 void instanceEventListener(Event event) { 667 void instanceEventListener(Event event) {
679 _listenLocal(host, event); 668 _listenLocal(this, event);
680 } 669 }
681 670
682 // TODO(sjmiles): much of the below privatized only because of the vague 671 // TODO(sjmiles): much of the below privatized only because of the vague
683 // notion this code is too fiddly and we need to revisit the core feature 672 // notion this code is too fiddly and we need to revisit the core feature
684 void _listenLocal(Element host, Event event) { 673 void _listenLocal(Polymer host, Event event) {
685 // TODO(jmesserly): do we need this check? It was using cancelBubble, see: 674 // TODO(jmesserly): do we need this check? It was using cancelBubble, see:
686 // https://github.com/Polymer/polymer/issues/292 675 // https://github.com/Polymer/polymer/issues/292
687 if (!event.bubbles) return; 676 if (!event.bubbles) return;
688 677
689 bool log = _eventsLog.isLoggable(Level.INFO); 678 bool log = _eventsLog.isLoggable(Level.INFO);
690 if (log) _eventsLog.info('>>> [$localName]: listenLocal [${event.type}]'); 679 if (log) _eventsLog.info('>>> [$localName]: listenLocal [${event.type}]');
691 680
692 final eventOn = '$_EVENT_PREFIX${_eventNameFromType(event.type)}'; 681 final eventOn = '$_EVENT_PREFIX${_eventNameFromType(event.type)}';
693 if (event.path == null) { 682 if (event.path == null) {
694 _listenLocalNoEventPath(host, event, eventOn); 683 _listenLocalNoEventPath(host, event, eventOn);
695 } else { 684 } else {
696 _listenLocalEventPath(host, event, eventOn); 685 _listenLocalEventPath(host, event, eventOn);
697 } 686 }
698 687
699 if (log) _eventsLog.info('<<< [$localName]: listenLocal [${event.type}]'); 688 if (log) _eventsLog.info('<<< [$localName]: listenLocal [${event.type}]');
700 } 689 }
701 690
702 static void _listenLocalEventPath(Element host, Event event, String eventOn) { 691 static void _listenLocalEventPath(Polymer host, Event event, String eventOn) {
703 var c = null; 692 var c = null;
704 for (var target in event.path) { 693 for (var target in event.path) {
705 // if we hit host, stop 694 // if we hit host, stop
706 if (identical(target, host)) return; 695 if (identical(target, host)) return;
707 696
708 // find a controller for the target, unless we already found `host` 697 // find a controller for the target, unless we already found `host`
709 // as a controller 698 // as a controller
710 c = identical(c, host) ? c : _findController(target); 699 c = identical(c, host) ? c : _findController(target);
711 700
712 // if we have a controller, dispatch the event, and stop if the handler 701 // if we have a controller, dispatch the event, and stop if the handler
713 // returns true 702 // returns true
714 if (c != null && _handleEvent(c, target, event, eventOn)) { 703 if (c != null && _handleEvent(c, target, event, eventOn)) {
715 return; 704 return;
716 } 705 }
717 } 706 }
718 } 707 }
719 708
720 // TODO(sorvell): remove when ShadowDOM polyfill supports event path. 709 // TODO(sorvell): remove when ShadowDOM polyfill supports event path.
721 // Note that _findController will not return the expected controller when the 710 // Note that _findController will not return the expected controller when the
722 // event target is a distributed node. This is because we cannot traverse 711 // event target is a distributed node. This is because we cannot traverse
723 // from a composed node to a node in shadowRoot. 712 // from a composed node to a node in shadowRoot.
724 // This will be addressed via an event path api 713 // This will be addressed via an event path api
725 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066 714 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066
726 static void _listenLocalNoEventPath(Element host, Event event, 715 static void _listenLocalNoEventPath(Polymer host, Event event,
727 String eventOn) { 716 String eventOn) {
728 717
729 if (_eventsLog.isLoggable(Level.INFO)) { 718 if (_eventsLog.isLoggable(Level.INFO)) {
730 _eventsLog.info('event.path() not supported for ${event.type}'); 719 _eventsLog.info('event.path() not supported for ${event.type}');
731 } 720 }
732 721
733 var target = event.target; 722 var target = event.target;
734 var c = null; 723 var c = null;
735 // if we hit dirt or host, stop 724 // if we hit dirt or host, stop
736 while (target != null && target != host) { 725 while (target != null && target != host) {
737 // find a controller for target `t`, unless we already found `host` 726 // find a controller for target `t`, unless we already found `host`
738 // as a controller 727 // as a controller
739 c = identical(c, host) ? c : _findController(target); 728 c = identical(c, host) ? c : _findController(target);
740 729
741 // if we have a controller, dispatch the event, return 'true' if 730 // if we have a controller, dispatch the event, return 'true' if
742 // handler returns true 731 // handler returns true
743 if (c != null && _handleEvent(c, target, event, eventOn)) { 732 if (c != null && _handleEvent(c, target, event, eventOn)) {
744 return; 733 return;
745 } 734 }
746 target = target.parent; 735 target = target.parent;
747 } 736 }
748 } 737 }
749 738
750 // TODO(jmesserly): this won't find the correct host unless the ShadowRoot 739 // TODO(jmesserly): this won't find the correct host unless the ShadowRoot
751 // was created on a PolymerElement. 740 // was created on a PolymerElement.
752 static Element _findController(Node node) { 741 static Polymer _findController(Node node) {
753 while (node.parentNode != null) { 742 while (node.parentNode != null) {
754 node = node.parentNode; 743 node = node.parentNode;
755 } 744 }
756 return _shadowHost[node]; 745 return _shadowHost[node];
757 } 746 }
758 747
759 static bool _handleEvent(Element ctrlr, Node node, Event event, 748 static bool _handleEvent(Polymer ctrlr, Node node, Event event,
760 String eventOn) { 749 String eventOn) {
761 750
762 // Note: local events are listened only in the shadow root. This dynamic 751 // Note: local events are listened only in the shadow root. This dynamic
763 // lookup is used to distinguish determine whether the target actually has a 752 // lookup is used to distinguish determine whether the target actually has a
764 // listener, and if so, to determine lazily what's the target method. 753 // listener, and if so, to determine lazily what's the target method.
765 var name = node is Element ? (node as Element).attributes[eventOn] : null; 754 var name = node is Element ? (node as Element).attributes[eventOn] : null;
766 if (name != null && _handleIfNotHandled(node, event)) { 755 if (name != null && _handleIfNotHandled(node, event)) {
767 if (_eventsLog.isLoggable(Level.INFO)) { 756 if (_eventsLog.isLoggable(Level.INFO)) {
768 _eventsLog.info('[${ctrlr.localName}] found handler name [$name]'); 757 _eventsLog.info('[${ctrlr.localName}] found handler name [$name]');
769 } 758 }
770 var detail = event is CustomEvent ? 759 var detail = event is CustomEvent ?
771 (event as CustomEvent).detail : null; 760 (event as CustomEvent).detail : null;
772 761
773 if (node != null) { 762 if (node != null) {
774 // TODO(jmesserly): cache symbols? 763 // TODO(jmesserly): cache symbols?
775 ctrlr.xtag.dispatchMethod(new Symbol(name), [event, detail, node]); 764 ctrlr.dispatchMethod(new Symbol(name), [event, detail, node]);
776 } 765 }
777 } 766 }
778 767
779 // TODO(jmesserly): do we need this? It was using cancelBubble, see: 768 // TODO(jmesserly): do we need this? It was using cancelBubble, see:
780 // https://github.com/Polymer/polymer/issues/292 769 // https://github.com/Polymer/polymer/issues/292
781 return !event.bubbles; 770 return !event.bubbles;
782 } 771 }
783 772
784 // TODO(jmesserly): I don't understand this bit. It seems to be a duplicate 773 // TODO(jmesserly): I don't understand this bit. It seems to be a duplicate
785 // delivery prevention mechanism? 774 // delivery prevention mechanism?
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 } 915 }
927 } 916 }
928 return type; 917 return type;
929 } 918 }
930 919
931 final Logger _observeLog = new Logger('polymer.observe'); 920 final Logger _observeLog = new Logger('polymer.observe');
932 final Logger _eventsLog = new Logger('polymer.events'); 921 final Logger _eventsLog = new Logger('polymer.events');
933 final Logger _unbindLog = new Logger('polymer.unbind'); 922 final Logger _unbindLog = new Logger('polymer.unbind');
934 final Logger _bindLog = new Logger('polymer.bind'); 923 final Logger _bindLog = new Logger('polymer.bind');
935 924
936 final Expando _shadowHost = new Expando<Element>(); 925 final Expando _shadowHost = new Expando<Polymer>();
937 926
938 final Expando _eventHandledTable = new Expando<Set<Node>>(); 927 final Expando _eventHandledTable = new Expando<Set<Node>>();
928
929 /**
930 * Base class for PolymerElements deriving from HtmlElement.
931 *
932 * See [Polymer].
933 */
934 class PolymerElement extends HtmlElement with Polymer, ObservableMixin {
935 PolymerElement.created() : super.created() {
936 initialize();
937 }
938 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698