| Index: third_party/pkg/angular/lib/core_dom/directive.dart
|
| diff --git a/third_party/pkg/angular/lib/core_dom/directive.dart b/third_party/pkg/angular/lib/core_dom/directive.dart
|
| index 1a8bfada6bb168cf0c38559180a31bffbbe5fe55..9a6c868b2f20b85dc1f3050154ab4b13bb162d98 100644
|
| --- a/third_party/pkg/angular/lib/core_dom/directive.dart
|
| +++ b/third_party/pkg/angular/lib/core_dom/directive.dart
|
| @@ -1,72 +1,101 @@
|
| -part of angular.core.dom;
|
| +part of angular.core.dom_internal;
|
|
|
| -/**
|
| - * Callback function used to notify of attribute changes.
|
| - */
|
| -typedef AttributeChanged(String newValue);
|
| +/// Callback function used to notify of attribute changes.
|
| +typedef void _AttributeChanged(String newValue);
|
| +
|
| +/// Callback function used to notify of observer changes.
|
| +typedef void Mustache(bool hasObservers);
|
|
|
| /**
|
| - * NodeAttrs is a facade for element attributes. The facade is responsible
|
| - * for normalizing attribute names as well as allowing access to the
|
| - * value of the directive.
|
| + * NodeAttrs is a facade for element attributes.
|
| + *
|
| + * This facade allows reading and writing the attribute values as well as
|
| + * adding observers triggered when:
|
| + * - The value of an attribute changes,
|
| + * - An element becomes observed.
|
| */
|
| class NodeAttrs {
|
| final dom.Element element;
|
|
|
| - Map<String, List<AttributeChanged>> _observers;
|
| + Map<String, List<_AttributeChanged>> _observers;
|
| + final _mustacheAttrs = <String, _MustacheAttr>{};
|
|
|
| NodeAttrs(this.element);
|
|
|
| - operator [](String attributeName) =>
|
| - element.attributes[attributeName];
|
| + operator [](String attrName) => element.attributes[attrName];
|
|
|
| - operator []=(String attributeName, String value) {
|
| + void operator []=(String attrName, String value) {
|
| + if (_mustacheAttrs.containsKey(attrName)) {
|
| + _mustacheAttrs[attrName].isComputed = true;
|
| + }
|
| if (value == null) {
|
| - element.attributes.remove(attributeName);
|
| + element.attributes.remove(attrName);
|
| } else {
|
| - element.attributes[attributeName] = value;
|
| + element.attributes[attrName] = value;
|
| }
|
| - if (_observers != null && _observers.containsKey(attributeName)) {
|
| - _observers[attributeName].forEach((fn) => fn(value));
|
| +
|
| + if (_observers != null && _observers.containsKey(attrName)) {
|
| + _observers[attrName].forEach((notifyFn) => notifyFn(value));
|
| }
|
| }
|
|
|
| /**
|
| - * Observe changes to the attribute by invoking the [AttributeChanged]
|
| - * function. On registration the [AttributeChanged] function gets invoked
|
| - * synchronise with the current value.
|
| + * Observes changes to the attribute by invoking the [notifyFn]
|
| + * function. On registration the [notifyFn] function gets invoked in order to
|
| + * synchronize with the current value.
|
| + *
|
| + * When an observed is registered on an attributes any existing
|
| + * [_observerListeners] will be called with the first parameter set to
|
| + * [:true:]
|
| */
|
| - observe(String attributeName, AttributeChanged notifyFn) {
|
| - if (_observers == null) {
|
| - _observers = new Map<String, List<AttributeChanged>>();
|
| - }
|
| - if (!_observers.containsKey(attributeName)) {
|
| - _observers[attributeName] = new List<AttributeChanged>();
|
| + observe(String attrName, notifyFn(String value)) {
|
| + if (_observers == null) _observers = <String, List<_AttributeChanged>>{};
|
| + _observers.putIfAbsent(attrName, () => <_AttributeChanged>[])
|
| + .add(notifyFn);
|
| +
|
| + if (_mustacheAttrs.containsKey(attrName)) {
|
| + if (_mustacheAttrs[attrName].isComputed) notifyFn(this[attrName]);
|
| + _mustacheAttrs[attrName].notifyFn(true);
|
| + } else {
|
| + notifyFn(this[attrName]);
|
| }
|
| - _observers[attributeName].add(notifyFn);
|
| - notifyFn(this[attributeName]);
|
| }
|
|
|
| void forEach(void f(String k, String v)) {
|
| element.attributes.forEach(f);
|
| }
|
|
|
| - bool containsKey(String attributeName) =>
|
| - element.attributes.containsKey(attributeName);
|
| + bool containsKey(String attrName) => element.attributes.containsKey(attrName);
|
| +
|
| + Iterable<String> get keys => element.attributes.keys;
|
|
|
| - Iterable<String> get keys =>
|
| - element.attributes.keys;
|
| + /**
|
| + * Registers a listener to be called when the attribute [attrName] becomes
|
| + * observed. On registration [notifyFn] function gets invoked with [:false:]
|
| + * as the first argument.
|
| + */
|
| + void listenObserverChanges(String attrName, Mustache notifyFn) {
|
| + _mustacheAttrs[attrName] = new _MustacheAttr(notifyFn);
|
| + notifyFn(false);
|
| + }
|
| }
|
|
|
| /**
|
| - * TemplateLoader is an asynchronous access to ShadowRoot which is
|
| + * [TemplateLoader] is an asynchronous access to ShadowRoot which is
|
| * loaded asynchronously. It allows a Component to be notified when its
|
| * ShadowRoot is ready.
|
| */
|
| class TemplateLoader {
|
| - final async.Future<dom.ShadowRoot> _template;
|
| + final async.Future<dom.ShadowRoot> template;
|
| +
|
| + TemplateLoader(this.template);
|
| +}
|
|
|
| - async.Future<dom.ShadowRoot> get template => _template;
|
| +class _MustacheAttr {
|
| + // Listener trigger when the attribute becomes observed
|
| + final Mustache notifyFn;
|
| + // Whether the value has first been computed
|
| + bool isComputed = false;
|
|
|
| - TemplateLoader(this._template);
|
| + _MustacheAttr(this.notifyFn);
|
| }
|
|
|