OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of html_common; | 5 part of html_common; |
6 | 6 |
7 /** | 7 /** |
8 * An indexable collection of a node's descendants in the document tree, | 8 * An indexable collection of a node's descendants in the document tree, |
9 * filtered so that only elements are in the collection. | 9 * filtered so that only elements are in the collection. |
10 */ | 10 */ |
11 class FilteredElementList implements List { | 11 class FilteredElementList implements List { |
12 final Node _node; | 12 final Node _node; |
13 final List<Node> _childNodes; | 13 final List<Node> _childNodes; |
14 | 14 |
15 /** | 15 /** |
16 * Creates a collection of the elements that descend from a node. | 16 * Creates a collection of the elements that descend from a node. |
17 * | 17 * |
18 * Example usage: | 18 * Example usage: |
19 * | 19 * |
20 * var filteredElements = new FilteredElementList(query("#container")); | 20 * var filteredElements = new FilteredElementList(query("#container")); |
21 * // filteredElements is [a, b, c]. | 21 * // filteredElements is [a, b, c]. |
22 */ | 22 */ |
23 FilteredElementList(Node node): _childNodes = node.nodes, _node = node; | 23 FilteredElementList(Node node): _childNodes = node.nodes, _node = node; |
24 | 24 |
25 // We can't memoize this, since it's possible that children will be messed | 25 // We can't memoize this, since it's possible that children will be messed |
26 // with externally to this class. | 26 // with externally to this class. |
27 // | 27 // |
28 // TODO(nweiz): Do we really need to copy the list to make the types work out? | 28 // TODO(nweiz): we don't always need to create a new list. For example |
| 29 // forEach, every, any, ... could directly work on the _childNodes. |
29 List<Element> get _filtered => | 30 List<Element> get _filtered => |
30 new List.from(_childNodes.filter((n) => n is Element)); | 31 new List<Element>.from(_childNodes.where((n) => n is Element)); |
31 | 32 |
32 void forEach(void f(Element element)) { | 33 void forEach(void f(Element element)) { |
33 _filtered.forEach(f); | 34 _filtered.forEach(f); |
34 } | 35 } |
35 | 36 |
36 void operator []=(int index, Element value) { | 37 void operator []=(int index, Element value) { |
37 this[index].replaceWith(value); | 38 this[index].replaceWith(value); |
38 } | 39 } |
39 | 40 |
40 void set length(int newLength) { | 41 void set length(int newLength) { |
41 final len = this.length; | 42 final len = this.length; |
42 if (newLength >= len) { | 43 if (newLength >= len) { |
43 return; | 44 return; |
44 } else if (newLength < 0) { | 45 } else if (newLength < 0) { |
45 throw new ArgumentError("Invalid list length"); | 46 throw new ArgumentError("Invalid list length"); |
46 } | 47 } |
47 | 48 |
48 removeRange(newLength, len - newLength); | 49 removeRange(newLength, len - newLength); |
49 } | 50 } |
50 | 51 |
| 52 String join([String separator]) => _filtered.join(separator); |
| 53 |
51 void add(Element value) { | 54 void add(Element value) { |
52 _childNodes.add(value); | 55 _childNodes.add(value); |
53 } | 56 } |
54 | 57 |
55 void addAll(Collection<Element> collection) { | 58 void addAll(Iterable<Element> iterable) { |
56 collection.forEach(add); | 59 for (Element element in iterable) { |
| 60 add(element); |
| 61 } |
57 } | 62 } |
58 | 63 |
59 void addLast(Element value) { | 64 void addLast(Element value) { |
60 add(value); | 65 add(value); |
61 } | 66 } |
62 | 67 |
63 bool contains(Element element) { | 68 bool contains(Element element) { |
64 return element is Element && _childNodes.contains(element); | 69 return element is Element && _childNodes.contains(element); |
65 } | 70 } |
66 | 71 |
(...skipping 20 matching lines...) Expand all Loading... |
87 } | 92 } |
88 | 93 |
89 Element removeLast() { | 94 Element removeLast() { |
90 final result = this.last; | 95 final result = this.last; |
91 if (result != null) { | 96 if (result != null) { |
92 result.remove(); | 97 result.remove(); |
93 } | 98 } |
94 return result; | 99 return result; |
95 } | 100 } |
96 | 101 |
| 102 Iterable mappedBy(f(Element element)) => _filtered.mappedBy(f); |
| 103 Iterable<Element> where(bool f(Element element)) => _filtered.where(f); |
| 104 |
97 Element removeAt(int index) { | 105 Element removeAt(int index) { |
98 final result = this[index]; | 106 final result = this[index]; |
99 result.remove(); | 107 result.remove(); |
100 return result; | 108 return result; |
101 } | 109 } |
102 | 110 |
103 dynamic reduce(dynamic initialValue, | 111 dynamic reduce(dynamic initialValue, |
104 dynamic combine(dynamic previousValue, Element element)) { | 112 dynamic combine(dynamic previousValue, Element element)) { |
105 return Collections.reduce(this, initialValue, combine); | 113 return Collections.reduce(this, initialValue, combine); |
106 } | 114 } |
107 Collection map(f(Element element)) => _filtered.map(f); | |
108 Collection<Element> filter(bool f(Element element)) => _filtered.filter(f); | |
109 bool every(bool f(Element element)) => _filtered.every(f); | 115 bool every(bool f(Element element)) => _filtered.every(f); |
110 bool some(bool f(Element element)) => _filtered.some(f); | 116 bool any(bool f(Element element)) => _filtered.any(f); |
| 117 Element firstMatching(bool test(Element value), {Element orElse()}) { |
| 118 return _filtered.firstMatching(test, orElse: orElse); |
| 119 } |
| 120 |
| 121 Element lastMatching(bool test(Element value), {Element orElse()}) { |
| 122 return _filtered.lastMatching(test, orElse: orElse); |
| 123 } |
| 124 |
| 125 Element singleMatching(bool test(Element value)) { |
| 126 return _filtered.singleMatching(test); |
| 127 } |
| 128 |
| 129 E elementAt(int index) { |
| 130 return this[index]; |
| 131 } |
| 132 |
| 133 |
111 bool get isEmpty => _filtered.isEmpty; | 134 bool get isEmpty => _filtered.isEmpty; |
112 int get length => _filtered.length; | 135 int get length => _filtered.length; |
113 Element operator [](int index) => _filtered[index]; | 136 Element operator [](int index) => _filtered[index]; |
114 Iterator<Element> iterator() => _filtered.iterator(); | 137 Iterator<Element> get iterator => _filtered.iterator; |
115 List<Element> getRange(int start, int rangeLength) => | 138 List<Element> getRange(int start, int rangeLength) => |
116 _filtered.getRange(start, rangeLength); | 139 _filtered.getRange(start, rangeLength); |
117 int indexOf(Element element, [int start = 0]) => | 140 int indexOf(Element element, [int start = 0]) => |
118 _filtered.indexOf(element, start); | 141 _filtered.indexOf(element, start); |
119 | 142 |
120 int lastIndexOf(Element element, [int start = null]) { | 143 int lastIndexOf(Element element, [int start = null]) { |
121 if (start == null) start = length - 1; | 144 if (start == null) start = length - 1; |
122 return _filtered.lastIndexOf(element, start); | 145 return _filtered.lastIndexOf(element, start); |
123 } | 146 } |
124 | 147 |
| 148 Iterable<Element> take(int n) { |
| 149 return new TakeIterable<Element>(this, n); |
| 150 } |
| 151 |
| 152 Iterable<Element> takeWhile(bool test(Element value)) { |
| 153 return new TakeWhileIterable<Element>(this, test); |
| 154 } |
| 155 |
| 156 Iterable<Element> skip(int n) { |
| 157 return new SkipIterable<Element>(this, n); |
| 158 } |
| 159 |
| 160 Iterable<Element> skipWhile(bool test(Element value)) { |
| 161 return new SkipWhileIterable<Element>(this, test); |
| 162 } |
| 163 |
125 Element get first => _filtered.first; | 164 Element get first => _filtered.first; |
126 | 165 |
127 Element get last => _filtered.last; | 166 Element get last => _filtered.last; |
| 167 |
| 168 Element get single => _filtered.single; |
| 169 |
| 170 Element min([int compare(Element a, Element b)]) => _filtered.min(compare); |
| 171 |
| 172 Element max([int compare(Element a, Element b)]) => _filtered.max(compare); |
128 } | 173 } |
OLD | NEW |