| Index: tool/input_sdk/lib/html/html_common/filtered_element_list.dart
|
| diff --git a/tool/input_sdk/lib/html/html_common/filtered_element_list.dart b/tool/input_sdk/lib/html/html_common/filtered_element_list.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e9e47180fbdb26805ee503a5e413e5a639f70b88
|
| --- /dev/null
|
| +++ b/tool/input_sdk/lib/html/html_common/filtered_element_list.dart
|
| @@ -0,0 +1,154 @@
|
| +// 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.
|
| +
|
| +part of html_common;
|
| +
|
| +/**
|
| + * An indexable collection of a node's direct descendants in the document tree,
|
| + * filtered so that only elements are in the collection.
|
| + */
|
| +class FilteredElementList extends ListBase<Element> implements NodeListWrapper {
|
| + final Node _node;
|
| + final List<Node> _childNodes;
|
| +
|
| + /**
|
| + * Creates a collection of the elements that descend from a node.
|
| + *
|
| + * Example usage:
|
| + *
|
| + * var filteredElements = new FilteredElementList(query("#container"));
|
| + * // filteredElements is [a, b, c].
|
| + */
|
| + 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.
|
| + //
|
| + // We can't use where directly because the types don't agree and there's
|
| + // no way to cast it, so take advantage of being in the SDK to construct
|
| + // a WhereIterable directly. Even so it has to be of dynamic.
|
| + Iterable<Element> get _iterable =>
|
| + new WhereIterable(_childNodes, (n) => n is Element);
|
| + List<Element> get _filtered =>
|
| + new List<Element>.from(_iterable, growable: false);
|
| +
|
| + void forEach(void f(Element element)) {
|
| + // This cannot use the iterator, because operations during iteration might
|
| + // modify the collection, e.g. addAll might append a node to another parent.
|
| + _filtered.forEach(f);
|
| + }
|
| +
|
| + void operator []=(int index, Element value) {
|
| + this[index].replaceWith(value);
|
| + }
|
| +
|
| + set length(int newLength) {
|
| + final len = this.length;
|
| + if (newLength >= len) {
|
| + return;
|
| + } else if (newLength < 0) {
|
| + throw new ArgumentError("Invalid list length");
|
| + }
|
| +
|
| + removeRange(newLength, len);
|
| + }
|
| +
|
| + void add(Element value) {
|
| + _childNodes.add(value);
|
| + }
|
| +
|
| + void addAll(Iterable<Element> iterable) {
|
| + for (Element element in iterable) {
|
| + add(element);
|
| + }
|
| + }
|
| +
|
| + bool contains(Object needle) {
|
| + if (needle is! Element) return false;
|
| + Element element = needle;
|
| + return element.parentNode == _node;
|
| + }
|
| +
|
| + Iterable<Element> get reversed => _filtered.reversed;
|
| +
|
| + void sort([int compare(Element a, Element b)]) {
|
| + throw new UnsupportedError('Cannot sort filtered list');
|
| + }
|
| +
|
| + void setRange(int start, int end, Iterable<Element> iterable,
|
| + [int skipCount = 0]) {
|
| + throw new UnsupportedError('Cannot setRange on filtered list');
|
| + }
|
| +
|
| + void fillRange(int start, int end, [Element fillValue]) {
|
| + throw new UnsupportedError('Cannot fillRange on filtered list');
|
| + }
|
| +
|
| + void replaceRange(int start, int end, Iterable<Element> iterable) {
|
| + throw new UnsupportedError('Cannot replaceRange on filtered list');
|
| + }
|
| +
|
| + void removeRange(int start, int end) {
|
| + new List.from(_iterable.skip(start).take(end - start))
|
| + .forEach((el) => el.remove());
|
| + }
|
| +
|
| + void clear() {
|
| + // Currently, ElementList#clear clears even non-element nodes, so we follow
|
| + // that behavior.
|
| + _childNodes.clear();
|
| + }
|
| +
|
| + Element removeLast() {
|
| + final result = _iterable.last;
|
| + if (result != null) {
|
| + result.remove();
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + void insert(int index, Element value) {
|
| + if (index == length) {
|
| + add(value);
|
| + } else {
|
| + var element = _iterable.elementAt(index);
|
| + element.parentNode.insertBefore(value, element);
|
| + }
|
| + }
|
| +
|
| + void insertAll(int index, Iterable<Element> iterable) {
|
| + if (index == length) {
|
| + addAll(iterable);
|
| + } else {
|
| + var element = _iterable.elementAt(index);
|
| + element.parentNode.insertAllBefore(iterable, element);
|
| + }
|
| + }
|
| +
|
| + Element removeAt(int index) {
|
| + final result = this[index];
|
| + result.remove();
|
| + return result;
|
| + }
|
| +
|
| + bool remove(Object element) {
|
| + if (element is! Element) return false;
|
| + if (contains(element)) {
|
| + (element as Element).remove(); // Placate the type checker
|
| + return true;
|
| + } else {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + int get length => _iterable.length;
|
| + Element operator [](int index) => _iterable.elementAt(index);
|
| + // This cannot use the iterator, because operations during iteration might
|
| + // modify the collection, e.g. addAll might append a node to another parent.
|
| + Iterator<Element> get iterator => _filtered.iterator;
|
| +
|
| + List<Node> get rawList => _node.childNodes;
|
| +}
|
|
|