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

Side by Side Diff: lib/polymer_element.dart

Issue 22962005: Merge pull request #581 from kevmoo/polymer (Closed) Base URL: https://github.com/dart-lang/web-ui.git@polymer
Patch Set: Created 7 years, 4 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
« no previous file with comments | « lib/polymer.dart ('k') | lib/safe_html.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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:custom_element/custom_element.dart'; 11 import 'package:custom_element/custom_element.dart';
12 import 'package:mdv/mdv.dart' as mdv; 12 import 'package:fancy_syntax/syntax.dart' show FancySyntax;
13 import 'package:mdv/mdv.dart' show NodeBinding;
13 import 'package:observe/observe.dart'; 14 import 'package:observe/observe.dart';
15 import 'package:observe/src/microtask.dart';
14 16
15 import 'observe.dart';
16 import 'src/utils_observe.dart' show toCamelCase, toHyphenedName; 17 import 'src/utils_observe.dart' show toCamelCase, toHyphenedName;
17 18
18 /** 19 /**
19 * Registers a [PolymerElement]. This is similar to [registerCustomElement] 20 * Registers a [PolymerElement]. This is similar to [registerCustomElement]
20 * but it is designed to work with the `<element>` element and adds additional 21 * but it is designed to work with the `<element>` element and adds additional
21 * features. 22 * features.
22 */ 23 */
23 void registerPolymerElement(String localName, PolymerElement create()) { 24 void registerPolymerElement(String localName, PolymerElement create()) {
24 registerCustomElement(localName, () => create().._initialize(localName)); 25 registerCustomElement(localName, () => create().._initialize(localName));
25 } 26 }
26 27
27 /** 28 /**
28 * *Warning*: many features of this class are not fully implemented. 29 * *Warning*: many features of this class are not fully implemented.
29 * 30 *
30 * The base class for Polymer elements. It provides convience features on top 31 * The base class for Polymer elements. It provides convience features on top
31 * of the custom elements web standard. 32 * of the custom elements web standard.
32 * 33 *
33 * Currently it supports publishing attributes via: 34 * Currently it supports publishing attributes via:
34 * 35 *
35 * <element name="..." attributes="foo, bar, baz"> 36 * <element name="..." attributes="foo, bar, baz">
36 * 37 *
37 * Any attribute published this way can be used in a data binding expression, 38 * Any attribute published this way can be used in a data binding expression,
38 * and it should contain a corresponding DOM field. 39 * and it should contain a corresponding DOM field.
39 * 40 *
40 * *Warning*: due to dart2js mirror limititations, the mapping from HTML 41 * *Warning*: due to dart2js mirror limititations, the mapping from HTML
41 * attribute to element property is a conversion from `dash-separated-words` 42 * attribute to element property is a conversion from `dash-separated-words`
42 * to camelCase, rather than searching for a property with the same name. 43 * to camelCase, rather than searching for a property with the same name.
43 */ 44 */
44 // TODO(jmesserly): fix the dash-separated-words issue. Polymer uses lowercase. 45 // TODO(jmesserly): fix the dash-separated-words issue. Polymer uses lowercase.
45 abstract class PolymerElement extends CustomElement with _EventsMixin { 46 class PolymerElement extends CustomElement with _EventsMixin {
46 // This is a partial port of: 47 // This is a partial port of:
47 // https://github.com/Polymer/polymer/blob/stable/src/attrs.js 48 // https://github.com/Polymer/polymer/blob/stable/src/attrs.js
48 // https://github.com/Polymer/polymer/blob/stable/src/bindProperties.js 49 // https://github.com/Polymer/polymer/blob/stable/src/bindProperties.js
49 // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js 50 // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js
50 // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js 51 // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js
51 // TODO(jmesserly): we still need to port more of the functionality 52 // TODO(jmesserly): we still need to port more of the functionality
52 53
54 /// The one syntax to rule them all.
55 static BindingDelegate _fancySyntax = new FancySyntax();
56
53 // TODO(sigmund): delete. The next line is only added to avoid warnings from 57 // TODO(sigmund): delete. The next line is only added to avoid warnings from
54 // the analyzer (see http://dartbug.com/11672) 58 // the analyzer (see http://dartbug.com/11672)
55 Element get host => super.host; 59 Element get host => super.host;
56 60
57 bool get applyAuthorStyles => false; 61 bool get applyAuthorStyles => false;
58 bool get resetStyleInheritance => false; 62 bool get resetStyleInheritance => false;
59 63
60 /** 64 /**
61 * The declaration of this polymer-element, used to extract template contents 65 * The declaration of this polymer-element, used to extract template contents
62 * and other information. 66 * and other information.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 void created() { 118 void created() {
115 // TODO(jmesserly): this breaks until we get some kind of type conversion. 119 // TODO(jmesserly): this breaks until we get some kind of type conversion.
116 // _publishedAttrs.forEach((name, propObserver) { 120 // _publishedAttrs.forEach((name, propObserver) {
117 // var value = attributes[name]; 121 // var value = attributes[name];
118 // if (value != null) propObserver.value = value; 122 // if (value != null) propObserver.value = value;
119 // }); 123 // });
120 _initShadowRoot(); 124 _initShadowRoot();
121 _addHostListeners(); 125 _addHostListeners();
122 } 126 }
123 127
128 /**
129 * Creates the document fragment to use for each instance of the custom
130 * element, given the `<template>` node. By default this is equivalent to:
131 *
132 * template.createInstance(this, fancySyntax);
133 *
134 * Where fancySyntax is a singleton `FancySyntax` instance from the
135 * [fancy_syntax](https://pub.dartlang.org/packages/fancy_syntax) package.
136 *
137 * You can override this method to change the instantiation behavior of the
138 * template, for example to use a different data-binding syntax.
139 */
140 DocumentFragment instanceTemplate(Element template) =>
141 template.createInstance(this, _fancySyntax);
142
124 void _initShadowRoot() { 143 void _initShadowRoot() {
125 for (var localName in _localNames) { 144 for (var localName in _localNames) {
126 var declaration = getDeclaration(localName); 145 var declaration = getDeclaration(localName);
127 var root = createShadowRoot(localName); 146 var root = createShadowRoot(localName);
128 _addInstanceListeners(root, localName); 147 _addInstanceListeners(root, localName);
129 148
130 root.applyAuthorStyles = applyAuthorStyles; 149 root.applyAuthorStyles = applyAuthorStyles;
131 root.resetStyleInheritance = resetStyleInheritance; 150 root.resetStyleInheritance = resetStyleInheritance;
132 151
133 var templateNode = declaration.children.firstWhere( 152 var templateNode = declaration.children.firstWhere(
134 (n) => n.localName == 'template', orElse: () => null); 153 (n) => n.localName == 'template', orElse: () => null);
135 if (templateNode == null) return; 154 if (templateNode == null) return;
136 155
137 root.nodes.add(cloneTemplate(templateNode.content)); 156 // Create the contents of the element's ShadowRoot, and add them.
138 // TODO(sigmund): use fancy-syntax as the default. 157 root.nodes.add(instanceTemplate(templateNode));
139 // TODO(sigmund,jmesserly): mdv.bindModel should be async internally
140 Timer.run(() => mdv.bindModel(root, this));
141 } 158 }
142 } 159 }
143 160
144 void bind(String name, model, String path) { 161 NodeBinding createBinding(String name, model, String path) {
145 var propObserver = _publishedAttrs[name]; 162 var propObserver = _publishedAttrs[name];
146 if (propObserver != null) { 163 if (propObserver != null) {
147 unbind(name); 164 return new _PolymerBinding(this, name, model, path, propObserver);
148
149 _bindings[name] = new PathObserver(model, path).bindSync((value) {
150 propObserver.value = value;
151 });
152 return;
153 } 165 }
154 return super.bind(name, model, path); 166 return super.createBinding(name, model, path);
155 }
156
157 void unbind(String name) {
158 if (_bindings != null) {
159 var binding = _bindings.remove(name);
160 if (binding != null) {
161 binding.cancel();
162 return;
163 }
164 }
165 return super.unbind(name);
166 }
167
168 void unbindAll() {
169 for (var binding in _bindings.values) binding.cancel();
170 _bindings.clear();
171 return super.unbindAll();
172 } 167 }
173 } 168 }
174 169
170 class _PolymerBinding extends NodeBinding {
171 final PathObserver _publishedAttr;
172
173 _PolymerBinding(node, property, model, path, PathObserver this._publishedAttr)
174 : super(node, property, model, path);
175
176 void boundValueChanged(newValue) {
177 _publishedAttr.value = newValue;
178 }
179 }
180
175 /** 181 /**
176 * Polymer features to handle the syntactic sugar on-* to declare to 182 * Polymer features to handle the syntactic sugar on-* to declare to
177 * automatically map event handlers to instance methods of the [PolymerElement]. 183 * automatically map event handlers to instance methods of the [PolymerElement].
178 * This mixin is a port of: 184 * This mixin is a port of:
179 * https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js 185 * https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js
180 * https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js 186 * https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js
181 */ 187 */
182 abstract class _EventsMixin { 188 abstract class _EventsMixin {
183 // TODO(sigmund): implement the Dart equivalent of 'inheritDelegates' 189 // TODO(sigmund): implement the Dart equivalent of 'inheritDelegates'
184 // Notes about differences in the implementation below: 190 // Notes about differences in the implementation below:
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 // dartbug.com/11108). 353 // dartbug.com/11108).
348 var methodDecl = reflectClass(receiver.runtimeType).methods[method]; 354 var methodDecl = reflectClass(receiver.runtimeType).methods[method];
349 if (methodDecl != null) { 355 if (methodDecl != null) {
350 // This will either truncate the argument list or extend it with extra 356 // This will either truncate the argument list or extend it with extra
351 // null arguments, so it will match the signature. 357 // null arguments, so it will match the signature.
352 // TODO(sigmund): consider accepting optional arguments when we can tell 358 // TODO(sigmund): consider accepting optional arguments when we can tell
353 // them appart from named arguments (see http://dartbug.com/11334) 359 // them appart from named arguments (see http://dartbug.com/11334)
354 args.length = methodDecl.parameters.where((p) => !p.isOptional).length; 360 args.length = methodDecl.parameters.where((p) => !p.isOptional).length;
355 } 361 }
356 reflect(receiver).invoke(method, args); 362 reflect(receiver).invoke(method, args);
363 performMicrotaskCheckpoint();
357 } 364 }
358 365
359 bool _instanceEventListener(String eventName, Event event) { 366 bool _instanceEventListener(String eventName, Event event) {
360 if (event.bubbles) { 367 if (event.bubbles) {
361 if (event.path == null || !ShadowRoot.supported) { 368 if (event.path == null || !ShadowRoot.supported) {
362 return _listenLocalNoEventPath(eventName, event); 369 return _listenLocalNoEventPath(eventName, event);
363 } else { 370 } else {
364 return _listenLocal(eventName, event); 371 return _listenLocal(eventName, event);
365 } 372 }
366 } 373 }
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 'onKeyMessage': MediaElement.keyMessageEvent, 515 'onKeyMessage': MediaElement.keyMessageEvent,
509 'onNeedKey': MediaElement.needKeyEvent, 516 'onNeedKey': MediaElement.needKeyEvent,
510 'onWebGlContextLost': CanvasElement.webGlContextLostEvent, 517 'onWebGlContextLost': CanvasElement.webGlContextLostEvent,
511 'onWebGlContextRestored': CanvasElement.webGlContextRestoredEvent, 518 'onWebGlContextRestored': CanvasElement.webGlContextRestoredEvent,
512 'onPointerLockChange': Document.pointerLockChangeEvent, 519 'onPointerLockChange': Document.pointerLockChangeEvent,
513 'onPointerLockError': Document.pointerLockErrorEvent, 520 'onPointerLockError': Document.pointerLockErrorEvent,
514 'onReadyStateChange': Document.readyStateChangeEvent, 521 'onReadyStateChange': Document.readyStateChangeEvent,
515 'onSelectionChange': Document.selectionChangeEvent, 522 'onSelectionChange': Document.selectionChangeEvent,
516 'onSecurityPolicyViolation': Document.securityPolicyViolationEvent, 523 'onSecurityPolicyViolation': Document.securityPolicyViolationEvent,
517 }; 524 };
OLDNEW
« no previous file with comments | « lib/polymer.dart ('k') | lib/safe_html.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698