Index: sdk/lib/html/src/FilteredElementList.dart |
diff --git a/sdk/lib/html/src/FilteredElementList.dart b/sdk/lib/html/src/FilteredElementList.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d055014e6632cdfdcfaa7e0d26cd3d788db5e08e |
--- /dev/null |
+++ b/sdk/lib/html/src/FilteredElementList.dart |
@@ -0,0 +1,102 @@ |
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+class FilteredElementList implements List { |
+ final Node _node; |
+ final List<Node> _childNodes; |
+ |
+ FilteredElementList(Node node): _childNodes = node.nodes, _node = node; |
+ |
+ // We can't memoize this, since it's possible that children will be messed |
+ // with externally to this class. |
+ // |
+ // TODO(nweiz): Do we really need to copy the list to make the types work out? |
+ List<Element> get _filtered => |
+ new List.from(_childNodes.filter((n) => n is Element)); |
+ |
+ void forEach(void f(Element element)) { |
+ _filtered.forEach(f); |
+ } |
+ |
+ void operator []=(int index, Element value) { |
+ this[index].replaceWith(value); |
+ } |
+ |
+ void set length(int newLength) { |
+ final len = this.length; |
+ if (newLength >= len) { |
+ return; |
+ } else if (newLength < 0) { |
+ throw new ArgumentError("Invalid list length"); |
+ } |
+ |
+ removeRange(newLength - 1, len - newLength); |
+ } |
+ |
+ void add(Element value) { |
+ _childNodes.add(value); |
+ } |
+ |
+ void addAll(Collection<Element> collection) { |
+ collection.forEach(add); |
+ } |
+ |
+ void addLast(Element value) { |
+ add(value); |
+ } |
+ |
+ bool contains(Element element) { |
+ return element is Element && _childNodes.contains(element); |
+ } |
+ |
+ void sort([Comparator<Element> compare = Comparable.compare]) { |
+ throw new UnsupportedError('TODO(jacobr): should we impl?'); |
+ } |
+ |
+ void setRange(int start, int rangeLength, List from, [int startFrom = 0]) { |
+ throw new UnimplementedError(); |
+ } |
+ |
+ void removeRange(int start, int rangeLength) { |
+ _filtered.getRange(start, rangeLength).forEach((el) => el.remove()); |
+ } |
+ |
+ void insertRange(int start, int rangeLength, [initialValue = null]) { |
+ throw new UnimplementedError(); |
+ } |
+ |
+ void clear() { |
+ // Currently, ElementList#clear clears even non-element nodes, so we follow |
+ // that behavior. |
+ _childNodes.clear(); |
+ } |
+ |
+ Element removeLast() { |
+ final result = this.last; |
+ if (result != null) { |
+ result.remove(); |
+ } |
+ return result; |
+ } |
+ |
+ Collection map(f(Element element)) => _filtered.map(f); |
+ Collection<Element> filter(bool f(Element element)) => _filtered.filter(f); |
+ bool every(bool f(Element element)) => _filtered.every(f); |
+ bool some(bool f(Element element)) => _filtered.some(f); |
+ bool get isEmpty => _filtered.isEmpty; |
+ int get length => _filtered.length; |
+ Element operator [](int index) => _filtered[index]; |
+ Iterator<Element> iterator() => _filtered.iterator(); |
+ List<Element> getRange(int start, int rangeLength) => |
+ _filtered.getRange(start, rangeLength); |
+ int indexOf(Element element, [int start = 0]) => |
+ _filtered.indexOf(element, start); |
+ |
+ int lastIndexOf(Element element, [int start = null]) { |
+ if (start == null) start = length - 1; |
+ return _filtered.lastIndexOf(element, start); |
+ } |
+ |
+ Element get last => _filtered.last; |
+} |