| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of polymer; | 5 part of polymer; |
| 6 | 6 |
| 7 /** | 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 /** | 24 /** |
| 25 * The mixin class for Polymer elements. It provides convenience features on top | 25 * The mixin class for Polymer elements. It provides convenience features on top |
| 26 * of the custom elements web standard. | 26 * of the custom elements web standard. |
| 27 */ | 27 */ |
| 28 abstract class Polymer implements Element { | 28 abstract class Polymer implements Element, NodeBindExtension { |
| 29 // Fully ported from revision: | 29 // Fully ported from revision: |
| 30 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212
67779 | 30 // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f212
67779 |
| 31 // | 31 // |
| 32 // src/instance/attributes.js | 32 // src/instance/attributes.js |
| 33 // src/instance/base.js | 33 // src/instance/base.js |
| 34 // src/instance/events.js | 34 // src/instance/events.js |
| 35 // src/instance/mdv.js | 35 // src/instance/mdv.js |
| 36 // src/instance/properties.js | 36 // src/instance/properties.js |
| 37 // src/instance/utils.js | 37 // src/instance/utils.js |
| 38 // | 38 // |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 // attrs. | 364 // attrs. |
| 365 } else if (propValue is bool) { | 365 } else if (propValue is bool) { |
| 366 attributes.remove(name); | 366 attributes.remove(name); |
| 367 } | 367 } |
| 368 } | 368 } |
| 369 | 369 |
| 370 /** | 370 /** |
| 371 * Creates the document fragment to use for each instance of the custom | 371 * Creates the document fragment to use for each instance of the custom |
| 372 * element, given the `<template>` node. By default this is equivalent to: | 372 * element, given the `<template>` node. By default this is equivalent to: |
| 373 * | 373 * |
| 374 * template.createInstance(this, polymerSyntax); | 374 * templateBind(template).createInstance(this, polymerSyntax); |
| 375 * | 375 * |
| 376 * Where polymerSyntax is a singleton `PolymerExpressions` instance from the | 376 * Where polymerSyntax is a singleton `PolymerExpressions` instance from the |
| 377 * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions
) | 377 * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions
) |
| 378 * package. | 378 * package. |
| 379 * | 379 * |
| 380 * You can override this method to change the instantiation behavior of the | 380 * You can override this method to change the instantiation behavior of the |
| 381 * template, for example to use a different data-binding syntax. | 381 * template, for example to use a different data-binding syntax. |
| 382 */ | 382 */ |
| 383 DocumentFragment instanceTemplate(Element template) => | 383 DocumentFragment instanceTemplate(Element template) => |
| 384 template.createInstance(this, _polymerSyntax); | 384 templateBind(template).createInstance(this, _polymerSyntax); |
| 385 |
| 386 NodeBinding createBinding(String name, model, String path) => |
| 387 nodeBindFallback(this).createBinding(name, model, path); |
| 385 | 388 |
| 386 NodeBinding bind(String name, model, String path) { | 389 NodeBinding bind(String name, model, String path) { |
| 387 // note: binding is a prepare signal. This allows us to be sure that any | 390 // note: binding is a prepare signal. This allows us to be sure that any |
| 388 // property changes that occur as a result of binding will be observed. | 391 // property changes that occur as a result of binding will be observed. |
| 389 if (!_elementPrepared) prepareElement(); | 392 if (!_elementPrepared) prepareElement(); |
| 390 | 393 |
| 391 var property = propertyForAttribute(name); | 394 var property = propertyForAttribute(name); |
| 392 if (property != null) { | 395 if (property != null) { |
| 393 unbind(name); | 396 unbind(name); |
| 394 // use n-way Polymer binding | 397 // use n-way Polymer binding |
| 395 var observer = bindProperty(property.simpleName, model, path); | 398 var observer = bindProperty(property.simpleName, model, path); |
| 396 // reflect bound property to attribute when binding | 399 // reflect bound property to attribute when binding |
| 397 // to ensure binding is not left on attribute if property | 400 // to ensure binding is not left on attribute if property |
| 398 // does not update due to not changing. | 401 // does not update due to not changing. |
| 399 // Dart note: we include this patch: | 402 // Dart note: we include this patch: |
| 400 // https://github.com/Polymer/polymer/pull/319 | 403 // https://github.com/Polymer/polymer/pull/319 |
| 401 reflectPropertyToAttribute(MirrorSystem.getName(property.simpleName)); | 404 reflectPropertyToAttribute(MirrorSystem.getName(property.simpleName)); |
| 402 return bindings[name] = observer; | 405 return bindings[name] = observer; |
| 403 } else { | 406 } else { |
| 404 // Cannot call super.bind because of | 407 // Cannot call super.bind because template_binding is its own package |
| 405 // https://code.google.com/p/dart/issues/detail?id=13156 | 408 return nodeBindFallback(this).bind(name, model, path); |
| 406 // https://code.google.com/p/dart/issues/detail?id=12456 | |
| 407 return TemplateElement.mdvPackage(this).bind(name, model, path); | |
| 408 } | 409 } |
| 409 } | 410 } |
| 410 | 411 |
| 412 Map<String, NodeBinding> get bindings => nodeBindFallback(this).bindings; |
| 413 |
| 414 void unbind(String name) => nodeBindFallback(this).unbind(name); |
| 415 |
| 411 void asyncUnbindAll() { | 416 void asyncUnbindAll() { |
| 412 if (_unbound == true) return; | 417 if (_unbound == true) return; |
| 413 _unbindLog.fine('[$localName] asyncUnbindAll'); | 418 _unbindLog.fine('[$localName] asyncUnbindAll'); |
| 414 _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0)); | 419 _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0)); |
| 415 } | 420 } |
| 416 | 421 |
| 417 void unbindAll() { | 422 void unbindAll() { |
| 418 if (_unbound == true) return; | 423 if (_unbound == true) return; |
| 419 | 424 |
| 420 unbindAllProperties(); | 425 unbindAllProperties(); |
| 421 // Cannot call super.bind because of | 426 nodeBindFallback(this).unbindAll(); |
| 422 // https://code.google.com/p/dart/issues/detail?id=13156 | |
| 423 // https://code.google.com/p/dart/issues/detail?id=12456 | |
| 424 TemplateElement.mdvPackage(this).unbindAll(); | |
| 425 | 427 |
| 426 _unbindNodeTree(shadowRoot); | 428 _unbindNodeTree(shadowRoot); |
| 427 // TODO(sjmiles): must also unbind inherited shadow roots | 429 // TODO(sjmiles): must also unbind inherited shadow roots |
| 428 _unbound = true; | 430 _unbound = true; |
| 429 } | 431 } |
| 430 | 432 |
| 431 void cancelUnbindAll({bool preventCascade}) { | 433 void cancelUnbindAll({bool preventCascade}) { |
| 432 if (_unbound == true) { | 434 if (_unbound == true) { |
| 433 _unbindLog.warning( | 435 _unbindLog.warning( |
| 434 '[$localName] already unbound, cannot cancel unbindAll'); | 436 '[$localName] already unbound, cannot cancel unbindAll'); |
| 435 return; | 437 return; |
| 436 } | 438 } |
| 437 _unbindLog.fine('[$localName] cancelUnbindAll'); | 439 _unbindLog.fine('[$localName] cancelUnbindAll'); |
| 438 if (_unbindAllJob != null) { | 440 if (_unbindAllJob != null) { |
| 439 _unbindAllJob.stop(); | 441 _unbindAllJob.stop(); |
| 440 _unbindAllJob = null; | 442 _unbindAllJob = null; |
| 441 } | 443 } |
| 442 | 444 |
| 443 // cancel unbinding our shadow tree iff we're not in the process of | 445 // cancel unbinding our shadow tree iff we're not in the process of |
| 444 // cascading our tree (as we do, for example, when the element is inserted). | 446 // cascading our tree (as we do, for example, when the element is inserted). |
| 445 if (preventCascade == true) return; | 447 if (preventCascade == true) return; |
| 446 _forNodeTree(shadowRoot, (n) { | 448 _forNodeTree(shadowRoot, (n) { |
| 447 if (n is Polymer) { | 449 if (n is Polymer) { |
| 448 (n as Polymer).cancelUnbindAll(); | 450 (n as Polymer).cancelUnbindAll(); |
| 449 } | 451 } |
| 450 }); | 452 }); |
| 451 } | 453 } |
| 452 | 454 |
| 453 static void _unbindNodeTree(Node node) { | 455 static void _unbindNodeTree(Node node) { |
| 454 _forNodeTree(node, (node) => node.unbindAll()); | 456 _forNodeTree(node, (node) => nodeBind(node).unbindAll()); |
| 455 } | 457 } |
| 456 | 458 |
| 457 static void _forNodeTree(Node node, void callback(Node node)) { | 459 static void _forNodeTree(Node node, void callback(Node node)) { |
| 458 if (node == null) return; | 460 if (node == null) return; |
| 459 | 461 |
| 460 callback(node); | 462 callback(node); |
| 461 for (var child = node.firstChild; child != null; child = child.nextNode) { | 463 for (var child = node.firstChild; child != null; child = child.nextNode) { |
| 462 _forNodeTree(child, callback); | 464 _forNodeTree(child, callback); |
| 463 } | 465 } |
| 464 } | 466 } |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 /** | 954 /** |
| 953 * Base class for PolymerElements deriving from HtmlElement. | 955 * Base class for PolymerElements deriving from HtmlElement. |
| 954 * | 956 * |
| 955 * See [Polymer]. | 957 * See [Polymer]. |
| 956 */ | 958 */ |
| 957 class PolymerElement extends HtmlElement with Polymer, Observable { | 959 class PolymerElement extends HtmlElement with Polymer, Observable { |
| 958 PolymerElement.created() : super.created() { | 960 PolymerElement.created() : super.created() { |
| 959 polymerCreated(); | 961 polymerCreated(); |
| 960 } | 962 } |
| 961 } | 963 } |
| OLD | NEW |