Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 $LIBRARYNAME; | 5 part of $LIBRARYNAME; |
| 6 | 6 |
| 7 class _ChildrenElementList extends ListBase<Element> { | 7 class _ChildrenElementList extends ListBase<Element> { |
| 8 // Raw Element. | 8 // Raw Element. |
| 9 final Element _element; | 9 final Element _element; |
| 10 final HtmlCollection _childElements; | 10 final HtmlCollection _childElements; |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 Element get single { | 134 Element get single { |
| 135 if (length > 1) throw new StateError("More than one element"); | 135 if (length > 1) throw new StateError("More than one element"); |
| 136 return first; | 136 return first; |
| 137 } | 137 } |
| 138 } | 138 } |
| 139 | 139 |
| 140 // TODO(jacobr): this is an inefficient implementation but it is hard to see | 140 // TODO(jacobr): this is an inefficient implementation but it is hard to see |
| 141 // a better option given that we cannot quite force NodeList to be an | 141 // a better option given that we cannot quite force NodeList to be an |
| 142 // ElementList as there are valid cases where a NodeList JavaScript object | 142 // ElementList as there are valid cases where a NodeList JavaScript object |
| 143 // contains Node objects that are not Elements. | 143 // contains Node objects that are not Elements. |
| 144 class _FrozenElementList<T extends Element> extends ListBase<T> { | 144 /** |
| 145 * An immutable list containing HTML elements. This list contains some | |
| 146 * additional methods for ease of CSS manipulation on a group of elements. | |
| 147 */ | |
| 148 class HtmlList<T extends Element> extends ListBase<T> { | |
|
Emily Fortuna
2013/05/03 20:03:50
Is this "T extends Element" correct? I'm confused
blois
2013/05/03 20:13:37
Can we make this HtmlList and have it just be an i
| |
| 145 final List<Node> _nodeList; | 149 final List<Node> _nodeList; |
| 146 | 150 |
| 147 _FrozenElementList._wrap(this._nodeList); | 151 HtmlList._wrap(this._nodeList); |
| 148 | 152 |
| 149 int get length => _nodeList.length; | 153 int get length => _nodeList.length; |
| 150 | 154 |
| 151 Element operator [](int index) => _nodeList[index]; | 155 Element operator [](int index) => _nodeList[index]; |
| 152 | 156 |
| 153 void operator []=(int index, Element value) { | 157 void operator []=(int index, Element value) { |
| 154 throw new UnsupportedError('Cannot modify list'); | 158 throw new UnsupportedError('Cannot modify list'); |
| 155 } | 159 } |
| 156 | 160 |
| 157 void set length(int newLength) { | 161 void set length(int newLength) { |
| 158 throw new UnsupportedError('Cannot modify list'); | 162 throw new UnsupportedError('Cannot modify list'); |
| 159 } | 163 } |
| 160 | 164 |
| 161 void sort([Comparator<Element> compare]) { | 165 void sort([Comparator<Element> compare]) { |
| 162 throw new UnsupportedError('Cannot sort list'); | 166 throw new UnsupportedError('Cannot sort list'); |
| 163 } | 167 } |
| 164 | 168 |
| 165 Element get first => _nodeList.first; | 169 Element get first => _nodeList.first; |
| 166 | 170 |
| 167 Element get last => _nodeList.last; | 171 Element get last => _nodeList.last; |
| 168 | 172 |
| 169 Element get single => _nodeList.single; | 173 Element get single => _nodeList.single; |
| 174 | |
| 175 /** | |
| 176 * The union of all CSS classes applied to the elements in this list. | |
| 177 * | |
| 178 * This set makes it easy to add, remove or toggle (add if not present, remove | |
| 179 * if present) the classes applied to a collection of elements. | |
| 180 * | |
| 181 * htmlList.classes.add('selected'); | |
| 182 * htmlList.classes.toggle('isOnline'); | |
| 183 * htmlList.classes.remove('selected'); | |
| 184 */ | |
| 185 CssClassSet get classes => new _MultiElementCssClassSet( | |
| 186 _nodeList.where((e) => e is Element)); | |
| 187 | |
| 188 /** Replace the classes with `value` for every element in this list. */ | |
| 189 void set classes(Iterable<String> value) { | |
| 190 _nodeList.where((e) => e is Element).forEach((e) { | |
| 191 e.classes.clear(); | |
| 192 e.classes.addAll(value); | |
| 193 }); | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 /** | |
| 198 * A set (union) of the CSS classes that are present in a set of elements. | |
| 199 * Implemented separately from _ElementCssClassSet for performance. | |
| 200 */ | |
| 201 class _MultiElementCssClassSet extends CssClassSet { | |
| 202 final Iterable<Element> _elementIterable; | |
| 203 Iterable<_ElementCssClassSet> _elementCssClassSetIterable; | |
| 204 | |
| 205 _MultiElementCssClassSet(this._elementIterable) { | |
| 206 _elementCssClassSetIterable = new List.from(_elementIterable).map( | |
| 207 (e) => new _ElementCssClassSet(e)); | |
| 208 } | |
| 209 | |
| 210 Set<String> readClasses() { | |
| 211 var s = new LinkedHashSet<String>(); | |
| 212 _elementCssClassSetIterable.forEach((e) => s.addAll(e.readClasses())); | |
| 213 return s; | |
| 214 } | |
| 215 | |
| 216 void writeClasses(Set<String> s) { | |
| 217 var classes = new List.from(s).join(' '); | |
| 218 for (Element e in _elementIterable) { | |
| 219 e.$dom_className = classes; | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 /** | |
| 224 * Helper method used to modify the set of css classes on this element. | |
| 225 * | |
| 226 * f - callback with: | |
| 227 * s - a Set of all the css class name currently on this element. | |
| 228 * | |
| 229 * After f returns, the modified set is written to the | |
| 230 * className property of this element. | |
| 231 */ | |
| 232 void modify( f(Set<String> s)) { | |
| 233 _elementCssClassSetIterable.forEach((e) => e.modify(f)); | |
| 234 } | |
| 235 | |
| 236 /** | |
| 237 * Adds the class [value] to the element if it is not on it, removes it if it | |
| 238 * is. | |
| 239 */ | |
| 240 bool toggle(String value) => | |
| 241 _modifyWithReturnValue((e) => e.toggle(value)); | |
| 242 | |
| 243 /** | |
| 244 * Remove the class [value] from element, and return true on successful | |
| 245 * removal. | |
| 246 * | |
| 247 * This is the Dart equivalent of jQuery's | |
| 248 * [removeClass](http://api.jquery.com/removeClass/). | |
| 249 */ | |
| 250 bool remove(Object value) => _modifyWithReturnValue((e) => e.remove(value)); | |
| 251 | |
| 252 bool _modifyWithReturnValue(f) => _elementCssClassSetIterable.fold( | |
| 253 false, (prevValue, element) => f(element) || prevValue); | |
| 170 } | 254 } |
| 171 | 255 |
| 172 class _ElementCssClassSet extends CssClassSet { | 256 class _ElementCssClassSet extends CssClassSet { |
| 173 | 257 |
| 174 final Element _element; | 258 final Element _element; |
| 175 | 259 |
| 176 _ElementCssClassSet(this._element); | 260 _ElementCssClassSet(this._element); |
| 177 | 261 |
| 178 Set<String> readClasses() { | 262 Set<String> readClasses() { |
| 179 var s = new LinkedHashSet<String>(); | 263 var s = new LinkedHashSet<String>(); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 } | 366 } |
| 283 | 367 |
| 284 /** | 368 /** |
| 285 * Finds all descendent elements of this element that match the specified | 369 * Finds all descendent elements of this element that match the specified |
| 286 * group of selectors. | 370 * group of selectors. |
| 287 * | 371 * |
| 288 * [selectors] should be a string using CSS selector syntax. | 372 * [selectors] should be a string using CSS selector syntax. |
| 289 * | 373 * |
| 290 * var items = element.query('.itemClassName'); | 374 * var items = element.query('.itemClassName'); |
| 291 */ | 375 */ |
| 292 List<Element> queryAll(String selectors) => | 376 HtmlList<Element> queryAll(String selectors) => |
| 293 new _FrozenElementList._wrap($dom_querySelectorAll(selectors)); | 377 new HtmlList._wrap($dom_querySelectorAll(selectors)); |
| 294 | 378 |
| 295 /** | 379 /** |
| 296 * The set of CSS classes applied to this element. | 380 * The set of CSS classes applied to this element. |
| 297 * | 381 * |
| 298 * This set makes it easy to add, remove or toggle the classes applied to | 382 * This set makes it easy to add, remove or toggle the classes applied to |
| 299 * this element. | 383 * this element. |
| 300 * | 384 * |
| 301 * element.classes.add('selected'); | 385 * element.classes.add('selected'); |
| 302 * element.classes.toggle('isOnline'); | 386 * element.classes.toggle('isOnline'); |
| 303 * element.classes.remove('selected'); | 387 * element.classes.remove('selected'); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 774 const ScrollAlignment._internal(this._value); | 858 const ScrollAlignment._internal(this._value); |
| 775 toString() => 'ScrollAlignment.$_value'; | 859 toString() => 'ScrollAlignment.$_value'; |
| 776 | 860 |
| 777 /// Attempt to align the element to the top of the scrollable area. | 861 /// Attempt to align the element to the top of the scrollable area. |
| 778 static const TOP = const ScrollAlignment._internal('TOP'); | 862 static const TOP = const ScrollAlignment._internal('TOP'); |
| 779 /// Attempt to center the element in the scrollable area. | 863 /// Attempt to center the element in the scrollable area. |
| 780 static const CENTER = const ScrollAlignment._internal('CENTER'); | 864 static const CENTER = const ScrollAlignment._internal('CENTER'); |
| 781 /// Attempt to align the element to the bottom of the scrollable area. | 865 /// Attempt to align the element to the bottom of the scrollable area. |
| 782 static const BOTTOM = const ScrollAlignment._internal('BOTTOM'); | 866 static const BOTTOM = const ScrollAlignment._internal('BOTTOM'); |
| 783 } | 867 } |
| OLD | NEW |