Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
refactor(ngRepeat): simplify the code
Browse files Browse the repository at this point in the history
This re-introduce the PR #1018: "refactor(ng-repeat): refactor fix for
#1015" which had been reverted.
  • Loading branch information
vicb authored and [email protected] committed Aug 26, 2014
1 parent 7c2846e commit e22a456
Showing 1 changed file with 60 additions and 85 deletions.
145 changes: 60 additions & 85 deletions lib/directive/ng_repeat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class NgRepeat {
String _valueIdentifier;
String _keyIdentifier;
String _listExpr;
List<_Row> _rows;
List<View> _views;
Function _generateId = (key, value, index) => value;
Watch _watch;

Expand Down Expand Up @@ -131,109 +131,95 @@ class NgRepeat {
_watch = _scope.watch(
_listExpr,
(changes, _) {
_onChange((changes is CollectionChangeRecord) ? changes : null);
if (changes is CollectionChangeRecord && changes != null) {
_onCollectionChange(changes);
} else if (_views != null) {
_views.forEach(_viewPort.remove);
_views = null;
}
},
collection: true,
formatters: formatters
);
}

// Computes and executes DOM changes when the item list changes
void _onChange(CollectionChangeRecord changes) {
final iterable = (changes == null) ? const [] : changes.iterable;
final int length = (changes == null) ? 0 : changes.length;
final rows = new List<_Row>(length);
void _onCollectionChange(CollectionChangeRecord changes) {
final int length = changes.length;
final views = new List<View>(length);
final changeFunctions = new List<Function>(length);
final removedIndexes = <int>[];
final int domLength = _rows == null ? 0 : _rows.length;
final int domLength = _views == null ? 0 : _views.length;
final leftInDom = new List.generate(domLength, (i) => domLength - 1 - i);
var domIndex;

var addRow = (int index, value, View previousView) {
var childContext = _updateContext(new PrototypeMap(_scope.context), index,
length)..[_valueIdentifier] = value;
var childScope = _scope.createChild(childContext);
var view = _boundViewFactory(childScope);
var nodes = view.nodes;
rows[index] = new _Row(_generateId(index, value, index))
..view = view
..scope = childScope
..nodes = nodes
..startNode = nodes.first
..endNode = nodes.last;
_viewPort.insert(view, insertAfter: previousView);
};
Function addFn, moveFn, removeFn;

// todo(vicb) refactor once GH-774 gets fixed
if (_rows == null) {
_rows = new List<_Row>(length);
for (var i = 0; i < length; i++) {
changeFunctions[i] = (index, previousView) {
addRow(index, iterable.elementAt(i), previousView);
};
}
if (_views == null) {
addFn = changes.forEachItem;
moveFn = (_) {};
removeFn = (_) {};
} else {
if (changes == null) {
_rows.forEach((row) {
_viewPort.remove(row.view);
});
leftInDom.clear();
} else {
changes.forEachRemoval((CollectionChangeItem removal) {
var index = removal.previousIndex;
var row = _rows[index];
_viewPort.remove(row.view);
leftInDom.removeAt(domLength - 1 - index);
});

changes.forEachAddition((CollectionChangeItem addition) {
changeFunctions[addition.currentIndex] = (index, previousView) {
addRow(index, addition.item, previousView);
};
});

changes.forEachMove((CollectionChangeItem move) {
var previousIndex = move.previousIndex;
var value = move.item;
changeFunctions[move.currentIndex] = (index, previousView) {
var previousRow = _rows[previousIndex];
var childScope = previousRow.scope;
var childContext = _updateContext(childScope.context, index, length);
if (!identical(childScope.context[_valueIdentifier], value)) {
childContext[_valueIdentifier] = value;
}
rows[index] = _rows[previousIndex];
// Only move the DOM node when required
if (domIndex < 0 || leftInDom[domIndex] != previousIndex) {
_viewPort.move(previousRow.view, moveAfter: previousView);
leftInDom.remove(previousIndex);
}
domIndex--;
};
});
}
addFn = changes.forEachAddition;
moveFn = changes.forEachMove;
removeFn = changes.forEachRemoval;
}

removeFn((CollectionChangeItem removal) {
var index = removal.previousIndex;
_viewPort.remove(_views[index]);
leftInDom.removeAt(domLength - 1 - index);
});

addFn((CollectionChangeItem addition) {
changeFunctions[addition.currentIndex] = (index, previousView) {
var childContext = _updateContext(new PrototypeMap(_scope.context), index,length)
..[_valueIdentifier] = addition.item;
var childScope = _scope.createChild(childContext);
var view = views[index] = _boundViewFactory(childScope);
_viewPort.insert(view, insertAfter: previousView);
};
});

moveFn((CollectionChangeItem move) {
var previousIndex = move.previousIndex;
var value = move.item;
changeFunctions[move.currentIndex] = (index, moveAfter) {
var previousView = _views[previousIndex];
var childScope = previousView.scope;
var childContext = _updateContext(childScope.context, index, length);
if (!identical(childScope.context[_valueIdentifier], value)) {
childContext[_valueIdentifier] = value;
}
views[index] = _views[previousIndex];
// Only move the DOM node when required
if (domIndex < 0 || leftInDom[domIndex] != previousIndex) {
_viewPort.move(previousView, moveAfter: moveAfter);
leftInDom.remove(previousIndex);
}
domIndex--;
};
});

var previousView = null;
domIndex = leftInDom.length - 1;
for(var targetIndex = 0; targetIndex < length; targetIndex++) {
var changeFn = changeFunctions[targetIndex];
if (changeFn == null) {
rows[targetIndex] = _rows[targetIndex];
views[targetIndex] = _views[targetIndex];
if (domIndex < 0 || leftInDom[domIndex] != targetIndex) {
_viewPort.move(rows[targetIndex].view, moveAfter: previousView);
_viewPort.move(views[targetIndex], moveAfter: previousView);
leftInDom.remove(targetIndex);
}
domIndex--;
// The element has not moved but `$last` and `$middle` might still need to be updated
_updateContext(rows[targetIndex].scope.context, targetIndex, length);
_updateContext(views[targetIndex].scope.context, targetIndex, length);
} else {
changeFn(targetIndex, previousView);
}
previousView = rows[targetIndex].view;
previousView = views[targetIndex];
}

_rows = rows;
_views = views;
}

PrototypeMap _updateContext(PrototypeMap context, int index, int length) {
Expand All @@ -248,14 +234,3 @@ class NgRepeat {
..[r'$even'] = index.isEven;
}
}

class _Row {
final id;
Scope scope;
View view;
dom.Element startNode;
dom.Element endNode;
List<dom.Node> nodes;

_Row(this.id);
}

0 comments on commit e22a456

Please sign in to comment.