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 */ |
(...skipping 10 matching lines...) Expand all Loading... |
21 * var filteredElements = new FilteredElementList(query("#container")); | 21 * var filteredElements = new FilteredElementList(query("#container")); |
22 * // filteredElements is [a, b, c]. | 22 * // filteredElements is [a, b, c]. |
23 */ | 23 */ |
24 FilteredElementList(Node node): _childNodes = node.nodes, _node = node; | 24 FilteredElementList(Node node): _childNodes = node.nodes, _node = node; |
25 | 25 |
26 // We can't memoize this, since it's possible that children will be messed | 26 // We can't memoize this, since it's possible that children will be messed |
27 // with externally to this class. | 27 // with externally to this class. |
28 // | 28 // |
29 // TODO(nweiz): we don't always need to create a new list. For example | 29 // TODO(nweiz): we don't always need to create a new list. For example |
30 // forEach, every, any, ... could directly work on the _childNodes. | 30 // forEach, every, any, ... could directly work on the _childNodes. |
31 List<Element> get _filtered => | 31 List<T> get _filtered => |
32 new List<Element>.from(_childNodes.where((n) => n is Element)); | 32 new List<T>.from(_childNodes.where((n) => n is Element)); |
33 | 33 |
34 void forEach(void f(Element element)) { | 34 void forEach(void f(T element)) { |
35 _filtered.forEach(f); | 35 _filtered.forEach(f); |
36 } | 36 } |
37 | 37 |
38 void operator []=(int index, Element value) { | 38 void operator []=(int index, T value) { |
39 this[index].replaceWith(value); | 39 this[index].replaceWith(value); |
40 } | 40 } |
41 | 41 |
42 void set length(int newLength) { | 42 void set length(int newLength) { |
43 final len = this.length; | 43 final len = this.length; |
44 if (newLength >= len) { | 44 if (newLength >= len) { |
45 return; | 45 return; |
46 } else if (newLength < 0) { | 46 } else if (newLength < 0) { |
47 throw new ArgumentError("Invalid list length"); | 47 throw new ArgumentError("Invalid list length"); |
48 } | 48 } |
49 | 49 |
50 removeRange(newLength, len); | 50 removeRange(newLength, len); |
51 } | 51 } |
52 | 52 |
53 void add(Element value) { | 53 void add(T value) { |
54 _childNodes.add(value); | 54 _childNodes.add(value); |
55 } | 55 } |
56 | 56 |
57 void addAll(Iterable<Element> iterable) { | 57 void addAll(Iterable<T> iterable) { |
58 for (Element element in iterable) { | 58 for (T element in iterable) { |
59 add(element); | 59 add(element); |
60 } | 60 } |
61 } | 61 } |
62 | 62 |
63 bool contains(Object needle) { | 63 bool contains(Object needle) { |
64 if (needle is! Element) return false; | 64 if (needle is! Element) return false; |
65 Element element = needle; | 65 T element = needle; |
66 return element.parentNode == _node; | 66 return element.parentNode == _node; |
67 } | 67 } |
68 | 68 |
69 Iterable<Element> get reversed => _filtered.reversed; | 69 Iterable<T> get reversed => _filtered.reversed; |
70 | 70 |
71 void sort([int compare(Element a, Element b)]) { | 71 void sort([int compare(T a, T b)]) { |
72 throw new UnsupportedError('Cannot sort filtered list'); | 72 throw new UnsupportedError('Cannot sort filtered list'); |
73 } | 73 } |
74 | 74 |
75 void setRange(int start, int end, Iterable<Element> iterable, | 75 void setRange(int start, int end, Iterable<T> iterable, |
76 [int skipCount = 0]) { | 76 [int skipCount = 0]) { |
77 throw new UnsupportedError('Cannot setRange on filtered list'); | 77 throw new UnsupportedError('Cannot setRange on filtered list'); |
78 } | 78 } |
79 | 79 |
80 void fillRange(int start, int end, [Element fillValue]) { | 80 void fillRange(int start, int end, [T fillValue]) { |
81 throw new UnsupportedError('Cannot fillRange on filtered list'); | 81 throw new UnsupportedError('Cannot fillRange on filtered list'); |
82 } | 82 } |
83 | 83 |
84 void replaceRange(int start, int end, Iterable<Element> iterable) { | 84 void replaceRange(int start, int end, Iterable<T> iterable) { |
85 throw new UnsupportedError('Cannot replaceRange on filtered list'); | 85 throw new UnsupportedError('Cannot replaceRange on filtered list'); |
86 } | 86 } |
87 | 87 |
88 void removeRange(int start, int end) { | 88 void removeRange(int start, int end) { |
89 _filtered.sublist(start, end).forEach((el) => el.remove()); | 89 _filtered.sublist(start, end).forEach((el) => el.remove()); |
90 } | 90 } |
91 | 91 |
92 void clear() { | 92 void clear() { |
93 // Currently, ElementList#clear clears even non-element nodes, so we follow | 93 // Currently, ElementList#clear clears even non-element nodes, so we follow |
94 // that behavior. | 94 // that behavior. |
95 _childNodes.clear(); | 95 _childNodes.clear(); |
96 } | 96 } |
97 | 97 |
98 Element removeLast() { | 98 T removeLast() { |
99 final result = this.last; | 99 final result = this.last; |
100 if (result != null) { | 100 if (result != null) { |
101 result.remove(); | 101 result.remove(); |
102 } | 102 } |
103 return result; | 103 return result; |
104 } | 104 } |
105 | 105 |
106 void insert(int index, Element value) { | 106 void insert(int index, T value) { |
107 _childNodes.insert(index, value); | 107 _childNodes.insert(index, value); |
108 } | 108 } |
109 | 109 |
110 void insertAll(int index, Iterable<Element> iterable) { | 110 void insertAll(int index, Iterable<T> iterable) { |
111 _childNodes.insertAll(index, iterable); | 111 _childNodes.insertAll(index, iterable); |
112 } | 112 } |
113 | 113 |
114 Element removeAt(int index) { | 114 T removeAt(int index) { |
115 final result = this[index]; | 115 final result = this[index]; |
116 result.remove(); | 116 result.remove(); |
117 return result; | 117 return result; |
118 } | 118 } |
119 | 119 |
120 bool remove(Object element) { | 120 bool remove(Object element) { |
121 if (element is! Element) return false; | 121 if (element is! Element) return false; |
122 for (int i = 0; i < length; i++) { | 122 for (int i = 0; i < length; i++) { |
123 Element indexElement = this[i]; | 123 T indexElement = this[i]; |
124 if (identical(indexElement, element)) { | 124 if (identical(indexElement, element)) { |
125 indexElement.remove(); | 125 indexElement.remove(); |
126 return true; | 126 return true; |
127 } | 127 } |
128 } | 128 } |
129 return false; | 129 return false; |
130 } | 130 } |
131 | 131 |
132 int get length => _filtered.length; | 132 int get length => _filtered.length; |
133 Element operator [](int index) => _filtered[index]; | 133 T operator [](int index) => _filtered[index]; |
134 Iterator<Element> get iterator => _filtered.iterator; | 134 Iterator<T> get iterator => _filtered.iterator; |
135 | 135 |
136 List<Node> get rawList => _node.childNodes; | 136 List<Node> get rawList => _node.childNodes; |
137 } | 137 } |
OLD | NEW |