OLD | NEW |
1 part of angular.filter; | 1 part of angular.formatter_internal; |
2 | 2 |
3 typedef dynamic Mapper(dynamic e); | 3 typedef dynamic _Mapper(dynamic e); |
4 | 4 |
5 /** | 5 /** |
6 * Orders the provided [Iterable] by the `expression` predicate. | 6 * Orders the provided [Iterable] by the `expression` predicate. |
7 * | 7 * |
8 * Example 1: Simple array and single/empty expression. | 8 * Example 1: Simple array and single/empty expression. |
9 * | 9 * |
10 * Assume that you have an array on scope called `colors` and that it has a list | 10 * Assume that you have an array on scope called `colors` and that it has a list |
11 * of these strings – `['red', 'blue', 'green']`. You might sort these in | 11 * of these strings – `['red', 'blue', 'green']`. You might sort these in |
12 * ascending order this way: | 12 * ascending order this way: |
13 * | 13 * |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 * For example, one might want to sort the authors list, first by last name and | 97 * For example, one might want to sort the authors list, first by last name and |
98 * then by first name when the last names are equal. You would do that like | 98 * then by first name when the last names are equal. You would do that like |
99 * this: | 99 * this: |
100 * | 100 * |
101 * <li ng-repeat="author in authors | orderBy:['lastName', 'firstName']"> | 101 * <li ng-repeat="author in authors | orderBy:['lastName', 'firstName']"> |
102 * | 102 * |
103 * The items in such a list may either be string expressions or callables. The | 103 * The items in such a list may either be string expressions or callables. The |
104 * list itself might be provided as an expression that is looked up on the scope | 104 * list itself might be provided as an expression that is looked up on the scope |
105 * chain. | 105 * chain. |
106 */ | 106 */ |
107 @NgFilter(name: 'orderBy') | 107 @Formatter(name: 'orderBy') |
108 class OrderByFilter { | 108 class OrderBy implements Function { |
109 Parser _parser; | 109 Parser _parser; |
110 | 110 |
111 OrderByFilter(this._parser); | 111 OrderBy(this._parser); |
112 | 112 |
113 static _nop(e) => e; | 113 static _nop(e) => e; |
114 static bool _isNonZero(int n) => (n != 0); | 114 static bool _isNonZero(int n) => (n != 0); |
115 static int _returnZero() => 0; | 115 static int _returnZero() => 0; |
116 static int _defaultComparator(a, b) => Comparable.compare(a, b); | 116 static int _defaultComparator(a, b) => Comparable.compare(a, b); |
117 static int _reverseComparator(a, b) => _defaultComparator(b, a); | 117 static int _reverseComparator(a, b) => _defaultComparator(b, a); |
118 | 118 |
119 static int _compareLists(List a, List b, List<Comparator> comparators) { | 119 static int _compareLists(List a, List b, List<Comparator> comparators) { |
120 return new Iterable.generate(a.length, (i) => comparators[i](a[i], b[i])) | 120 return new Iterable.generate(a.length, (i) => comparators[i](a[i], b[i])) |
121 .firstWhere(_isNonZero, orElse: _returnZero); | 121 .firstWhere(_isNonZero, orElse: _returnZero); |
122 } | 122 } |
123 | 123 |
124 static List _sorted( | 124 static List _sorted( |
125 List items, List<Mapper> mappers, List<Comparator> comparators, bool desce
nding) { | 125 List items, List<_Mapper> mappers, List<Comparator> comparators, bool desc
ending) { |
126 // Do the standard decorate-sort-undecorate aka Schwartzian dance since Dart | 126 // Do the standard decorate-sort-undecorate aka Schwartzian dance since Dart |
127 // doesn't support a key/transform parameter to sort(). | 127 // doesn't support a key/transform parameter to sort(). |
128 // Ref: http://en.wikipedia.org/wiki/Schwartzian_transform | 128 // Ref: http://en.wikipedia.org/wiki/Schwartzian_transform |
129 mapper(e) => mappers.map((m) => m(e)).toList(growable: false); | 129 mapper(e) => mappers.map((m) => m(e)).toList(growable: false); |
130 List decorated = items.map(mapper).toList(growable: false); | 130 List decorated = items.map(mapper).toList(growable: false); |
131 List<int> indices = new Iterable.generate(decorated.length, _nop).toList(gro
wable: false); | 131 List<int> indices = new Iterable.generate(decorated.length, _nop).toList(gro
wable: false); |
132 comparator(i, j) => _compareLists(decorated[i], decorated[j], comparators); | 132 comparator(i, j) => _compareLists(decorated[i], decorated[j], comparators); |
133 indices.sort((descending) ? (i, j) => comparator(j, i) : comparator); | 133 indices.sort((descending) ? (i, j) => comparator(j, i) : comparator); |
134 return indices.map((i) => items[i]).toList(growable: false); | 134 return indices.map((i) => items[i]).toList(growable: false); |
135 } | 135 } |
136 | 136 |
137 /** | 137 /** |
138 * expression: String/Function or Array of String/Function. | 138 * expression: String/Function or Array of String/Function. |
139 */ | 139 */ |
140 List call(List items, var expression, [bool descending=false]) { | 140 List call(List items, var expression, [bool descending=false]) { |
141 if (items == null) { | 141 if (items == null) { |
142 return null; | 142 return null; |
143 } | 143 } |
144 List expressions = null; | 144 List expressions = null; |
145 if (expression is String || expression is Mapper) { | 145 if (expression is String || expression is _Mapper) { |
146 expressions = [expression]; | 146 expressions = [expression]; |
147 } else if (expression is List) { | 147 } else if (expression is List) { |
148 expressions = expression as List; | 148 expressions = expression as List; |
149 } | 149 } |
150 if (expressions == null || expressions.length == 0) { | 150 if (expressions == null || expressions.length == 0) { |
151 // AngularJS behavior. You must have an expression to get any work done. | 151 // AngularJS behavior. You must have an expression to get any work done. |
152 return items; | 152 return items; |
153 } | 153 } |
154 int numExpressions = expressions.length; | 154 int numExpressions = expressions.length; |
155 List<Mapper> mappers = new List(numExpressions); | 155 List<_Mapper> mappers = new List(numExpressions); |
156 List<Comparator> comparators = new List<Comparator>(numExpressions); | 156 List<Comparator> comparators = new List<Comparator>(numExpressions); |
157 for (int i = 0; i < numExpressions; i++) { | 157 for (int i = 0; i < numExpressions; i++) { |
158 expression = expressions[i]; | 158 expression = expressions[i]; |
159 if (expression is String) { | 159 if (expression is String) { |
160 var strExp = expression as String; | 160 var strExp = expression as String; |
161 var desc = false; | 161 var desc = false; |
162 if (strExp.startsWith('-') || strExp.startsWith('+')) { | 162 if (strExp.startsWith('-') || strExp.startsWith('+')) { |
163 desc = strExp.startsWith('-'); | 163 desc = strExp.startsWith('-'); |
164 strExp = strExp.substring(1); | 164 strExp = strExp.substring(1); |
165 } | 165 } |
166 comparators[i] = desc ? _reverseComparator : _defaultComparator; | 166 comparators[i] = desc ? _reverseComparator : _defaultComparator; |
167 if (strExp == '') { | 167 if (strExp == '') { |
168 mappers[i] = _nop; | 168 mappers[i] = _nop; |
169 } else { | 169 } else { |
170 Expression parsed = _parser(strExp); | 170 Expression parsed = _parser(strExp); |
171 mappers[i] = (e) => parsed.eval(e); | 171 mappers[i] = (e) => parsed.eval(e); |
172 } | 172 } |
173 } else if (expression is Mapper) { | 173 } else if (expression is _Mapper) { |
174 mappers[i] = (expression as Mapper); | 174 mappers[i] = (expression as _Mapper); |
175 comparators[i] = _defaultComparator; | 175 comparators[i] = _defaultComparator; |
176 } | 176 } |
177 } | 177 } |
178 return _sorted(items, mappers, comparators, descending); | 178 return _sorted(items, mappers, comparators, descending); |
179 } | 179 } |
180 } | 180 } |
OLD | NEW |