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

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

Issue 180373003: [polymer] switch comment style (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 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 /// 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: 8 ///
9 * 9 /// class MyPlaybackElement extends PolymerElement {
10 * class MyPlaybackElement extends PolymerElement { 10 /// // This will be available as an HTML attribute, for example:
11 * // This will be available as an HTML attribute, for example: 11 /// // <my-playback volume="11">
12 * // <my-playback volume="11"> 12 /// @published double volume;
13 * @published double volume; 13 /// }
14 * }
15 */
16 const published = const PublishedProperty(); 14 const published = const PublishedProperty();
17 15
18 /** An annotation used to publish a field as an attribute. See [published]. */ 16 /// An annotation used to publish a field as an attribute. See [published].
19 class PublishedProperty extends ObservableProperty { 17 class PublishedProperty extends ObservableProperty {
20 const PublishedProperty(); 18 const PublishedProperty();
21 } 19 }
22 20
23 /** 21 /// Use this type to observe a property and have the method be called when it
24 * Use this type to observe a property and have the method be called when it 22 /// changes. For example:
25 * changes. For example: 23 ///
26 * 24 /// @ObserveProperty('foo.bar baz qux')
27 * @ObserveProperty('foo.bar baz qux') 25 /// validate() {
28 * validate() { 26 /// // use this.foo.bar, this.baz, and this.qux in validation
29 * // use this.foo.bar, this.baz, and this.qux in validation 27 /// ...
30 * ... 28 /// }
31 * } 29 ///
32 * 30 /// Note that you can observe a property path, and more than a single property
33 * Note that you can observe a property path, and more than a single property 31 /// can be specified in a space-delimited list or as a constant List.
34 * can be specified in a space-delimited list or as a constant List.
35 */
36 class ObserveProperty { 32 class ObserveProperty {
37 final _names; 33 final _names;
38 34
39 List<String> get names { 35 List<String> get names {
40 var n = _names; 36 var n = _names;
41 // TODO(jmesserly): the bogus '$n' is to workaround a dart2js bug, otherwise 37 // TODO(jmesserly): the bogus '$n' is to workaround a dart2js bug, otherwise
42 // it generates an incorrect call site. 38 // it generates an incorrect call site.
43 if (n is String) return '$n'.split(' '); 39 if (n is String) return '$n'.split(' ');
44 if (n is! Iterable) { 40 if (n is! Iterable) {
45 throw new UnsupportedError('ObserveProperty takes either an Iterable of ' 41 throw new UnsupportedError('ObserveProperty takes either an Iterable of '
46 'names, or a space separated String, instead of `$n`.'); 42 'names, or a space separated String, instead of `$n`.');
47 } 43 }
48 return n; 44 return n;
49 } 45 }
50 46
51 const ObserveProperty(this._names); 47 const ObserveProperty(this._names);
52 } 48 }
53 49
54 /** 50 /// The mixin class for Polymer elements. It provides convenience features on
55 * The mixin class for Polymer elements. It provides convenience features on top 51 /// top of the custom elements web standard.
56 * of the custom elements web standard. 52 ///
57 * 53 /// If this class is used as a mixin,
58 * If this class is used as a mixin, 54 /// you must call `polymerCreated()` from the body of your constructor.
59 * you must call `polymerCreated()` from the body of your constructor.
60 */
61 abstract class Polymer implements Element, Observable, NodeBindExtension { 55 abstract class Polymer implements Element, Observable, NodeBindExtension {
62 // Fully ported from revision: 56 // Fully ported from revision:
63 // https://github.com/Polymer/polymer/blob/37eea00e13b9f86ab21c85a955585e8e423 7e3d2 57 // https://github.com/Polymer/polymer/blob/37eea00e13b9f86ab21c85a955585e8e423 7e3d2
64 // 58 //
65 // src/boot.js (static APIs on "Polymer" object) 59 // src/boot.js (static APIs on "Polymer" object)
66 // src/instance/attributes.js 60 // src/instance/attributes.js
67 // src/instance/base.js 61 // src/instance/base.js
68 // src/instance/events.js 62 // src/instance/events.js
69 // src/instance/mdv.js 63 // src/instance/mdv.js
70 // src/instance/properties.js 64 // src/instance/properties.js
71 // src/instance/style.js 65 // src/instance/style.js
72 // src/instance/utils.js 66 // src/instance/utils.js
73 67
74 // TODO(jmesserly): should this really be public? 68 // TODO(jmesserly): should this really be public?
75 /** Regular expression that matches data-bindings. */ 69 /// Regular expression that matches data-bindings.
76 static final bindPattern = new RegExp(r'\{\{([^{}]*)}}'); 70 static final bindPattern = new RegExp(r'\{\{([^{}]*)}}');
77 71
78 /** 72 /// Like [document.register] but for Polymer elements.
79 * Like [document.register] but for Polymer elements. 73 ///
80 * 74 /// Use the [name] to specify custom elment's tag name, for example:
81 * Use the [name] to specify custom elment's tag name, for example: 75 /// "fancy-button" if the tag is used as `<fancy-button>`.
82 * "fancy-button" if the tag is used as `<fancy-button>`. 76 ///
83 * 77 /// The [type] is the type to construct. If not supplied, it defaults to
84 * The [type] is the type to construct. If not supplied, it defaults to 78 /// [PolymerElement].
85 * [PolymerElement].
86 */
87 // NOTE: this is called "element" in src/declaration/polymer-element.js, and 79 // NOTE: this is called "element" in src/declaration/polymer-element.js, and
88 // exported as "Polymer". 80 // exported as "Polymer".
89 static void register(String name, [Type type]) { 81 static void register(String name, [Type type]) {
90 //console.log('registering [' + name + ']'); 82 //console.log('registering [' + name + ']');
91 if (type == null) type = PolymerElement; 83 if (type == null) type = PolymerElement;
92 84
93 _typesByName[name] = type; 85 _typesByName[name] = type;
94 // notify the registrar waiting for 'name', if any 86 // notify the registrar waiting for 'name', if any
95 _notifyType(name); 87 _notifyType(name);
96 } 88 }
97 89
98 /// The one syntax to rule them all. 90 /// The one syntax to rule them all.
99 static final BindingDelegate _polymerSyntax = 91 static final BindingDelegate _polymerSyntax =
100 new _PolymerExpressionsWithEventDelegate(); 92 new _PolymerExpressionsWithEventDelegate();
101 93
102 static int _preparingElements = 0; 94 static int _preparingElements = 0;
103 95
104 static final Completer _ready = new Completer(); 96 static final Completer _ready = new Completer();
105 97
106 /** 98 /// Future indicating that the Polymer library has been loaded and is ready
107 * Future indicating that the Polymer library has been loaded and is ready 99 /// for use.
108 * for use.
109 */
110 static Future get onReady => _ready.future; 100 static Future get onReady => _ready.future;
111 101
112 PolymerDeclaration _declaration; 102 PolymerDeclaration _declaration;
113 103
114 /** The most derived `<polymer-element>` declaration for this element. */ 104 /// The most derived `<polymer-element>` declaration for this element.
115 PolymerDeclaration get declaration => _declaration; 105 PolymerDeclaration get declaration => _declaration;
116 106
117 Map<String, StreamSubscription> _observers; 107 Map<String, StreamSubscription> _observers;
118 bool _unbound; // lazy-initialized 108 bool _unbound; // lazy-initialized
119 _Job _unbindAllJob; 109 _Job _unbindAllJob;
120 110
121 CompoundObserver _propertyObserver; 111 CompoundObserver _propertyObserver;
122 112
123 bool get _elementPrepared => _declaration != null; 113 bool get _elementPrepared => _declaration != null;
124 114
125 bool get applyAuthorStyles => false; 115 bool get applyAuthorStyles => false;
126 bool get resetStyleInheritance => false; 116 bool get resetStyleInheritance => false;
127 bool get alwaysPrepare => false; 117 bool get alwaysPrepare => false;
128 bool get preventDispose => false; 118 bool get preventDispose => false;
129 119
130 BindingDelegate syntax = _polymerSyntax; 120 BindingDelegate syntax = _polymerSyntax;
131 121
132 /** 122 /// Shadow roots created by [parseElement]. See [getShadowRoot].
133 * Shadow roots created by [parseElement]. See [getShadowRoot].
134 */
135 final _shadowRoots = new HashMap<String, ShadowRoot>(); 123 final _shadowRoots = new HashMap<String, ShadowRoot>();
136 124
137 /** Map of items in the shadow root(s) by their [Element.id]. */ 125 /// Map of items in the shadow root(s) by their [Element.id].
138 // TODO(jmesserly): various issues: 126 // TODO(jmesserly): various issues:
139 // * wrap in UnmodifiableMapView? 127 // * wrap in UnmodifiableMapView?
140 // * should we have an object that implements noSuchMethod? 128 // * should we have an object that implements noSuchMethod?
141 // * should the map have a key order (e.g. LinkedHash or SplayTree)? 129 // * should the map have a key order (e.g. LinkedHash or SplayTree)?
142 // * should this be a live list? Polymer doesn't, maybe due to JS limitations? 130 // * should this be a live list? Polymer doesn't, maybe due to JS limitations?
143 // Note: this is observable to support $['someId'] being used in templates. 131 // Note: this is observable to support $['someId'] being used in templates.
144 // The template is stamped before $ is populated, so we need observation if 132 // The template is stamped before $ is populated, so we need observation if
145 // we want it to be usable in bindings. 133 // we want it to be usable in bindings.
146 @reflectable final Map<String, Element> $ = 134 @reflectable final Map<String, Element> $ =
147 new ObservableMap<String, Element>(); 135 new ObservableMap<String, Element>();
148 136
149 /** 137 /// Gets the shadow root associated with the corresponding custom element.
150 * Gets the shadow root associated with the corresponding custom element. 138 ///
151 * 139 /// This is identical to [shadowRoot], unless there are multiple levels of
152 * This is identical to [shadowRoot], unless there are multiple levels of 140 /// inheritance and they each have their own shadow root. For example,
153 * inheritance and they each have their own shadow root. For example, 141 /// this can happen if the base class and subclass both have `<template>` tags
154 * this can happen if the base class and subclass both have `<template>` tags 142 /// in their `<polymer-element>` tags.
155 * in their `<polymer-element>` tags.
156 */
157 // TODO(jmesserly): Polymer does not have this feature. Reconcile. 143 // TODO(jmesserly): Polymer does not have this feature. Reconcile.
158 ShadowRoot getShadowRoot(String customTagName) => _shadowRoots[customTagName]; 144 ShadowRoot getShadowRoot(String customTagName) => _shadowRoots[customTagName];
159 145
160 /** 146 /// If this class is used as a mixin, this method must be called from inside
161 * If this class is used as a mixin, this method must be called from inside 147 /// of the `created()` constructor.
162 * of the `created()` constructor. 148 ///
163 * 149 /// If this class is a superclass, calling `super.created()` is sufficient.
164 * If this class is a superclass, calling `super.created()` is sufficient.
165 */
166 void polymerCreated() { 150 void polymerCreated() {
167 if (this.ownerDocument.window != null || alwaysPrepare || 151 if (this.ownerDocument.window != null || alwaysPrepare ||
168 _preparingElements > 0) { 152 _preparingElements > 0) {
169 prepareElement(); 153 prepareElement();
170 } 154 }
171 } 155 }
172 156
173 /** Retrieves the custom element name by inspecting the host node. */ 157 /// Retrieves the custom element name by inspecting the host node.
174 String get _customTagName { 158 String get _customTagName {
175 var isAttr = attributes['is']; 159 var isAttr = attributes['is'];
176 return (isAttr == null || isAttr == '') ? localName : isAttr; 160 return (isAttr == null || isAttr == '') ? localName : isAttr;
177 } 161 }
178 162
179 void prepareElement() { 163 void prepareElement() {
180 // Dart note: get the _declaration, which also marks _elementPrepared 164 // Dart note: get the _declaration, which also marks _elementPrepared
181 _declaration = _getDeclaration(_customTagName); 165 _declaration = _getDeclaration(_customTagName);
182 // do this first so we can observe changes during initialization 166 // do this first so we can observe changes during initialization
183 observeProperties(); 167 observeProperties();
184 // install boilerplate attributes 168 // install boilerplate attributes
185 copyInstanceAttributes(); 169 copyInstanceAttributes();
186 // process input attributes 170 // process input attributes
187 takeAttributes(); 171 takeAttributes();
188 // add event listeners 172 // add event listeners
189 addHostListeners(); 173 addHostListeners();
190 // guarantees that while preparing, any 174 // guarantees that while preparing, any
191 // sub-elements are also prepared 175 // sub-elements are also prepared
192 _preparingElements++; 176 _preparingElements++;
193 // process declarative resources 177 // process declarative resources
194 parseDeclarations(_declaration); 178 parseDeclarations(_declaration);
195 // decrement semaphore 179 // decrement semaphore
196 _preparingElements--; 180 _preparingElements--;
197 // user entry point 181 // user entry point
198 ready(); 182 ready();
199 } 183 }
200 184
201 /** Called when [prepareElement] is finished. */ 185 /// Called when [prepareElement] is finished.
202 void ready() {} 186 void ready() {}
203 187
204 void enteredView() { 188 void enteredView() {
205 if (!_elementPrepared) { 189 if (!_elementPrepared) {
206 prepareElement(); 190 prepareElement();
207 } 191 }
208 cancelUnbindAll(preventCascade: true); 192 cancelUnbindAll(preventCascade: true);
209 } 193 }
210 194
211 void leftView() { 195 void leftView() {
212 if (!preventDispose) asyncUnbindAll(); 196 if (!preventDispose) asyncUnbindAll();
213 } 197 }
214 198
215 /** Recursive ancestral <element> initialization, oldest first. */ 199 /// Recursive ancestral <element> initialization, oldest first.
216 void parseDeclarations(PolymerDeclaration declaration) { 200 void parseDeclarations(PolymerDeclaration declaration) {
217 if (declaration != null) { 201 if (declaration != null) {
218 parseDeclarations(declaration.superDeclaration); 202 parseDeclarations(declaration.superDeclaration);
219 parseDeclaration(declaration); 203 parseDeclaration(declaration);
220 } 204 }
221 } 205 }
222 206
223 /** 207 /// Parse input `<polymer-element>` as needed, override for custom behavior.
224 * Parse input `<polymer-element>` as needed, override for custom behavior.
225 */
226 void parseDeclaration(Element elementElement) { 208 void parseDeclaration(Element elementElement) {
227 var template = fetchTemplate(elementElement); 209 var template = fetchTemplate(elementElement);
228 210
229 var root = null; 211 var root = null;
230 if (template != null) { 212 if (template != null) {
231 if (_declaration.attributes.containsKey('lightdom')) { 213 if (_declaration.attributes.containsKey('lightdom')) {
232 lightFromTemplate(template); 214 lightFromTemplate(template);
233 } else { 215 } else {
234 root = shadowFromTemplate(template); 216 root = shadowFromTemplate(template);
235 } 217 }
236 } 218 }
237 219
238 // Dart note: the following code is to support the getShadowRoot method. 220 // Dart note: the following code is to support the getShadowRoot method.
239 if (root is! ShadowRoot) return; 221 if (root is! ShadowRoot) return;
240 222
241 var name = elementElement.attributes['name']; 223 var name = elementElement.attributes['name'];
242 if (name == null) return; 224 if (name == null) return;
243 _shadowRoots[name] = root; 225 _shadowRoots[name] = root;
244 } 226 }
245 227
246 /** 228 /// Return a shadow-root template (if desired), override for custom behavior.
247 * Return a shadow-root template (if desired), override for custom behavior.
248 */
249 Element fetchTemplate(Element elementElement) => 229 Element fetchTemplate(Element elementElement) =>
250 elementElement.querySelector('template'); 230 elementElement.querySelector('template');
251 231
252 /** 232 /// Utility function that stamps a `<template>` into light-dom.
253 * Utility function that stamps a `<template>` into light-dom.
254 */
255 Node lightFromTemplate(Element template) { 233 Node lightFromTemplate(Element template) {
256 if (template == null) return null; 234 if (template == null) return null;
257 // stamp template 235 // stamp template
258 // which includes parsing and applying MDV bindings before being 236 // which includes parsing and applying MDV bindings before being
259 // inserted (to avoid {{}} in attribute values) 237 // inserted (to avoid {{}} in attribute values)
260 // e.g. to prevent <img src="images/{{icon}}"> from generating a 404. 238 // e.g. to prevent <img src="images/{{icon}}"> from generating a 404.
261 var dom = instanceTemplate(template); 239 var dom = instanceTemplate(template);
262 // append to shadow dom 240 // append to shadow dom
263 append(dom); 241 append(dom);
264 // perform post-construction initialization tasks on shadow root 242 // perform post-construction initialization tasks on shadow root
265 shadowRootReady(this, template); 243 shadowRootReady(this, template);
266 // return the created shadow root 244 // return the created shadow root
267 return dom; 245 return dom;
268 } 246 }
269 247
270 /** 248 /// Utility function that creates a shadow root from a `<template>`.
271 * Utility function that creates a shadow root from a `<template>`. 249 ///
272 * 250 /// The base implementation will return a [ShadowRoot], but you can replace it
273 * The base implementation will return a [ShadowRoot], but you can replace it 251 /// with your own code and skip ShadowRoot creation. In that case, you should
274 * with your own code and skip ShadowRoot creation. In that case, you should 252 /// return `null`.
275 * return `null`. 253 ///
276 * 254 /// In your overridden method, you can use [instanceTemplate] to stamp the
277 * In your overridden method, you can use [instanceTemplate] to stamp the 255 /// template and initialize data binding, and [shadowRootReady] to intialize
278 * template and initialize data binding, and [shadowRootReady] to intialize 256 /// other Polymer features like event handlers. It is fine to call
279 * other Polymer features like event handlers. It is fine to call 257 /// shadowRootReady with a node other than a ShadowRoot such as with `this`.
280 * shadowRootReady with a node something other than a ShadowRoot; for example,
281 * with this Node.
282 */
283 ShadowRoot shadowFromTemplate(Element template) { 258 ShadowRoot shadowFromTemplate(Element template) {
284 if (template == null) return null; 259 if (template == null) return null;
285 // cache elder shadow root (if any) 260 // cache elder shadow root (if any)
286 var elderRoot = this.shadowRoot; 261 var elderRoot = this.shadowRoot;
287 // make a shadow root 262 // make a shadow root
288 var root = createShadowRoot(); 263 var root = createShadowRoot();
289 264
290 // Provides ability to traverse from ShadowRoot to the host. 265 // Provides ability to traverse from ShadowRoot to the host.
291 // TODO(jmessery): remove once we have this ability on the DOM. 266 // TODO(jmessery): remove once we have this ability on the DOM.
292 _shadowHost[root] = this; 267 _shadowHost[root] = this;
(...skipping 15 matching lines...) Expand all
308 } 283 }
309 284
310 void shadowRootReady(Node root, Element template) { 285 void shadowRootReady(Node root, Element template) {
311 // locate nodes with id and store references to them in this.$ hash 286 // locate nodes with id and store references to them in this.$ hash
312 marshalNodeReferences(root); 287 marshalNodeReferences(root);
313 // TODO(jmesserly): port this 288 // TODO(jmesserly): port this
314 // set up pointer gestures 289 // set up pointer gestures
315 // PointerGestures.register(root); 290 // PointerGestures.register(root);
316 } 291 }
317 292
318 /** Locate nodes with id and store references to them in [$] hash. */ 293 /// Locate nodes with id and store references to them in [$] hash.
319 void marshalNodeReferences(Node root) { 294 void marshalNodeReferences(Node root) {
320 if (root == null) return; 295 if (root == null) return;
321 for (var n in (root as dynamic).querySelectorAll('[id]')) { 296 for (var n in (root as dynamic).querySelectorAll('[id]')) {
322 $[n.id] = n; 297 $[n.id] = n;
323 } 298 }
324 } 299 }
325 300
326 void attributeChanged(String name, String oldValue, String newValue) { 301 void attributeChanged(String name, String oldValue, String newValue) {
327 if (name != 'class' && name != 'style') { 302 if (name != 'class' && name != 'style') {
328 attributeToProperty(name, newValue); 303 attributeToProperty(name, newValue);
329 } 304 }
330 } 305 }
331 306
332 // TODO(jmesserly): this could be a top level method. 307 // TODO(jmesserly): this could be a top level method.
333 /** 308 /// Returns a future when `node` changes, or when its children or subtree
334 * Returns a future when `node` changes, or when its children or subtree 309 /// changes.
335 * changes. 310 ///
336 * 311 /// Use [MutationObserver] if you want to listen to a stream of changes.
337 * Use [MutationObserver] if you want to listen to a stream of changes.
338 */
339 Future<List<MutationRecord>> onMutation(Node node) { 312 Future<List<MutationRecord>> onMutation(Node node) {
340 var completer = new Completer(); 313 var completer = new Completer();
341 new MutationObserver((mutations, observer) { 314 new MutationObserver((mutations, observer) {
342 observer.disconnect(); 315 observer.disconnect();
343 completer.complete(mutations); 316 completer.complete(mutations);
344 })..observe(node, childList: true, subtree: true); 317 })..observe(node, childList: true, subtree: true);
345 return completer.future; 318 return completer.future;
346 } 319 }
347 320
348 void copyInstanceAttributes() { 321 void copyInstanceAttributes() {
349 _declaration._instanceAttributes.forEach((name, value) { 322 _declaration._instanceAttributes.forEach((name, value) {
350 attributes.putIfAbsent(name, () => value); 323 attributes.putIfAbsent(name, () => value);
351 }); 324 });
352 } 325 }
353 326
354 void takeAttributes() { 327 void takeAttributes() {
355 if (_declaration._publishLC == null) return; 328 if (_declaration._publishLC == null) return;
356 attributes.forEach(attributeToProperty); 329 attributes.forEach(attributeToProperty);
357 } 330 }
358 331
359 /** 332 /// If attribute [name] is mapped to a property, deserialize
360 * If attribute [name] is mapped to a property, deserialize 333 /// [value] into that property.
361 * [value] into that property.
362 */
363 void attributeToProperty(String name, String value) { 334 void attributeToProperty(String name, String value) {
364 // try to match this attribute to a property (attributes are 335 // try to match this attribute to a property (attributes are
365 // all lower-case, so this is case-insensitive search) 336 // all lower-case, so this is case-insensitive search)
366 var decl = propertyForAttribute(name); 337 var decl = propertyForAttribute(name);
367 if (decl == null) return; 338 if (decl == null) return;
368 339
369 // filter out 'mustached' values, these are to be 340 // filter out 'mustached' values, these are to be
370 // replaced with bound-data and are not yet values 341 // replaced with bound-data and are not yet values
371 // themselves. 342 // themselves.
372 if (value == null || value.contains(Polymer.bindPattern)) return; 343 if (value == null || value.contains(Polymer.bindPattern)) return;
373 344
374 final currentValue = smoke.read(this, decl.name); 345 final currentValue = smoke.read(this, decl.name);
375 346
376 // deserialize Boolean or Number values from attribute 347 // deserialize Boolean or Number values from attribute
377 var type = decl.type; 348 var type = decl.type;
378 if ((type == Object || type == dynamic) && currentValue != null) { 349 if ((type == Object || type == dynamic) && currentValue != null) {
379 // Attempt to infer field type from the current value. 350 // Attempt to infer field type from the current value.
380 type = currentValue.runtimeType; 351 type = currentValue.runtimeType;
381 } 352 }
382 final newValue = deserializeValue(value, currentValue, type); 353 final newValue = deserializeValue(value, currentValue, type);
383 354
384 // only act if the value has changed 355 // only act if the value has changed
385 if (!identical(newValue, currentValue)) { 356 if (!identical(newValue, currentValue)) {
386 // install new value (has side-effects) 357 // install new value (has side-effects)
387 smoke.write(this, decl.name, newValue); 358 smoke.write(this, decl.name, newValue);
388 } 359 }
389 } 360 }
390 361
391 /** Return the published property matching name, or null. */ 362 /// Return the published property matching name, or null.
392 // TODO(jmesserly): should we just return Symbol here? 363 // TODO(jmesserly): should we just return Symbol here?
393 smoke.Declaration propertyForAttribute(String name) { 364 smoke.Declaration propertyForAttribute(String name) {
394 final publishLC = _declaration._publishLC; 365 final publishLC = _declaration._publishLC;
395 if (publishLC == null) return null; 366 if (publishLC == null) return null;
396 //console.log('propertyForAttribute:', name, 'matches', match); 367 //console.log('propertyForAttribute:', name, 'matches', match);
397 return publishLC[name]; 368 return publishLC[name];
398 } 369 }
399 370
400 /** 371 /// Convert representation of [value] based on [type] and [currentValue].
401 * Convert representation of [value] based on [type] and [currentValue].
402 */
403 Object deserializeValue(String value, Object currentValue, Type type) => 372 Object deserializeValue(String value, Object currentValue, Type type) =>
404 deserialize.deserializeValue(value, currentValue, type); 373 deserialize.deserializeValue(value, currentValue, type);
405 374
406 String serializeValue(Object value) { 375 String serializeValue(Object value) {
407 if (value == null) return null; 376 if (value == null) return null;
408 377
409 if (value is bool) { 378 if (value is bool) {
410 return _toBoolean(value) ? '' : null; 379 return _toBoolean(value) ? '' : null;
411 } else if (value is String || value is num) { 380 } else if (value is String || value is num) {
412 return '$value'; 381 return '$value';
(...skipping 14 matching lines...) Expand all
427 // TODO(sorvell): we should remove attr for all properties 396 // TODO(sorvell): we should remove attr for all properties
428 // that have undefined serialization; however, we will need to 397 // that have undefined serialization; however, we will need to
429 // refine the attr reflection system to achieve this; pica, for example, 398 // refine the attr reflection system to achieve this; pica, for example,
430 // relies on having inferredType object properties not removed as 399 // relies on having inferredType object properties not removed as
431 // attrs. 400 // attrs.
432 } else if (propValue is bool) { 401 } else if (propValue is bool) {
433 attributes.remove('$path'); 402 attributes.remove('$path');
434 } 403 }
435 } 404 }
436 405
437 /** 406 /// Creates the document fragment to use for each instance of the custom
438 * Creates the document fragment to use for each instance of the custom 407 /// element, given the `<template>` node. By default this is equivalent to:
439 * element, given the `<template>` node. By default this is equivalent to: 408 ///
440 * 409 /// templateBind(template).createInstance(this, polymerSyntax);
441 * templateBind(template).createInstance(this, polymerSyntax); 410 ///
442 * 411 /// Where polymerSyntax is a singleton `PolymerExpressions` instance from the
443 * Where polymerSyntax is a singleton `PolymerExpressions` instance from the 412 /// [polymer_expressions](https://pub.dartlang.org/packages/polymer_expression s)
444 * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions ) 413 /// package.
445 * package. 414 ///
446 * 415 /// You can override this method to change the instantiation behavior of the
447 * You can override this method to change the instantiation behavior of the 416 /// template, for example to use a different data-binding syntax.
448 * template, for example to use a different data-binding syntax.
449 */
450 DocumentFragment instanceTemplate(Element template) => 417 DocumentFragment instanceTemplate(Element template) =>
451 templateBind(template).createInstance(this, syntax); 418 templateBind(template).createInstance(this, syntax);
452 419
453 // TODO(jmesserly): Polymer does not seem to implement the oneTime flag 420 // TODO(jmesserly): Polymer does not seem to implement the oneTime flag
454 // correctly. File bug. 421 // correctly. File bug.
455 Bindable bind(String name, Bindable bindable, {bool oneTime: false}) { 422 Bindable bind(String name, Bindable bindable, {bool oneTime: false}) {
456 // note: binding is a prepare signal. This allows us to be sure that any 423 // note: binding is a prepare signal. This allows us to be sure that any
457 // property changes that occur as a result of binding will be observed. 424 // property changes that occur as a result of binding will be observed.
458 if (!_elementPrepared) prepareElement(); 425 if (!_elementPrepared) prepareElement();
459 426
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 501
535 static void _forNodeTree(Node node, void callback(Node node)) { 502 static void _forNodeTree(Node node, void callback(Node node)) {
536 if (node == null) return; 503 if (node == null) return;
537 504
538 callback(node); 505 callback(node);
539 for (var child = node.firstChild; child != null; child = child.nextNode) { 506 for (var child = node.firstChild; child != null; child = child.nextNode) {
540 _forNodeTree(child, callback); 507 _forNodeTree(child, callback);
541 } 508 }
542 } 509 }
543 510
544 /** Set up property observers. */ 511 /// Set up property observers.
545 void observeProperties() { 512 void observeProperties() {
546 final observe = _declaration._observe; 513 final observe = _declaration._observe;
547 final publish = _declaration._publish; 514 final publish = _declaration._publish;
548 515
549 // TODO(jmesserly): workaround for a dart2js compiler bug 516 // TODO(jmesserly): workaround for a dart2js compiler bug
550 bool hasObserved = observe != null; 517 bool hasObserved = observe != null;
551 518
552 if (hasObserved || publish != null) { 519 if (hasObserved || publish != null) {
553 var o = _propertyObserver = new CompoundObserver(); 520 var o = _propertyObserver = new CompoundObserver();
554 if (hasObserved) { 521 if (hasObserved) {
(...skipping 11 matching lines...) Expand all
566 if (!hasObserved || !observe.containsKey(path)) { 533 if (!hasObserved || !observe.containsKey(path)) {
567 o.addPath(this, path); 534 o.addPath(this, path);
568 } 535 }
569 } 536 }
570 } 537 }
571 o.open(notifyPropertyChanges); 538 o.open(notifyPropertyChanges);
572 } 539 }
573 } 540 }
574 541
575 542
576 /** Responds to property changes on this element. */ 543 /// Responds to property changes on this element.
577 void notifyPropertyChanges(List newValues, Map oldValues, List paths) { 544 void notifyPropertyChanges(List newValues, Map oldValues, List paths) {
578 final observe = _declaration._observe; 545 final observe = _declaration._observe;
579 final publish = _declaration._publish; 546 final publish = _declaration._publish;
580 final called = new HashSet(); 547 final called = new HashSet();
581 548
582 oldValues.forEach((i, oldValue) { 549 oldValues.forEach((i, oldValue) {
583 // note: paths is of form [object, path, object, path] 550 // note: paths is of form [object, path, object, path]
584 var path = paths[2 * i + 1]; 551 var path = paths[2 * i + 1];
585 if (publish != null && publish.containsKey(path)) { 552 if (publish != null && publish.containsKey(path)) {
586 reflectPropertyToAttribute(path); 553 reflectPropertyToAttribute(path);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 bool unbindProperty(String name) => unregisterObserver(name); 605 bool unbindProperty(String name) => unregisterObserver(name);
639 606
640 void unbindAllProperties() { 607 void unbindAllProperties() {
641 if (_propertyObserver != null) { 608 if (_propertyObserver != null) {
642 _propertyObserver.close(); 609 _propertyObserver.close();
643 _propertyObserver = null; 610 _propertyObserver = null;
644 } 611 }
645 unregisterObservers(); 612 unregisterObservers();
646 } 613 }
647 614
648 /** Bookkeeping observers for memory management. */ 615 /// Bookkeeping observers for memory management.
649 void registerObserver(String name, StreamSubscription sub) { 616 void registerObserver(String name, StreamSubscription sub) {
650 if (_observers == null) { 617 if (_observers == null) {
651 _observers = new Map<String, StreamSubscription>(); 618 _observers = new Map<String, StreamSubscription>();
652 } 619 }
653 _observers[name] = sub; 620 _observers[name] = sub;
654 } 621 }
655 622
656 bool unregisterObserver(String name) { 623 bool unregisterObserver(String name) {
657 var sub = _observers.remove(name); 624 var sub = _observers.remove(name);
658 if (sub == null) return false; 625 if (sub == null) return false;
659 sub.cancel(); 626 sub.cancel();
660 return true; 627 return true;
661 } 628 }
662 629
663 void unregisterObservers() { 630 void unregisterObservers() {
664 if (_observers == null) return; 631 if (_observers == null) return;
665 for (var sub in _observers.values) sub.cancel(); 632 for (var sub in _observers.values) sub.cancel();
666 _observers.clear(); 633 _observers.clear();
667 _observers = null; 634 _observers = null;
668 } 635 }
669 636
670 /** 637 /// Bind a [property] in this object to a [path] in model. *Note* in Dart it
671 * Bind a [property] in this object to a [path] in model. *Note* in Dart it 638 /// is necessary to also define the field:
672 * is necessary to also define the field: 639 ///
673 * 640 /// var myProperty;
674 * var myProperty; 641 ///
675 * 642 /// ready() {
676 * ready() { 643 /// super.ready();
677 * super.ready(); 644 /// bindProperty(#myProperty, this, 'myModel.path.to.otherProp');
678 * bindProperty(#myProperty, this, 'myModel.path.to.otherProp'); 645 /// }
679 * }
680 */
681 Bindable bindProperty(Symbol name, Bindable bindable) { 646 Bindable bindProperty(Symbol name, Bindable bindable) {
682 // Dart note: normally we only reach this code when we know it's a 647 // Dart note: normally we only reach this code when we know it's a
683 // property, but if someone uses bindProperty directly they might get a 648 // property, but if someone uses bindProperty directly they might get a
684 // NoSuchMethodError either from the getField below, or from the setField 649 // NoSuchMethodError either from the getField below, or from the setField
685 // inside PolymerBinding. That doesn't seem unreasonable, but it's a slight 650 // inside PolymerBinding. That doesn't seem unreasonable, but it's a slight
686 // difference from Polymer.js behavior. 651 // difference from Polymer.js behavior.
687 652
688 if (_bindLog.isLoggable(Level.FINE)) { 653 if (_bindLog.isLoggable(Level.FINE)) {
689 _bindLog.fine('bindProperty: [$bindable] to [${localName}].[name]'); 654 _bindLog.fine('bindProperty: [$bindable] to [${localName}].[name]');
690 } 655 }
691 656
692 // capture A's value if B's value is null or undefined, 657 // capture A's value if B's value is null or undefined,
693 // otherwise use B's value 658 // otherwise use B's value
694 // TODO(sorvell): need to review, can do with ObserverTransform 659 // TODO(sorvell): need to review, can do with ObserverTransform
695 var v = bindable.value; 660 var v = bindable.value;
696 if (v == null) { 661 if (v == null) {
697 bindable.value = reflect(this).getField(name).reflectee; 662 bindable.value = reflect(this).getField(name).reflectee;
698 } 663 }
699 664
700 // TODO(jmesserly): this will create another subscription. 665 // TODO(jmesserly): this will create another subscription.
701 // It would be nice to have this reuse our existing _propertyObserver 666 // It would be nice to have this reuse our existing _propertyObserver
702 // created by observeProperties, to avoid more observation overhead. 667 // created by observeProperties, to avoid more observation overhead.
703 return new _PolymerBinding(this, name, bindable); 668 return new _PolymerBinding(this, name, bindable);
704 } 669 }
705 670
706 /** Attach event listeners on the host (this) element. */ 671 /// Attach event listeners on the host (this) element.
707 void addHostListeners() { 672 void addHostListeners() {
708 var events = _declaration._eventDelegates; 673 var events = _declaration._eventDelegates;
709 if (events.isEmpty) return; 674 if (events.isEmpty) return;
710 675
711 if (_eventsLog.isLoggable(Level.FINE)) { 676 if (_eventsLog.isLoggable(Level.FINE)) {
712 _eventsLog.fine('[$localName] addHostListeners: $events'); 677 _eventsLog.fine('[$localName] addHostListeners: $events');
713 } 678 }
714 addNodeListeners(this, events.keys, hostEventListener); 679 addNodeListeners(this, events.keys, hostEventListener);
715 } 680 }
716 681
(...skipping 28 matching lines...) Expand all
745 } 710 }
746 711
747 if (log) { 712 if (log) {
748 _eventsLog.fine('<<< [$localName]: hostEventListener(${event.type})'); 713 _eventsLog.fine('<<< [$localName]: hostEventListener(${event.type})');
749 } 714 }
750 } 715 }
751 716
752 String findEventDelegate(Event event) => 717 String findEventDelegate(Event event) =>
753 _declaration._eventDelegates[_eventNameFromType(event.type)]; 718 _declaration._eventDelegates[_eventNameFromType(event.type)];
754 719
755 /** 720 /// Calls [methodOrCallback] with [args] if it is a closure, otherwise, treat
756 * Calls [methodOrCallback] with [args] if it is a closure, otherwise, treat 721 /// it as a method name in [object], and invoke it.
757 * it as a method name in [object], and invoke it.
758 */
759 void dispatchMethod(object, callbackOrMethod, List args) { 722 void dispatchMethod(object, callbackOrMethod, List args) {
760 bool log = _eventsLog.isLoggable(Level.FINE); 723 bool log = _eventsLog.isLoggable(Level.FINE);
761 if (log) _eventsLog.fine('>>> [$localName]: dispatch $callbackOrMethod'); 724 if (log) _eventsLog.fine('>>> [$localName]: dispatch $callbackOrMethod');
762 725
763 if (callbackOrMethod is Function) { 726 if (callbackOrMethod is Function) {
764 int maxArgs = smoke.maxArgs(callbackOrMethod); 727 int maxArgs = smoke.maxArgs(callbackOrMethod);
765 if (maxArgs == -1) { 728 if (maxArgs == -1) {
766 _eventsLog.warning( 729 _eventsLog.warning(
767 'invalid callback: expected callback of 0, 1, 2, or 3 arguments'); 730 'invalid callback: expected callback of 0, 1, 2, or 3 arguments');
768 } 731 }
769 args.length = maxArgs; 732 args.length = maxArgs;
770 Function.apply(callbackOrMethod, args); 733 Function.apply(callbackOrMethod, args);
771 } else if (callbackOrMethod is String) { 734 } else if (callbackOrMethod is String) {
772 smoke.invoke(object, smoke.nameToSymbol(callbackOrMethod), args, 735 smoke.invoke(object, smoke.nameToSymbol(callbackOrMethod), args,
773 adjust: true); 736 adjust: true);
774 } else { 737 } else {
775 _eventsLog.warning('invalid callback'); 738 _eventsLog.warning('invalid callback');
776 } 739 }
777 740
778 if (log) _eventsLog.info('<<< [$localName]: dispatch $callbackOrMethod'); 741 if (log) _eventsLog.info('<<< [$localName]: dispatch $callbackOrMethod');
779 } 742 }
780 743
781 /** 744 /// Bind events via attributes of the form `on-eventName`. This method can be
782 * Bind events via attributes of the form `on-eventName`. This method can be 745 /// use to hooks into the model syntax and adds event listeners as needed. By
783 * use to hooks into the model syntax and adds event listeners as needed. By 746 /// default, binding paths are always method names on the root model, the
784 * default, binding paths are always method names on the root model, the 747 /// custom element in which the node exists. Adding a '@' in the path directs
785 * custom element in which the node exists. Adding a '@' in the path directs 748 /// the event binding to use the model path as the event listener. In both
786 * the event binding to use the model path as the event listener. In both 749 /// cases, the actual listener is attached to a generic method which evaluates
787 * cases, the actual listener is attached to a generic method which evaluates 750 /// the bound path at event execution time.
788 * the bound path at event execution time.
789 */
790 // from src/instance/event.js#prepareBinding 751 // from src/instance/event.js#prepareBinding
791 static PrepareBindingFunction prepareBinding(String path, String name, node) { 752 static PrepareBindingFunction prepareBinding(String path, String name, node) {
792 753
793 // provide an event-binding callback. 754 // provide an event-binding callback.
794 return (model, node, oneTime) { 755 return (model, node, oneTime) {
795 if (_eventsLog.isLoggable(Level.FINE)) { 756 if (_eventsLog.isLoggable(Level.FINE)) {
796 _eventsLog.fine('event: [$node].$name => [$model].$path())'); 757 _eventsLog.fine('event: [$node].$name => [$model].$path())');
797 } 758 }
798 var eventName = _removeEventPrefix(name); 759 var eventName = _removeEventPrefix(name);
799 // TODO(sigmund): polymer.js dropped event translations. reconcile? 760 // TODO(sigmund): polymer.js dropped event translations. reconcile?
800 var translated = _eventTranslations[eventName]; 761 var translated = _eventTranslations[eventName];
801 eventName = translated != null ? translated : eventName; 762 eventName = translated != null ? translated : eventName;
802 763
803 return new _EventBindable(node, eventName, model, path); 764 return new _EventBindable(node, eventName, model, path);
804 }; 765 };
805 } 766 }
806 767
807 /** Call [methodName] method on this object with [args]. */ 768 /// Call [methodName] method on this object with [args].
808 invokeMethod(Symbol methodName, List args) => 769 invokeMethod(Symbol methodName, List args) =>
809 smoke.invoke(this, methodName, args, adjust: true); 770 smoke.invoke(this, methodName, args, adjust: true);
810 771
811 /** 772 /// Invokes a function asynchronously.
812 * Invokes a function asynchronously. 773 /// This will call `Platform.flush()` and then return a `new Timer`
813 * This will call `Platform.flush()` and then return a `new Timer` 774 /// with the provided [method] and [timeout].
814 * with the provided [method] and [timeout]. 775 ///
815 * 776 /// If you would prefer to run the callback using
816 * If you would prefer to run the callback using 777 /// [window.requestAnimationFrame], see the [async] method.
817 * [window.requestAnimationFrame], see the [async] method.
818 */
819 // Dart note: "async" is split into 2 methods so it can have a sensible type 778 // Dart note: "async" is split into 2 methods so it can have a sensible type
820 // signatures. Also removed the various features that don't make sense in a 779 // signatures. Also removed the various features that don't make sense in a
821 // Dart world, like binding to "this" and taking arguments list. 780 // Dart world, like binding to "this" and taking arguments list.
822 Timer asyncTimer(void method(), Duration timeout) { 781 Timer asyncTimer(void method(), Duration timeout) {
823 // when polyfilling Object.observe, ensure changes 782 // when polyfilling Object.observe, ensure changes
824 // propagate before executing the async method 783 // propagate before executing the async method
825 scheduleMicrotask(Observable.dirtyCheck); 784 scheduleMicrotask(Observable.dirtyCheck);
826 return new Timer(timeout, method); 785 return new Timer(timeout, method);
827 } 786 }
828 787
829 /** 788 /// Invokes a function asynchronously.
830 * Invokes a function asynchronously. 789 /// This will call `Platform.flush()` and then call
831 * This will call `Platform.flush()` and then call 790 /// [window.requestAnimationFrame] with the provided [method] and return the
832 * [window.requestAnimationFrame] with the provided [method] and return the 791 /// result.
833 * result. 792 ///
834 * 793 /// If you would prefer to run the callback after a given duration, see
835 * If you would prefer to run the callback after a given duration, see 794 /// the [asyncTimer] method.
836 * the [asyncTimer] method.
837 */
838 int async(RequestAnimationFrameCallback method) { 795 int async(RequestAnimationFrameCallback method) {
839 // when polyfilling Object.observe, ensure changes 796 // when polyfilling Object.observe, ensure changes
840 // propagate before executing the async method 797 // propagate before executing the async method
841 scheduleMicrotask(Observable.dirtyCheck); 798 scheduleMicrotask(Observable.dirtyCheck);
842 return window.requestAnimationFrame(method); 799 return window.requestAnimationFrame(method);
843 } 800 }
844 801
845 /** 802 /// Fire a [CustomEvent] targeting [toNode], or this if toNode is not
846 * Fire a [CustomEvent] targeting [toNode], or this if toNode is not 803 /// supplied. Returns the [detail] object.
847 * supplied. Returns the [detail] object.
848 */
849 Object fire(String type, {Object detail, Node toNode, bool canBubble}) { 804 Object fire(String type, {Object detail, Node toNode, bool canBubble}) {
850 var node = toNode != null ? toNode : this; 805 var node = toNode != null ? toNode : this;
851 //log.events && console.log('[%s]: sending [%s]', node.localName, inType); 806 //log.events && console.log('[%s]: sending [%s]', node.localName, inType);
852 node.dispatchEvent(new CustomEvent( 807 node.dispatchEvent(new CustomEvent(
853 type, 808 type,
854 canBubble: canBubble != null ? canBubble : true, 809 canBubble: canBubble != null ? canBubble : true,
855 detail: detail 810 detail: detail
856 )); 811 ));
857 return detail; 812 return detail;
858 } 813 }
859 814
860 /** 815 /// Fire an event asynchronously. See [async] and [fire].
861 * Fire an event asynchronously. See [async] and [fire].
862 */
863 asyncFire(String type, {Object detail, Node toNode, bool canBubble}) { 816 asyncFire(String type, {Object detail, Node toNode, bool canBubble}) {
864 // TODO(jmesserly): I'm not sure this method adds much in Dart, it's easy to 817 // TODO(jmesserly): I'm not sure this method adds much in Dart, it's easy to
865 // add "() =>" 818 // add "() =>"
866 async((x) => fire( 819 async((x) => fire(
867 type, detail: detail, toNode: toNode, canBubble: canBubble)); 820 type, detail: detail, toNode: toNode, canBubble: canBubble));
868 } 821 }
869 822
870 /** 823 /// Remove [className] from [old], add class to [anew], if they exist.
871 * Remove [className] from [old], add class to [anew], if they exist.
872 */
873 void classFollows(Element anew, Element old, String className) { 824 void classFollows(Element anew, Element old, String className) {
874 if (old != null) { 825 if (old != null) {
875 old.classes.remove(className); 826 old.classes.remove(className);
876 } 827 }
877 if (anew != null) { 828 if (anew != null) {
878 anew.classes.add(className); 829 anew.classes.add(className);
879 } 830 }
880 } 831 }
881 832
882 /** 833 /// Installs external stylesheets and <style> elements with the attribute
883 * Installs external stylesheets and <style> elements with the attribute 834 /// polymer-scope='controller' into the scope of element. This is intended
884 * polymer-scope='controller' into the scope of element. This is intended 835 /// to be a called during custom element construction. Note, this incurs a
885 * to be a called during custom element construction. Note, this incurs a 836 /// per instance cost and should be used sparingly.
886 * per instance cost and should be used sparingly. 837 ///
887 * 838 /// The need for this type of styling should go away when the shadowDOM spec
888 * The need for this type of styling should go away when the shadowDOM spec 839 /// addresses these issues:
889 * addresses these issues: 840 ///
890 * 841 /// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21391
891 * https://www.w3.org/Bugs/Public/show_bug.cgi?id=21391 842 /// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21390
892 * https://www.w3.org/Bugs/Public/show_bug.cgi?id=21390 843 /// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21389
893 * https://www.w3.org/Bugs/Public/show_bug.cgi?id=21389 844 ///
894 * 845 /// @param element The custom element instance into whose controller (parent)
895 * @param element The custom element instance into whose controller (parent) 846 /// scope styles will be installed.
896 * scope styles will be installed. 847 /// @param elementElement The <element> containing controller styles.
897 * @param elementElement The <element> containing controller styles.
898 */
899 // TODO(sorvell): remove when spec issues are addressed 848 // TODO(sorvell): remove when spec issues are addressed
900 void installControllerStyles() { 849 void installControllerStyles() {
901 var scope = findStyleController(); 850 var scope = findStyleController();
902 if (scope != null && scopeHasElementStyle(scope, _STYLE_CONTROLLER_SCOPE)) { 851 if (scope != null && scopeHasElementStyle(scope, _STYLE_CONTROLLER_SCOPE)) {
903 // allow inherited controller styles 852 // allow inherited controller styles
904 var decl = _declaration; 853 var decl = _declaration;
905 var cssText = new StringBuffer(); 854 var cssText = new StringBuffer();
906 while (decl != null) { 855 while (decl != null) {
907 cssText.write(decl.cssTextForScope(_STYLE_CONTROLLER_SCOPE)); 856 cssText.write(decl.cssTextForScope(_STYLE_CONTROLLER_SCOPE));
908 decl = decl.superDeclaration; 857 decl = decl.superDeclaration;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 var clone = new StyleElement()..text = style.text; 895 var clone = new StyleElement()..text = style.text;
947 896
948 var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE]; 897 var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE];
949 if (attr != null) { 898 if (attr != null) {
950 clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr; 899 clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr;
951 } 900 }
952 901
953 scope.append(clone); 902 scope.append(clone);
954 } 903 }
955 904
956 /** 905 /// Prevents flash of unstyled content
957 * Prevents flash of unstyled content 906 /// This is the list of selectors for veiled elements
958 * This is the list of selectors for veiled elements
959 */
960 static List<Element> veiledElements = ['body']; 907 static List<Element> veiledElements = ['body'];
961 908
962 /** Apply unveil class. */ 909 /// Apply unveil class.
963 static void unveilElements() { 910 static void unveilElements() {
964 window.requestAnimationFrame((_) { 911 window.requestAnimationFrame((_) {
965 var nodes = document.querySelectorAll('.$_VEILED_CLASS'); 912 var nodes = document.querySelectorAll('.$_VEILED_CLASS');
966 for (var node in nodes) { 913 for (var node in nodes) {
967 (node.classes)..add(_UNVEIL_CLASS)..remove(_VEILED_CLASS); 914 (node.classes)..add(_UNVEIL_CLASS)..remove(_VEILED_CLASS);
968 } 915 }
969 // NOTE: depends on transition end event to remove 'unveil' class. 916 // NOTE: depends on transition end event to remove 'unveil' class.
970 if (nodes.isNotEmpty) { 917 if (nodes.isNotEmpty) {
971 window.onTransitionEnd.first.then((_) { 918 window.onTransitionEnd.first.then((_) {
972 for (var node in nodes) { 919 for (var node in nodes) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 977
1031 final Logger _observeLog = new Logger('polymer.observe'); 978 final Logger _observeLog = new Logger('polymer.observe');
1032 final Logger _eventsLog = new Logger('polymer.events'); 979 final Logger _eventsLog = new Logger('polymer.events');
1033 final Logger _unbindLog = new Logger('polymer.unbind'); 980 final Logger _unbindLog = new Logger('polymer.unbind');
1034 final Logger _bindLog = new Logger('polymer.bind'); 981 final Logger _bindLog = new Logger('polymer.bind');
1035 982
1036 final Expando _shadowHost = new Expando<Polymer>(); 983 final Expando _shadowHost = new Expando<Polymer>();
1037 984
1038 final Expando _eventHandledTable = new Expando<Set<Node>>(); 985 final Expando _eventHandledTable = new Expando<Set<Node>>();
1039 986
1040 /** 987 /// Base class for PolymerElements deriving from HtmlElement.
1041 * Base class for PolymerElements deriving from HtmlElement. 988 ///
1042 * 989 /// See [Polymer].
1043 * See [Polymer].
1044 */
1045 class PolymerElement extends HtmlElement with Polymer, Observable { 990 class PolymerElement extends HtmlElement with Polymer, Observable {
1046 PolymerElement.created() : super.created() { 991 PolymerElement.created() : super.created() {
1047 polymerCreated(); 992 polymerCreated();
1048 } 993 }
1049 } 994 }
1050 995
1051 class _PropertyValue { 996 class _PropertyValue {
1052 Object oldValue, newValue; 997 Object oldValue, newValue;
1053 _PropertyValue(this.oldValue); 998 _PropertyValue(this.oldValue);
1054 } 999 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 if (_sub != null) { 1047 if (_sub != null) {
1103 if (_eventsLog.isLoggable(Level.FINE)) { 1048 if (_eventsLog.isLoggable(Level.FINE)) {
1104 _eventsLog.fine( 1049 _eventsLog.fine(
1105 'event.remove: [$_node].$_eventName => [$_model].$_path())'); 1050 'event.remove: [$_node].$_eventName => [$_model].$_path())');
1106 } 1051 }
1107 _sub.cancel(); 1052 _sub.cancel();
1108 _sub = null; 1053 _sub = null;
1109 } 1054 }
1110 } 1055 }
1111 } 1056 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698