| Index: third_party/pkg/angular/lib/directive/ng_class.dart
|
| diff --git a/third_party/pkg/angular/lib/directive/ng_class.dart b/third_party/pkg/angular/lib/directive/ng_class.dart
|
| index 6c77f7302bc873dc776b344b2f55b9bb6df9c012..c3784309c69b0129aecd437432db9a3785bc7685 100644
|
| --- a/third_party/pkg/angular/lib/directive/ng_class.dart
|
| +++ b/third_party/pkg/angular/lib/directive/ng_class.dart
|
| @@ -62,13 +62,13 @@ part of angular.directive;
|
| * }
|
| *
|
| */
|
| -@NgDirective(
|
| +@Decorator(
|
| selector: '[ng-class]',
|
| map: const {'ng-class': '@valueExpression'},
|
| exportExpressionAttrs: const ['ng-class'])
|
| -class NgClassDirective extends _NgClassBase {
|
| - NgClassDirective(dom.Element element, Scope scope, NodeAttrs attrs, AstParser parser)
|
| - : super(element, scope, null, attrs, parser);
|
| +class NgClass extends _NgClassBase {
|
| + NgClass(NgElement ngElement, Scope scope, NodeAttrs nodeAttrs)
|
| + : super(ngElement, scope, nodeAttrs);
|
| }
|
|
|
| /**
|
| @@ -97,13 +97,13 @@ class NgClassDirective extends _NgClassBase {
|
| * color: blue;
|
| * }
|
| */
|
| -@NgDirective(
|
| +@Decorator(
|
| selector: '[ng-class-odd]',
|
| map: const {'ng-class-odd': '@valueExpression'},
|
| exportExpressionAttrs: const ['ng-class-odd'])
|
| -class NgClassOddDirective extends _NgClassBase {
|
| - NgClassOddDirective(dom.Element element, Scope scope, NodeAttrs attrs, AstParser parser)
|
| - : super(element, scope, 0, attrs, parser);
|
| +class NgClassOdd extends _NgClassBase {
|
| + NgClassOdd(NgElement ngElement, Scope scope, NodeAttrs nodeAttrs)
|
| + : super(ngElement, scope, nodeAttrs, 0);
|
| }
|
|
|
| /**
|
| @@ -132,84 +132,135 @@ class NgClassOddDirective extends _NgClassBase {
|
| * color: blue;
|
| * }
|
| */
|
| -@NgDirective(
|
| +@Decorator(
|
| selector: '[ng-class-even]',
|
| map: const {'ng-class-even': '@valueExpression'},
|
| exportExpressionAttrs: const ['ng-class-even'])
|
| -class NgClassEvenDirective extends _NgClassBase {
|
| - NgClassEvenDirective(dom.Element element, Scope scope, NodeAttrs attrs, AstParser parser)
|
| - : super(element, scope, 1, attrs, parser);
|
| +class NgClassEven extends _NgClassBase {
|
| + NgClassEven(NgElement ngElement, Scope scope, NodeAttrs nodeAttrs)
|
| + : super(ngElement, scope, nodeAttrs, 1);
|
| }
|
|
|
| abstract class _NgClassBase {
|
| - final dom.Element element;
|
| - final Scope scope;
|
| - final int mode;
|
| - final NodeAttrs nodeAttrs;
|
| - final AstParser _parser;
|
| - var previousSet = [];
|
| - var currentSet = [];
|
| + final NgElement _ngElement;
|
| + final Scope _scope;
|
| + final int _mode;
|
| + Watch _watchExpression;
|
| + Watch _watchPosition;
|
| + var _previousSet = new Set<String>();
|
| + var _currentSet = new Set<String>();
|
| + bool _first = true;
|
|
|
| - _NgClassBase(this.element, this.scope, this.mode, this.nodeAttrs, this._parser) {
|
| - var prevClass;
|
| + _NgClassBase(this._ngElement, this._scope, NodeAttrs nodeAttrs,
|
| + [this._mode = null])
|
| + {
|
| + var prevCls;
|
|
|
| - nodeAttrs.observe('class', (String newValue) {
|
| - if (prevClass != newValue) {
|
| - prevClass = newValue;
|
| - _handleChange(scope.context[r'$index']);
|
| + nodeAttrs.observe('class', (String cls) {
|
| + if (prevCls != cls) {
|
| + prevCls = cls;
|
| + _applyChanges(_scope.context[r'$index']);
|
| }
|
| });
|
| }
|
|
|
| - set valueExpression(currentExpression) {
|
| - // this should be called only once, so we don't worry about cleaning up
|
| - // watcher registrations.
|
| - scope.watch(
|
| - _parser(currentExpression, collection: true),
|
| - (current, _) {
|
| - currentSet = _flatten(current);
|
| - _handleChange(scope.context[r'$index']);
|
| - },
|
| - readOnly: true
|
| - );
|
| - if (mode != null) {
|
| - scope.watch(_parser(r'$index'), (index, oldIndex) {
|
| - var mod = index % 2;
|
| - if (oldIndex == null || mod != oldIndex % 2) {
|
| - if (mod == mode) {
|
| - element.classes.addAll(currentSet);
|
| + set valueExpression(expression) {
|
| + if (_watchExpression != null) _watchExpression.remove();
|
| + _watchExpression = _scope.watch(expression, (v, _) {
|
| + _computeChanges(v);
|
| + _applyChanges(_scope.context[r'$index']);
|
| + },
|
| + canChangeModel: false,
|
| + collection: true);
|
| +
|
| + if (_mode != null) {
|
| + if (_watchPosition != null) _watchPosition.remove();
|
| + _watchPosition = _scope.watch(r'$index', (idx, previousIdx) {
|
| + var mod = idx % 2;
|
| + if (previousIdx == null || mod != previousIdx % 2) {
|
| + if (mod == _mode) {
|
| + _currentSet.forEach((cls) => _ngElement.addClass(cls));
|
| } else {
|
| - element.classes.removeAll(previousSet);
|
| + _previousSet.forEach((cls) => _ngElement.removeClass(cls));
|
| }
|
| }
|
| - }, readOnly: true);
|
| + }, canChangeModel: false);
|
| }
|
| }
|
|
|
| - _handleChange(index) {
|
| - if (mode == null || (index != null && index % 2 == mode)) {
|
| - element.classes..removeAll(previousSet)..addAll(currentSet);
|
| + void _computeChanges(value) {
|
| + if (value is CollectionChangeRecord) {
|
| + _computeCollectionChanges(value, _first);
|
| + } else if (value is MapChangeRecord) {
|
| + _computeMapChanges(value, _first);
|
| + } else {
|
| + if (value is String) {
|
| + _currentSet..clear()..addAll(value.split(' '));
|
| + } else if (value == null) {
|
| + _currentSet.clear();
|
| + } else {
|
| + throw 'ng-class expects expression value to be List, Map or String, '
|
| + 'got $value';
|
| + }
|
| }
|
|
|
| - previousSet = currentSet;
|
| + _first = false;
|
| }
|
|
|
| - static List<String> _flatten(classes) {
|
| - if (classes == null) return [];
|
| - if (classes is CollectionChangeRecord) {
|
| - classes = (classes as CollectionChangeRecord).iterable.toList();
|
| - }
|
| - if (classes is List) {
|
| - return classes.where((String e) => e != null && e.isNotEmpty)
|
| - .toList(growable: false);
|
| + // todo(vicb) refactor once GH-774 gets fixed
|
| + void _computeCollectionChanges(CollectionChangeRecord changes, bool first) {
|
| + if (first) {
|
| + changes.iterable.forEach((cls) {
|
| + _currentSet.add(cls);
|
| + });
|
| + } else {
|
| + changes.forEachAddition((CollectionChangeItem a) {
|
| + _currentSet.add(a.item);
|
| + });
|
| + changes.forEachRemoval((CollectionChangeItem r) {
|
| + _currentSet.remove(r.item);
|
| + });
|
| }
|
| - if (classes is MapChangeRecord) {
|
| - classes = (classes as MapChangeRecord).map;
|
| + }
|
| +
|
| + // todo(vicb) refactor once GH-774 gets fixed
|
| + _computeMapChanges(MapChangeRecord changes, first) {
|
| + if (first) {
|
| + changes.map.forEach((cls, active) {
|
| + if (toBool(active)) _currentSet.add(cls);
|
| + });
|
| + } else {
|
| + changes.forEachChange((MapKeyValue kv) {
|
| + var cls = kv.key;
|
| + var active = toBool(kv.currentValue);
|
| + var wasActive = toBool(kv.previousValue);
|
| + if (active != wasActive) {
|
| + if (active) {
|
| + _currentSet.add(cls);
|
| + } else {
|
| + _currentSet.remove(cls);
|
| + }
|
| + }
|
| + });
|
| + changes.forEachAddition((MapKeyValue kv) {
|
| + if (toBool(kv.currentValue)) _currentSet.add(kv.key);
|
| + });
|
| + changes.forEachRemoval((MapKeyValue kv) {
|
| + if (toBool(kv.previousValue)) _currentSet.remove(kv.key);
|
| + });
|
| }
|
| - if (classes is Map) {
|
| - return classes.keys.where((key) => toBool(classes[key])).toList();
|
| + }
|
| +
|
| + _applyChanges(index) {
|
| + if (_mode == null || (index != null && index % 2 == _mode)) {
|
| + _previousSet
|
| + .where((cls) => cls != null)
|
| + .forEach((cls) => _ngElement.removeClass(cls));
|
| + _currentSet
|
| + .where((cls) => cls != null)
|
| + .forEach((cls) => _ngElement.addClass(cls));
|
| }
|
| - if (classes is String) return classes.split(' ');
|
| - throw 'ng-class expects expression value to be List, Map or String, got $classes';
|
| +
|
| + _previousSet = _currentSet.toSet();
|
| }
|
| }
|
|
|