OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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; | 5 part of html; |
6 | 6 |
7 /** | 7 /** |
8 * A set (union) of the CSS classes that are present in a set of elements. | 8 * A set (union) of the CSS classes that are present in a set of elements. |
9 * Implemented separately from _ElementCssClassSet for performance. | 9 * Implemented separately from _ElementCssClassSet for performance. |
10 */ | 10 */ |
11 class _MultiElementCssClassSet extends CssClassSetImpl { | 11 class _MultiElementCssClassSet extends CssClassSetImpl { |
12 final Iterable<Element> _elementIterable; | 12 final Iterable<Element> _elementIterable; |
13 | 13 |
14 // TODO(sra): Perhaps we should store the DomTokenList instead. | 14 // TODO(sra): Perhaps we should store the DomTokenList instead. |
15 final List<CssClassSetImpl> _sets; | 15 final List<CssClassSetImpl> _sets; |
16 | 16 |
17 factory _MultiElementCssClassSet(Iterable<Element> elements) { | 17 factory _MultiElementCssClassSet(Iterable<Element> elements) { |
18 return new _MultiElementCssClassSet._(elements, | 18 return new _MultiElementCssClassSet._( |
19 elements.map((Element e) => e.classes).toList()); | 19 elements, elements.map((Element e) => e.classes).toList()); |
20 } | 20 } |
21 | 21 |
22 _MultiElementCssClassSet._(this._elementIterable, this._sets); | 22 _MultiElementCssClassSet._(this._elementIterable, this._sets); |
23 | 23 |
24 Set<String> readClasses() { | 24 Set<String> readClasses() { |
25 var s = new LinkedHashSet<String>(); | 25 var s = new LinkedHashSet<String>(); |
26 _sets.forEach((CssClassSetImpl e) => s.addAll(e.readClasses())); | 26 _sets.forEach((CssClassSetImpl e) => s.addAll(e.readClasses())); |
27 return s; | 27 return s; |
28 } | 28 } |
29 | 29 |
30 void writeClasses(Set<String> s) { | 30 void writeClasses(Set<String> s) { |
31 var classes = s.join(' '); | 31 var classes = s.join(' '); |
32 for (Element e in _elementIterable) { | 32 for (Element e in _elementIterable) { |
33 e.className = classes; | 33 e.className = classes; |
34 } | 34 } |
35 } | 35 } |
36 | 36 |
37 /** | 37 /** |
38 * Helper method used to modify the set of css classes on this element. | 38 * Helper method used to modify the set of css classes on this element. |
39 * | 39 * |
40 * f - callback with: | 40 * f - callback with: |
41 * s - a Set of all the css class name currently on this element. | 41 * s - a Set of all the css class name currently on this element. |
42 * | 42 * |
43 * After f returns, the modified set is written to the | 43 * After f returns, the modified set is written to the |
44 * className property of this element. | 44 * className property of this element. |
45 */ | 45 */ |
46 modify( f(Set<String> s)) { | 46 modify(f(Set<String> s)) { |
47 _sets.forEach((CssClassSetImpl e) => e.modify(f)); | 47 _sets.forEach((CssClassSetImpl e) => e.modify(f)); |
48 } | 48 } |
49 | 49 |
50 /** | 50 /** |
51 * Adds the class [value] to the element if it is not on it, removes it if it | 51 * Adds the class [value] to the element if it is not on it, removes it if it |
52 * is. | 52 * is. |
53 * | 53 * |
54 * TODO(sra): It seems wrong to collect a 'changed' flag like this when the | 54 * TODO(sra): It seems wrong to collect a 'changed' flag like this when the |
55 * underlying toggle returns an 'is set' flag. | 55 * underlying toggle returns an 'is set' flag. |
56 */ | 56 */ |
57 bool toggle(String value, [bool shouldAdd]) => | 57 bool toggle(String value, [bool shouldAdd]) => _sets.fold( |
58 _sets.fold(false, | 58 false, |
59 (bool changed, CssClassSetImpl e) => | 59 (bool changed, CssClassSetImpl e) => |
60 e.toggle(value, shouldAdd) || changed); | 60 e.toggle(value, shouldAdd) || changed); |
61 | 61 |
62 /** | 62 /** |
63 * Remove the class [value] from element, and return true on successful | 63 * Remove the class [value] from element, and return true on successful |
64 * removal. | 64 * removal. |
65 * | 65 * |
66 * This is the Dart equivalent of jQuery's | 66 * This is the Dart equivalent of jQuery's |
67 * [removeClass](http://api.jquery.com/removeClass/). | 67 * [removeClass](http://api.jquery.com/removeClass/). |
68 */ | 68 */ |
69 bool remove(Object value) => _sets.fold(false, | 69 bool remove(Object value) => _sets.fold( |
70 (bool changed, CssClassSetImpl e) => e.remove(value) || changed); | 70 false, (bool changed, CssClassSetImpl e) => e.remove(value) || changed); |
71 } | 71 } |
72 | 72 |
73 class _ElementCssClassSet extends CssClassSetImpl { | 73 class _ElementCssClassSet extends CssClassSetImpl { |
74 final Element _element; | 74 final Element _element; |
75 | 75 |
76 _ElementCssClassSet(this._element); | 76 _ElementCssClassSet(this._element); |
77 | 77 |
78 Set<String> readClasses() { | 78 Set<String> readClasses() { |
79 var s = new LinkedHashSet<String>(); | 79 var s = new LinkedHashSet<String>(); |
80 var classname = _element.className; | 80 var classname = _element.className; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 } else { | 211 } else { |
212 ++i; | 212 ++i; |
213 } | 213 } |
214 } | 214 } |
215 } | 215 } |
216 | 216 |
217 // A collection of static methods for DomTokenList. These methods are a | 217 // A collection of static methods for DomTokenList. These methods are a |
218 // work-around for the lack of annotations to express the full behaviour of | 218 // work-around for the lack of annotations to express the full behaviour of |
219 // the DomTokenList methods. | 219 // the DomTokenList methods. |
220 | 220 |
221 static DomTokenList _classListOf(Element e) => | 221 static DomTokenList _classListOf(Element e) => JS( |
222 JS('returns:DomTokenList;creates:DomTokenList;effects:none;depends:all;', | 222 'returns:DomTokenList;creates:DomTokenList;effects:none;depends:all;', |
223 '#.classList', e); | 223 '#.classList', |
| 224 e); |
224 | 225 |
225 static int _classListLength(DomTokenList list) => | 226 static int _classListLength(DomTokenList list) => |
226 JS('returns:JSUInt31;effects:none;depends:all;', '#.length', list); | 227 JS('returns:JSUInt31;effects:none;depends:all;', '#.length', list); |
227 | 228 |
228 static bool _classListContains(DomTokenList list, String value) => | 229 static bool _classListContains(DomTokenList list, String value) => |
229 JS('returns:bool;effects:none;depends:all', | 230 JS('returns:bool;effects:none;depends:all', '#.contains(#)', list, value); |
230 '#.contains(#)', list, value); | |
231 | 231 |
232 static bool _classListContainsBeforeAddOrRemove( | 232 static bool _classListContainsBeforeAddOrRemove( |
233 DomTokenList list, String value) => | 233 DomTokenList list, String value) => |
234 // 'throws:never' is a lie, since 'contains' will throw on an illegal | 234 // 'throws:never' is a lie, since 'contains' will throw on an illegal |
235 // token. However, we always call this function immediately prior to | 235 // token. However, we always call this function immediately prior to |
236 // add/remove/toggle with the same token. Often the result of 'contains' | 236 // add/remove/toggle with the same token. Often the result of 'contains' |
237 // is unused and the lie makes it possible for the 'contains' instruction | 237 // is unused and the lie makes it possible for the 'contains' instruction |
238 // to be removed. | 238 // to be removed. |
239 JS('returns:bool;effects:none;depends:all;throws:null(1)', | 239 JS('returns:bool;effects:none;depends:all;throws:null(1)', |
240 '#.contains(#)', list, value); | 240 '#.contains(#)', list, value); |
241 | 241 |
242 static void _classListAdd(DomTokenList list, String value) { | 242 static void _classListAdd(DomTokenList list, String value) { |
243 // list.add(value); | 243 // list.add(value); |
244 JS('', '#.add(#)', list, value); | 244 JS('', '#.add(#)', list, value); |
245 } | 245 } |
246 | 246 |
247 static void _classListRemove(DomTokenList list, String value) { | 247 static void _classListRemove(DomTokenList list, String value) { |
248 // list.remove(value); | 248 // list.remove(value); |
249 JS('', '#.remove(#)', list, value); | 249 JS('', '#.remove(#)', list, value); |
250 } | 250 } |
251 | 251 |
252 static bool _classListToggle1(DomTokenList list, String value) { | 252 static bool _classListToggle1(DomTokenList list, String value) { |
253 return JS('bool', '#.toggle(#)', list, value); | 253 return JS('bool', '#.toggle(#)', list, value); |
254 } | 254 } |
255 | 255 |
256 static bool _classListToggle2( | 256 static bool _classListToggle2( |
257 DomTokenList list, String value, bool shouldAdd) { | 257 DomTokenList list, String value, bool shouldAdd) { |
258 return JS('bool', '#.toggle(#, #)', list, value, shouldAdd); | 258 return JS('bool', '#.toggle(#, #)', list, value, shouldAdd); |
259 } | 259 } |
260 } | 260 } |
OLD | NEW |