mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-15 18:23:09 +00:00
refacter(filters): convert filter/limitTo/orderBy from type augmentation to filters
This commit is contained in:
parent
3972d2a89b
commit
dd9151e522
11 changed files with 556 additions and 528 deletions
3
angularFiles.js
vendored
3
angularFiles.js
vendored
|
|
@ -15,7 +15,10 @@ angularFiles = {
|
||||||
'src/service/document.js',
|
'src/service/document.js',
|
||||||
'src/service/exceptionHandler.js',
|
'src/service/exceptionHandler.js',
|
||||||
'src/service/filter.js',
|
'src/service/filter.js',
|
||||||
|
'src/service/filter/filter.js',
|
||||||
'src/service/filter/filters.js',
|
'src/service/filter/filters.js',
|
||||||
|
'src/service/filter/limitTo.js',
|
||||||
|
'src/service/filter/orderBy.js',
|
||||||
'src/service/formFactory.js',
|
'src/service/formFactory.js',
|
||||||
'src/service/location.js',
|
'src/service/location.js',
|
||||||
'src/service/log.js',
|
'src/service/log.js',
|
||||||
|
|
|
||||||
377
src/apis.js
377
src/apis.js
|
|
@ -275,166 +275,6 @@ var angularArray = {
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc function
|
|
||||||
* @name angular.Array.filter
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Selects a subset of items from `array` and returns it as a new array.
|
|
||||||
*
|
|
||||||
* Note: This function is used to augment the `Array` type in Angular expressions. See
|
|
||||||
* {@link angular.Array} for more information about Angular arrays.
|
|
||||||
*
|
|
||||||
* @param {Array} array The source array.
|
|
||||||
* @param {string|Object|function()} expression The predicate to be used for selecting items from
|
|
||||||
* `array`.
|
|
||||||
*
|
|
||||||
* Can be one of:
|
|
||||||
*
|
|
||||||
* - `string`: Predicate that results in a substring match using the value of `expression`
|
|
||||||
* string. All strings or objects with string properties in `array` that contain this string
|
|
||||||
* will be returned. The predicate can be negated by prefixing the string with `!`.
|
|
||||||
*
|
|
||||||
* - `Object`: A pattern object can be used to filter specific properties on objects contained
|
|
||||||
* by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
|
|
||||||
* which have property `name` containing "M" and property `phone` containing "1". A special
|
|
||||||
* property name `$` can be used (as in `{$:"text"}`) to accept a match against any
|
|
||||||
* property of the object. That's equivalent to the simple substring match with a `string`
|
|
||||||
* as described above.
|
|
||||||
*
|
|
||||||
* - `function`: A predicate function can be used to write arbitrary filters. The function is
|
|
||||||
* called for each element of `array`. The final result is an array of those elements that
|
|
||||||
* the predicate returned true for.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
<doc:example>
|
|
||||||
<doc:source>
|
|
||||||
<div ng:init="friends = [{name:'John', phone:'555-1276'},
|
|
||||||
{name:'Mary', phone:'800-BIG-MARY'},
|
|
||||||
{name:'Mike', phone:'555-4321'},
|
|
||||||
{name:'Adam', phone:'555-5678'},
|
|
||||||
{name:'Julie', phone:'555-8765'}]"></div>
|
|
||||||
|
|
||||||
Search: <input ng:model="searchText"/>
|
|
||||||
<table id="searchTextResults">
|
|
||||||
<tr><th>Name</th><th>Phone</th><tr>
|
|
||||||
<tr ng:repeat="friend in friends.$filter(searchText)">
|
|
||||||
<td>{{friend.name}}</td>
|
|
||||||
<td>{{friend.phone}}</td>
|
|
||||||
<tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
Any: <input ng:model="search.$"/> <br>
|
|
||||||
Name only <input ng:model="search.name"/><br>
|
|
||||||
Phone only <input ng:model="search.phone"/><br>
|
|
||||||
<table id="searchObjResults">
|
|
||||||
<tr><th>Name</th><th>Phone</th><tr>
|
|
||||||
<tr ng:repeat="friend in friends.$filter(search)">
|
|
||||||
<td>{{friend.name}}</td>
|
|
||||||
<td>{{friend.phone}}</td>
|
|
||||||
<tr>
|
|
||||||
</table>
|
|
||||||
</doc:source>
|
|
||||||
<doc:scenario>
|
|
||||||
it('should search across all fields when filtering with a string', function() {
|
|
||||||
input('searchText').enter('m');
|
|
||||||
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
|
||||||
toEqual(['Mary', 'Mike', 'Adam']);
|
|
||||||
|
|
||||||
input('searchText').enter('76');
|
|
||||||
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
|
||||||
toEqual(['John', 'Julie']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search in specific fields when filtering with a predicate object', function() {
|
|
||||||
input('search.$').enter('i');
|
|
||||||
expect(repeater('#searchObjResults tr', 'friend in friends').column('name')).
|
|
||||||
toEqual(['Mary', 'Mike', 'Julie']);
|
|
||||||
});
|
|
||||||
</doc:scenario>
|
|
||||||
</doc:example>
|
|
||||||
*/
|
|
||||||
'filter':function(array, expression) {
|
|
||||||
var predicates = [];
|
|
||||||
predicates.check = function(value) {
|
|
||||||
for (var j = 0; j < predicates.length; j++) {
|
|
||||||
if(!predicates[j](value)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
var search = function(obj, text){
|
|
||||||
if (text.charAt(0) === '!') {
|
|
||||||
return !search(obj, text.substr(1));
|
|
||||||
}
|
|
||||||
switch (typeof obj) {
|
|
||||||
case "boolean":
|
|
||||||
case "number":
|
|
||||||
case "string":
|
|
||||||
return ('' + obj).toLowerCase().indexOf(text) > -1;
|
|
||||||
case "object":
|
|
||||||
for ( var objKey in obj) {
|
|
||||||
if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case "array":
|
|
||||||
for ( var i = 0; i < obj.length; i++) {
|
|
||||||
if (search(obj[i], text)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
switch (typeof expression) {
|
|
||||||
case "boolean":
|
|
||||||
case "number":
|
|
||||||
case "string":
|
|
||||||
expression = {$:expression};
|
|
||||||
case "object":
|
|
||||||
for (var key in expression) {
|
|
||||||
if (key == '$') {
|
|
||||||
(function() {
|
|
||||||
var text = (''+expression[key]).toLowerCase();
|
|
||||||
if (!text) return;
|
|
||||||
predicates.push(function(value) {
|
|
||||||
return search(value, text);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
} else {
|
|
||||||
(function() {
|
|
||||||
var path = key;
|
|
||||||
var text = (''+expression[key]).toLowerCase();
|
|
||||||
if (!text) return;
|
|
||||||
predicates.push(function(value) {
|
|
||||||
return search(getter(value, path), text);
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'function':
|
|
||||||
predicates.push(expression);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
var filtered = [];
|
|
||||||
for ( var j = 0; j < array.length; j++) {
|
|
||||||
var value = array[j];
|
|
||||||
if (predicates.check(value)) {
|
|
||||||
filtered.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filtered;
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
|
|
@ -577,223 +417,6 @@ var angularArray = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return count;
|
return count;
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc function
|
|
||||||
* @name angular.Array.orderBy
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Orders a specified `array` by the `expression` predicate.
|
|
||||||
*
|
|
||||||
* Note: this function is used to augment the `Array` type in Angular expressions. See
|
|
||||||
* {@link angular.Array} for more informaton about Angular arrays.
|
|
||||||
*
|
|
||||||
* @param {Array} array The array to sort.
|
|
||||||
* @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
|
|
||||||
* used by the comparator to determine the order of elements.
|
|
||||||
*
|
|
||||||
* Can be one of:
|
|
||||||
*
|
|
||||||
* - `function`: Getter function. The result of this function will be sorted using the
|
|
||||||
* `<`, `=`, `>` operator.
|
|
||||||
* - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
|
|
||||||
* to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
|
|
||||||
* ascending or descending sort order (for example, +name or -name).
|
|
||||||
* - `Array`: An array of function or string predicates. The first predicate in the array
|
|
||||||
* is used for sorting, but when two items are equivalent, the next predicate is used.
|
|
||||||
*
|
|
||||||
* @param {boolean=} reverse Reverse the order the array.
|
|
||||||
* @returns {Array} Sorted copy of the source array.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
<doc:example>
|
|
||||||
<doc:source>
|
|
||||||
<script>
|
|
||||||
function Ctrl() {
|
|
||||||
this.friends =
|
|
||||||
[{name:'John', phone:'555-1212', age:10},
|
|
||||||
{name:'Mary', phone:'555-9876', age:19},
|
|
||||||
{name:'Mike', phone:'555-4321', age:21},
|
|
||||||
{name:'Adam', phone:'555-5678', age:35},
|
|
||||||
{name:'Julie', phone:'555-8765', age:29}]
|
|
||||||
this.predicate = '-age';
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<div ng:controller="Ctrl">
|
|
||||||
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
|
||||||
<hr/>
|
|
||||||
[ <a href="" ng:click="predicate=''">unsorted</a> ]
|
|
||||||
<table class="friend">
|
|
||||||
<tr>
|
|
||||||
<th><a href="" ng:click="predicate = 'name'; reverse=false">Name</a>
|
|
||||||
(<a href ng:click="predicate = '-name'; reverse=false">^</a>)</th>
|
|
||||||
<th><a href="" ng:click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
|
|
||||||
<th><a href="" ng:click="predicate = 'age'; reverse=!reverse">Age</a></th>
|
|
||||||
<tr>
|
|
||||||
<tr ng:repeat="friend in friends.$orderBy(predicate, reverse)">
|
|
||||||
<td>{{friend.name}}</td>
|
|
||||||
<td>{{friend.phone}}</td>
|
|
||||||
<td>{{friend.age}}</td>
|
|
||||||
<tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</doc:source>
|
|
||||||
<doc:scenario>
|
|
||||||
it('should be reverse ordered by aged', function() {
|
|
||||||
expect(binding('predicate')).toBe('Sorting predicate = -age; reverse = ');
|
|
||||||
expect(repeater('table.friend', 'friend in friends').column('friend.age')).
|
|
||||||
toEqual(['35', '29', '21', '19', '10']);
|
|
||||||
expect(repeater('table.friend', 'friend in friends').column('friend.name')).
|
|
||||||
toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reorder the table when user selects different predicate', function() {
|
|
||||||
element('.doc-example-live a:contains("Name")').click();
|
|
||||||
expect(repeater('table.friend', 'friend in friends').column('friend.name')).
|
|
||||||
toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);
|
|
||||||
expect(repeater('table.friend', 'friend in friends').column('friend.age')).
|
|
||||||
toEqual(['35', '10', '29', '19', '21']);
|
|
||||||
|
|
||||||
element('.doc-example-live a:contains("Phone")').click();
|
|
||||||
expect(repeater('table.friend', 'friend in friends').column('friend.phone')).
|
|
||||||
toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);
|
|
||||||
expect(repeater('table.friend', 'friend in friends').column('friend.name')).
|
|
||||||
toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);
|
|
||||||
});
|
|
||||||
</doc:scenario>
|
|
||||||
</doc:example>
|
|
||||||
*/
|
|
||||||
'orderBy':function(array, sortPredicate, reverseOrder) {
|
|
||||||
if (!sortPredicate) return array;
|
|
||||||
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
|
|
||||||
sortPredicate = map(sortPredicate, function(predicate){
|
|
||||||
var descending = false, get = predicate || identity;
|
|
||||||
if (isString(predicate)) {
|
|
||||||
if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
|
|
||||||
descending = predicate.charAt(0) == '-';
|
|
||||||
predicate = predicate.substring(1);
|
|
||||||
}
|
|
||||||
get = expressionCompile(predicate);
|
|
||||||
}
|
|
||||||
return reverseComparator(function(a,b){
|
|
||||||
return compare(get(a),get(b));
|
|
||||||
}, descending);
|
|
||||||
});
|
|
||||||
var arrayCopy = [];
|
|
||||||
for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
|
|
||||||
return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
|
|
||||||
|
|
||||||
function comparator(o1, o2){
|
|
||||||
for ( var i = 0; i < sortPredicate.length; i++) {
|
|
||||||
var comp = sortPredicate[i](o1, o2);
|
|
||||||
if (comp !== 0) return comp;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
function reverseComparator(comp, descending) {
|
|
||||||
return toBoolean(descending)
|
|
||||||
? function(a,b){return comp(b,a);}
|
|
||||||
: comp;
|
|
||||||
}
|
|
||||||
function compare(v1, v2){
|
|
||||||
var t1 = typeof v1;
|
|
||||||
var t2 = typeof v2;
|
|
||||||
if (t1 == t2) {
|
|
||||||
if (t1 == "string") v1 = v1.toLowerCase();
|
|
||||||
if (t1 == "string") v2 = v2.toLowerCase();
|
|
||||||
if (v1 === v2) return 0;
|
|
||||||
return v1 < v2 ? -1 : 1;
|
|
||||||
} else {
|
|
||||||
return t1 < t2 ? -1 : 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc function
|
|
||||||
* @name angular.Array.limitTo
|
|
||||||
* @function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Creates a new array containing only a specified number of elements in an array. The elements
|
|
||||||
* are taken from either the beginning or the end of the source array, as specified by the
|
|
||||||
* value and sign (positive or negative) of `limit`.
|
|
||||||
*
|
|
||||||
* Note: This function is used to augment the `Array` type in Angular expressions. See
|
|
||||||
* {@link angular.Array} for more information about Angular arrays.
|
|
||||||
*
|
|
||||||
* @param {Array} array Source array to be limited.
|
|
||||||
* @param {string|Number} limit The length of the returned array. If the `limit` number is
|
|
||||||
* positive, `limit` number of items from the beginning of the source array are copied.
|
|
||||||
* If the number is negative, `limit` number of items from the end of the source array are
|
|
||||||
* copied. The `limit` will be trimmed if it exceeds `array.length`
|
|
||||||
* @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`
|
|
||||||
* elements.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
<doc:example>
|
|
||||||
<doc:source>
|
|
||||||
<script>
|
|
||||||
function Ctrl() {
|
|
||||||
this.numbers = [1,2,3,4,5,6,7,8,9];
|
|
||||||
this.limit = 3;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<div ng:controller="Ctrl">
|
|
||||||
Limit {{numbers}} to: <input type="integer" ng:model="limit"/>
|
|
||||||
<p>Output: {{ numbers.$limitTo(limit) | json }}</p>
|
|
||||||
</div>
|
|
||||||
</doc:source>
|
|
||||||
<doc:scenario>
|
|
||||||
it('should limit the numer array to first three items', function() {
|
|
||||||
expect(element('.doc-example-live input[ng\\:model=limit]').val()).toBe('3');
|
|
||||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update the output when -3 is entered', function() {
|
|
||||||
input('limit').enter(-3);
|
|
||||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not exceed the maximum size of input array', function() {
|
|
||||||
input('limit').enter(100);
|
|
||||||
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3,4,5,6,7,8,9]');
|
|
||||||
});
|
|
||||||
</doc:scenario>
|
|
||||||
</doc:example>
|
|
||||||
*/
|
|
||||||
limitTo: function(array, limit) {
|
|
||||||
limit = parseInt(limit, 10);
|
|
||||||
var out = [],
|
|
||||||
i, n;
|
|
||||||
|
|
||||||
// check that array is iterable
|
|
||||||
if (!array || !(array instanceof Array))
|
|
||||||
return out;
|
|
||||||
|
|
||||||
// if abs(limit) exceeds maximum length, trim it
|
|
||||||
if (limit > array.length)
|
|
||||||
limit = array.length;
|
|
||||||
else if (limit < -array.length)
|
|
||||||
limit = -array.length;
|
|
||||||
|
|
||||||
if (limit > 0) {
|
|
||||||
i = 0;
|
|
||||||
n = limit;
|
|
||||||
} else {
|
|
||||||
i = array.length + limit;
|
|
||||||
n = array.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; i<n; i++) {
|
|
||||||
out.push(array[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,14 @@ function $FilterProvider($provide) {
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
$provide.filter('currency', currencyFilter);
|
$provide.filter('currency', currencyFilter);
|
||||||
$provide.filter('number', numberFilter);
|
|
||||||
$provide.filter('date', dateFilter);
|
$provide.filter('date', dateFilter);
|
||||||
$provide.filter('json', jsonFilter);
|
$provide.filter('filter', filterFilter);
|
||||||
$provide.filter('lowercase', lowercaseFilter);
|
|
||||||
$provide.filter('uppercase', uppercaseFilter);
|
|
||||||
$provide.filter('html', htmlFilter);
|
$provide.filter('html', htmlFilter);
|
||||||
|
$provide.filter('json', jsonFilter);
|
||||||
|
$provide.filter('limitTo', limitToFilter);
|
||||||
$provide.filter('linky', linkyFilter);
|
$provide.filter('linky', linkyFilter);
|
||||||
|
$provide.filter('lowercase', lowercaseFilter);
|
||||||
|
$provide.filter('number', numberFilter);
|
||||||
|
$provide.filter('orderBy', orderByFilter);
|
||||||
|
$provide.filter('uppercase', uppercaseFilter);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
164
src/service/filter/filter.js
Normal file
164
src/service/filter/filter.js
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name angular.Array.filter
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Selects a subset of items from `array` and returns it as a new array.
|
||||||
|
*
|
||||||
|
* Note: This function is used to augment the `Array` type in Angular expressions. See
|
||||||
|
* {@link angular.Array} for more information about Angular arrays.
|
||||||
|
*
|
||||||
|
* @param {Array} array The source array.
|
||||||
|
* @param {string|Object|function()} expression The predicate to be used for selecting items from
|
||||||
|
* `array`.
|
||||||
|
*
|
||||||
|
* Can be one of:
|
||||||
|
*
|
||||||
|
* - `string`: Predicate that results in a substring match using the value of `expression`
|
||||||
|
* string. All strings or objects with string properties in `array` that contain this string
|
||||||
|
* will be returned. The predicate can be negated by prefixing the string with `!`.
|
||||||
|
*
|
||||||
|
* - `Object`: A pattern object can be used to filter specific properties on objects contained
|
||||||
|
* by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
|
||||||
|
* which have property `name` containing "M" and property `phone` containing "1". A special
|
||||||
|
* property name `$` can be used (as in `{$:"text"}`) to accept a match against any
|
||||||
|
* property of the object. That's equivalent to the simple substring match with a `string`
|
||||||
|
* as described above.
|
||||||
|
*
|
||||||
|
* - `function`: A predicate function can be used to write arbitrary filters. The function is
|
||||||
|
* called for each element of `array`. The final result is an array of those elements that
|
||||||
|
* the predicate returned true for.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
<doc:example>
|
||||||
|
<doc:source>
|
||||||
|
<div ng:init="friends = [{name:'John', phone:'555-1276'},
|
||||||
|
{name:'Mary', phone:'800-BIG-MARY'},
|
||||||
|
{name:'Mike', phone:'555-4321'},
|
||||||
|
{name:'Adam', phone:'555-5678'},
|
||||||
|
{name:'Julie', phone:'555-8765'}]"></div>
|
||||||
|
|
||||||
|
Search: <input ng:model="searchText"/>
|
||||||
|
<table id="searchTextResults">
|
||||||
|
<tr><th>Name</th><th>Phone</th><tr>
|
||||||
|
<tr ng:repeat="friend in friends.$filter(searchText)">
|
||||||
|
<td>{{friend.name}}</td>
|
||||||
|
<td>{{friend.phone}}</td>
|
||||||
|
<tr>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
Any: <input ng:model="search.$"/> <br>
|
||||||
|
Name only <input ng:model="search.name"/><br>
|
||||||
|
Phone only <input ng:model="search.phone"/><br>
|
||||||
|
<table id="searchObjResults">
|
||||||
|
<tr><th>Name</th><th>Phone</th><tr>
|
||||||
|
<tr ng:repeat="friend in friends.$filter(search)">
|
||||||
|
<td>{{friend.name}}</td>
|
||||||
|
<td>{{friend.phone}}</td>
|
||||||
|
<tr>
|
||||||
|
</table>
|
||||||
|
</doc:source>
|
||||||
|
<doc:scenario>
|
||||||
|
it('should search across all fields when filtering with a string', function() {
|
||||||
|
input('searchText').enter('m');
|
||||||
|
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
||||||
|
toEqual(['Mary', 'Mike', 'Adam']);
|
||||||
|
|
||||||
|
input('searchText').enter('76');
|
||||||
|
expect(repeater('#searchTextResults tr', 'friend in friends').column('name')).
|
||||||
|
toEqual(['John', 'Julie']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should search in specific fields when filtering with a predicate object', function() {
|
||||||
|
input('search.$').enter('i');
|
||||||
|
expect(repeater('#searchObjResults tr', 'friend in friends').column('name')).
|
||||||
|
toEqual(['Mary', 'Mike', 'Julie']);
|
||||||
|
});
|
||||||
|
</doc:scenario>
|
||||||
|
</doc:example>
|
||||||
|
*/
|
||||||
|
function filterFilter() {
|
||||||
|
return function(array, expression) {
|
||||||
|
if (!(array instanceof Array)) return array;
|
||||||
|
var predicates = [];
|
||||||
|
predicates.check = function(value) {
|
||||||
|
for (var j = 0; j < predicates.length; j++) {
|
||||||
|
if(!predicates[j](value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
var search = function(obj, text){
|
||||||
|
if (text.charAt(0) === '!') {
|
||||||
|
return !search(obj, text.substr(1));
|
||||||
|
}
|
||||||
|
switch (typeof obj) {
|
||||||
|
case "boolean":
|
||||||
|
case "number":
|
||||||
|
case "string":
|
||||||
|
return ('' + obj).toLowerCase().indexOf(text) > -1;
|
||||||
|
case "object":
|
||||||
|
for ( var objKey in obj) {
|
||||||
|
if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case "array":
|
||||||
|
for ( var i = 0; i < obj.length; i++) {
|
||||||
|
if (search(obj[i], text)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
switch (typeof expression) {
|
||||||
|
case "boolean":
|
||||||
|
case "number":
|
||||||
|
case "string":
|
||||||
|
expression = {$:expression};
|
||||||
|
case "object":
|
||||||
|
for (var key in expression) {
|
||||||
|
if (key == '$') {
|
||||||
|
(function() {
|
||||||
|
var text = (''+expression[key]).toLowerCase();
|
||||||
|
if (!text) return;
|
||||||
|
predicates.push(function(value) {
|
||||||
|
return search(value, text);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
} else {
|
||||||
|
(function() {
|
||||||
|
var path = key;
|
||||||
|
var text = (''+expression[key]).toLowerCase();
|
||||||
|
if (!text) return;
|
||||||
|
predicates.push(function(value) {
|
||||||
|
return search(getter(value, path), text);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'function':
|
||||||
|
predicates.push(expression);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
var filtered = [];
|
||||||
|
for ( var j = 0; j < array.length; j++) {
|
||||||
|
var value = array[j];
|
||||||
|
if (predicates.check(value)) {
|
||||||
|
filtered.push(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/service/filter/limitTo.js
Normal file
87
src/service/filter/limitTo.js
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name angular.Array.limitTo
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Creates a new array containing only a specified number of elements in an array. The elements
|
||||||
|
* are taken from either the beginning or the end of the source array, as specified by the
|
||||||
|
* value and sign (positive or negative) of `limit`.
|
||||||
|
*
|
||||||
|
* Note: This function is used to augment the `Array` type in Angular expressions. See
|
||||||
|
* {@link angular.Array} for more information about Angular arrays.
|
||||||
|
*
|
||||||
|
* @param {Array} array Source array to be limited.
|
||||||
|
* @param {string|Number} limit The length of the returned array. If the `limit` number is
|
||||||
|
* positive, `limit` number of items from the beginning of the source array are copied.
|
||||||
|
* If the number is negative, `limit` number of items from the end of the source array are
|
||||||
|
* copied. The `limit` will be trimmed if it exceeds `array.length`
|
||||||
|
* @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`
|
||||||
|
* elements.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
<doc:example>
|
||||||
|
<doc:source>
|
||||||
|
<script>
|
||||||
|
function Ctrl() {
|
||||||
|
this.numbers = [1,2,3,4,5,6,7,8,9];
|
||||||
|
this.limit = 3;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<div ng:controller="Ctrl">
|
||||||
|
Limit {{numbers}} to: <input type="integer" ng:model="limit"/>
|
||||||
|
<p>Output: {{ numbers.$limitTo(limit) | json }}</p>
|
||||||
|
</div>
|
||||||
|
</doc:source>
|
||||||
|
<doc:scenario>
|
||||||
|
it('should limit the numer array to first three items', function() {
|
||||||
|
expect(element('.doc-example-live input[ng\\:model=limit]').val()).toBe('3');
|
||||||
|
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the output when -3 is entered', function() {
|
||||||
|
input('limit').enter(-3);
|
||||||
|
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not exceed the maximum size of input array', function() {
|
||||||
|
input('limit').enter(100);
|
||||||
|
expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3,4,5,6,7,8,9]');
|
||||||
|
});
|
||||||
|
</doc:scenario>
|
||||||
|
</doc:example>
|
||||||
|
*/
|
||||||
|
function limitToFilter(){
|
||||||
|
return function(array, limit) {
|
||||||
|
if (!(array instanceof Array)) return array;
|
||||||
|
limit = parseInt(limit, 10);
|
||||||
|
var out = [],
|
||||||
|
i, n;
|
||||||
|
|
||||||
|
// check that array is iterable
|
||||||
|
if (!array || !(array instanceof Array))
|
||||||
|
return out;
|
||||||
|
|
||||||
|
// if abs(limit) exceeds maximum length, trim it
|
||||||
|
if (limit > array.length)
|
||||||
|
limit = array.length;
|
||||||
|
else if (limit < -array.length)
|
||||||
|
limit = -array.length;
|
||||||
|
|
||||||
|
if (limit > 0) {
|
||||||
|
i = 0;
|
||||||
|
n = limit;
|
||||||
|
} else {
|
||||||
|
i = array.length + limit;
|
||||||
|
n = array.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i<n; i++) {
|
||||||
|
out.push(array[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
137
src/service/filter/orderBy.js
Normal file
137
src/service/filter/orderBy.js
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name angular.Array.orderBy
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Orders a specified `array` by the `expression` predicate.
|
||||||
|
*
|
||||||
|
* Note: this function is used to augment the `Array` type in Angular expressions. See
|
||||||
|
* {@link angular.Array} for more informaton about Angular arrays.
|
||||||
|
*
|
||||||
|
* @param {Array} array The array to sort.
|
||||||
|
* @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
|
||||||
|
* used by the comparator to determine the order of elements.
|
||||||
|
*
|
||||||
|
* Can be one of:
|
||||||
|
*
|
||||||
|
* - `function`: Getter function. The result of this function will be sorted using the
|
||||||
|
* `<`, `=`, `>` operator.
|
||||||
|
* - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
|
||||||
|
* to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
|
||||||
|
* ascending or descending sort order (for example, +name or -name).
|
||||||
|
* - `Array`: An array of function or string predicates. The first predicate in the array
|
||||||
|
* is used for sorting, but when two items are equivalent, the next predicate is used.
|
||||||
|
*
|
||||||
|
* @param {boolean=} reverse Reverse the order the array.
|
||||||
|
* @returns {Array} Sorted copy of the source array.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
<doc:example>
|
||||||
|
<doc:source>
|
||||||
|
<script>
|
||||||
|
function Ctrl() {
|
||||||
|
this.friends =
|
||||||
|
[{name:'John', phone:'555-1212', age:10},
|
||||||
|
{name:'Mary', phone:'555-9876', age:19},
|
||||||
|
{name:'Mike', phone:'555-4321', age:21},
|
||||||
|
{name:'Adam', phone:'555-5678', age:35},
|
||||||
|
{name:'Julie', phone:'555-8765', age:29}]
|
||||||
|
this.predicate = '-age';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<div ng:controller="Ctrl">
|
||||||
|
<pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
|
||||||
|
<hr/>
|
||||||
|
[ <a href="" ng:click="predicate=''">unsorted</a> ]
|
||||||
|
<table class="friend">
|
||||||
|
<tr>
|
||||||
|
<th><a href="" ng:click="predicate = 'name'; reverse=false">Name</a>
|
||||||
|
(<a href ng:click="predicate = '-name'; reverse=false">^</a>)</th>
|
||||||
|
<th><a href="" ng:click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
|
||||||
|
<th><a href="" ng:click="predicate = 'age'; reverse=!reverse">Age</a></th>
|
||||||
|
<tr>
|
||||||
|
<tr ng:repeat="friend in friends.$orderBy(predicate, reverse)">
|
||||||
|
<td>{{friend.name}}</td>
|
||||||
|
<td>{{friend.phone}}</td>
|
||||||
|
<td>{{friend.age}}</td>
|
||||||
|
<tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</doc:source>
|
||||||
|
<doc:scenario>
|
||||||
|
it('should be reverse ordered by aged', function() {
|
||||||
|
expect(binding('predicate')).toBe('Sorting predicate = -age; reverse = ');
|
||||||
|
expect(repeater('table.friend', 'friend in friends').column('friend.age')).
|
||||||
|
toEqual(['35', '29', '21', '19', '10']);
|
||||||
|
expect(repeater('table.friend', 'friend in friends').column('friend.name')).
|
||||||
|
toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reorder the table when user selects different predicate', function() {
|
||||||
|
element('.doc-example-live a:contains("Name")').click();
|
||||||
|
expect(repeater('table.friend', 'friend in friends').column('friend.name')).
|
||||||
|
toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);
|
||||||
|
expect(repeater('table.friend', 'friend in friends').column('friend.age')).
|
||||||
|
toEqual(['35', '10', '29', '19', '21']);
|
||||||
|
|
||||||
|
element('.doc-example-live a:contains("Phone")').click();
|
||||||
|
expect(repeater('table.friend', 'friend in friends').column('friend.phone')).
|
||||||
|
toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);
|
||||||
|
expect(repeater('table.friend', 'friend in friends').column('friend.name')).
|
||||||
|
toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);
|
||||||
|
});
|
||||||
|
</doc:scenario>
|
||||||
|
</doc:example>
|
||||||
|
*/
|
||||||
|
orderByFilter.$inject = ['$parse'];
|
||||||
|
function orderByFilter($parse){
|
||||||
|
return function(array, sortPredicate, reverseOrder) {
|
||||||
|
if (!(array instanceof Array)) return array;
|
||||||
|
if (!sortPredicate) return array;
|
||||||
|
sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
|
||||||
|
sortPredicate = map(sortPredicate, function(predicate){
|
||||||
|
var descending = false, get = predicate || identity;
|
||||||
|
if (isString(predicate)) {
|
||||||
|
if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
|
||||||
|
descending = predicate.charAt(0) == '-';
|
||||||
|
predicate = predicate.substring(1);
|
||||||
|
}
|
||||||
|
get = $parse(predicate);
|
||||||
|
}
|
||||||
|
return reverseComparator(function(a,b){
|
||||||
|
return compare(get(a),get(b));
|
||||||
|
}, descending);
|
||||||
|
});
|
||||||
|
var arrayCopy = [];
|
||||||
|
for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
|
||||||
|
return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
|
||||||
|
|
||||||
|
function comparator(o1, o2){
|
||||||
|
for ( var i = 0; i < sortPredicate.length; i++) {
|
||||||
|
var comp = sortPredicate[i](o1, o2);
|
||||||
|
if (comp !== 0) return comp;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
function reverseComparator(comp, descending) {
|
||||||
|
return toBoolean(descending)
|
||||||
|
? function(a,b){return comp(b,a);}
|
||||||
|
: comp;
|
||||||
|
}
|
||||||
|
function compare(v1, v2){
|
||||||
|
var t1 = typeof v1;
|
||||||
|
var t2 = typeof v2;
|
||||||
|
if (t1 == t2) {
|
||||||
|
if (t1 == "string") v1 = v1.toLowerCase();
|
||||||
|
if (t1 == "string") v2 = v2.toLowerCase();
|
||||||
|
if (v1 === v2) return 0;
|
||||||
|
return v1 < v2 ? -1 : 1;
|
||||||
|
} else {
|
||||||
|
return t1 < t2 ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
146
test/ApiSpecs.js
146
test/ApiSpecs.js
|
|
@ -105,117 +105,6 @@ describe('api', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('filter', function() {
|
|
||||||
it('should filter by string', function() {
|
|
||||||
var items = ["MIsKO", {name:"shyam"}, ["adam"], 1234];
|
|
||||||
assertEquals(4, angular.Array.filter(items, "").length);
|
|
||||||
assertEquals(4, angular.Array.filter(items, undefined).length);
|
|
||||||
|
|
||||||
assertEquals(1, angular.Array.filter(items, 'iSk').length);
|
|
||||||
assertEquals("MIsKO", angular.Array.filter(items, 'isk')[0]);
|
|
||||||
|
|
||||||
assertEquals(1, angular.Array.filter(items, 'yam').length);
|
|
||||||
assertEquals(items[1], angular.Array.filter(items, 'yam')[0]);
|
|
||||||
|
|
||||||
assertEquals(1, angular.Array.filter(items, 'da').length);
|
|
||||||
assertEquals(items[2], angular.Array.filter(items, 'da')[0]);
|
|
||||||
|
|
||||||
assertEquals(1, angular.Array.filter(items, '34').length);
|
|
||||||
assertEquals(1234, angular.Array.filter(items, '34')[0]);
|
|
||||||
|
|
||||||
assertEquals(0, angular.Array.filter(items, "I don't exist").length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not read $ properties', function() {
|
|
||||||
assertEquals("", "".charAt(0)); // assumption
|
|
||||||
var items = [{$name:"misko"}];
|
|
||||||
assertEquals(0, angular.Array.filter(items, "misko").length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter on specific property', function() {
|
|
||||||
var items = [{ignore:"a", name:"a"}, {ignore:"a", name:"abc"}];
|
|
||||||
assertEquals(2, angular.Array.filter(items, {}).length);
|
|
||||||
|
|
||||||
assertEquals(2, angular.Array.filter(items, {name:'a'}).length);
|
|
||||||
|
|
||||||
assertEquals(1, angular.Array.filter(items, {name:'b'}).length);
|
|
||||||
assertEquals("abc", angular.Array.filter(items, {name:'b'})[0].name);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should take function as predicate', function() {
|
|
||||||
var items = [{name:"a"}, {name:"abc", done:true}];
|
|
||||||
assertEquals(1, angular.Array.filter(items, function(i) {return i.done;}).length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should take object as perdicate', function() {
|
|
||||||
var items = [{first:"misko", last:"hevery"},
|
|
||||||
{first:"adam", last:"abrons"}];
|
|
||||||
|
|
||||||
assertEquals(2, angular.Array.filter(items, {first:'', last:''}).length);
|
|
||||||
assertEquals(1, angular.Array.filter(items, {first:'', last:'hevery'}).length);
|
|
||||||
assertEquals(0, angular.Array.filter(items, {first:'adam', last:'hevery'}).length);
|
|
||||||
assertEquals(1, angular.Array.filter(items, {first:'misko', last:'hevery'}).length);
|
|
||||||
assertEquals(items[0], angular.Array.filter(items, {first:'misko', last:'hevery'})[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support negation operator', function() {
|
|
||||||
var items = ["misko", "adam"];
|
|
||||||
|
|
||||||
assertEquals(1, angular.Array.filter(items, '!isk').length);
|
|
||||||
assertEquals(items[1], angular.Array.filter(items, '!isk')[0]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('limit', function() {
|
|
||||||
var items;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should return the first X items when X is positive', function() {
|
|
||||||
expect(angular.Array.limitTo(items, 3)).toEqual(['a', 'b', 'c']);
|
|
||||||
expect(angular.Array.limitTo(items, '3')).toEqual(['a', 'b', 'c']);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should return the last X items when X is negative', function() {
|
|
||||||
expect(angular.Array.limitTo(items, -3)).toEqual(['f', 'g', 'h']);
|
|
||||||
expect(angular.Array.limitTo(items, '-3')).toEqual(['f', 'g', 'h']);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should return an empty array when X cannot be parsed', function() {
|
|
||||||
expect(angular.Array.limitTo(items, 'bogus')).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(items, 'null')).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(items, 'undefined')).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(items, null)).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(items, undefined)).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should return an empty array when input is not Array type', function() {
|
|
||||||
expect(angular.Array.limitTo('bogus', 1)).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(null, 1)).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(undefined, 1)).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(null, 1)).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo(undefined, 1)).toEqual([]);
|
|
||||||
expect(angular.Array.limitTo({}, 1)).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should return a copy of input array if X is exceeds array length', function () {
|
|
||||||
expect(angular.Array.limitTo(items, 19)).toEqual(items);
|
|
||||||
expect(angular.Array.limitTo(items, '9')).toEqual(items);
|
|
||||||
expect(angular.Array.limitTo(items, -9)).toEqual(items);
|
|
||||||
expect(angular.Array.limitTo(items, '-9')).toEqual(items);
|
|
||||||
|
|
||||||
expect(angular.Array.limitTo(items, 9)).not.toBe(items);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('add', function() {
|
it('add', function() {
|
||||||
var add = angular.Array.add;
|
var add = angular.Array.add;
|
||||||
|
|
@ -232,41 +121,6 @@ describe('api', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('orderBy', function() {
|
|
||||||
var orderBy;
|
|
||||||
beforeEach(function() {
|
|
||||||
orderBy = angular.Array.orderBy;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return same array if predicate is falsy', function() {
|
|
||||||
var array = [1, 2, 3];
|
|
||||||
expect(orderBy(array)).toBe(array);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shouldSortArrayInReverse', function() {
|
|
||||||
assertJsonEquals([{a:15},{a:2}], angular.Array.orderBy([{a:15},{a:2}], 'a', true));
|
|
||||||
assertJsonEquals([{a:15},{a:2}], angular.Array.orderBy([{a:15},{a:2}], 'a', "T"));
|
|
||||||
assertJsonEquals([{a:15},{a:2}], angular.Array.orderBy([{a:15},{a:2}], 'a', "reverse"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should sort array by predicate', function() {
|
|
||||||
assertJsonEquals([{a:2, b:1},{a:15, b:1}],
|
|
||||||
angular.Array.orderBy([{a:15, b:1},{a:2, b:1}], ['a', 'b']));
|
|
||||||
assertJsonEquals([{a:2, b:1},{a:15, b:1}],
|
|
||||||
angular.Array.orderBy([{a:15, b:1},{a:2, b:1}], ['b', 'a']));
|
|
||||||
assertJsonEquals([{a:15, b:1},{a:2, b:1}],
|
|
||||||
angular.Array.orderBy([{a:15, b:1},{a:2, b:1}], ['+b', '-a']));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use function', function() {
|
|
||||||
expect(
|
|
||||||
orderBy(
|
|
||||||
[{a:15, b:1},{a:2, b:1}],
|
|
||||||
function(value) { return value.a; })).
|
|
||||||
toEqual([{a:2, b:1},{a:15, b:1}]);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
68
test/service/filter/filterSpec.js
Normal file
68
test/service/filter/filterSpec.js
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('Filter: filter', function() {
|
||||||
|
var filter;
|
||||||
|
|
||||||
|
beforeEach(inject(function($filter){
|
||||||
|
filter = $filter('filter');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should filter by string', function() {
|
||||||
|
var items = ["MIsKO", {name:"shyam"}, ["adam"], 1234];
|
||||||
|
assertEquals(4, filter(items, "").length);
|
||||||
|
assertEquals(4, filter(items, undefined).length);
|
||||||
|
|
||||||
|
assertEquals(1, filter(items, 'iSk').length);
|
||||||
|
assertEquals("MIsKO", filter(items, 'isk')[0]);
|
||||||
|
|
||||||
|
assertEquals(1, filter(items, 'yam').length);
|
||||||
|
assertEquals(items[1], filter(items, 'yam')[0]);
|
||||||
|
|
||||||
|
assertEquals(1, filter(items, 'da').length);
|
||||||
|
assertEquals(items[2], filter(items, 'da')[0]);
|
||||||
|
|
||||||
|
assertEquals(1, filter(items, '34').length);
|
||||||
|
assertEquals(1234, filter(items, '34')[0]);
|
||||||
|
|
||||||
|
assertEquals(0, filter(items, "I don't exist").length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not read $ properties', function() {
|
||||||
|
assertEquals("", "".charAt(0)); // assumption
|
||||||
|
var items = [{$name:"misko"}];
|
||||||
|
assertEquals(0, filter(items, "misko").length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter on specific property', function() {
|
||||||
|
var items = [{ignore:"a", name:"a"}, {ignore:"a", name:"abc"}];
|
||||||
|
assertEquals(2, filter(items, {}).length);
|
||||||
|
|
||||||
|
assertEquals(2, filter(items, {name:'a'}).length);
|
||||||
|
|
||||||
|
assertEquals(1, filter(items, {name:'b'}).length);
|
||||||
|
assertEquals("abc", filter(items, {name:'b'})[0].name);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should take function as predicate', function() {
|
||||||
|
var items = [{name:"a"}, {name:"abc", done:true}];
|
||||||
|
assertEquals(1, filter(items, function(i) {return i.done;}).length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should take object as perdicate', function() {
|
||||||
|
var items = [{first:"misko", last:"hevery"},
|
||||||
|
{first:"adam", last:"abrons"}];
|
||||||
|
|
||||||
|
assertEquals(2, filter(items, {first:'', last:''}).length);
|
||||||
|
assertEquals(1, filter(items, {first:'', last:'hevery'}).length);
|
||||||
|
assertEquals(0, filter(items, {first:'adam', last:'hevery'}).length);
|
||||||
|
assertEquals(1, filter(items, {first:'misko', last:'hevery'}).length);
|
||||||
|
assertEquals(items[0], filter(items, {first:'misko', last:'hevery'})[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support negation operator', function() {
|
||||||
|
var items = ["misko", "adam"];
|
||||||
|
|
||||||
|
assertEquals(1, filter(items, '!isk').length);
|
||||||
|
assertEquals(items[1], filter(items, '!isk')[0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('filter', function() {
|
describe('filters', function() {
|
||||||
|
|
||||||
var filter;
|
var filter;
|
||||||
|
|
||||||
|
|
|
||||||
52
test/service/filter/limitToSpec.js
Normal file
52
test/service/filter/limitToSpec.js
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('Filter: limitTo', function() {
|
||||||
|
var items;
|
||||||
|
var limitTo;
|
||||||
|
|
||||||
|
beforeEach(inject(function($filter) {
|
||||||
|
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
|
||||||
|
limitTo = $filter('limitTo');
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should return the first X items when X is positive', function() {
|
||||||
|
expect(limitTo(items, 3)).toEqual(['a', 'b', 'c']);
|
||||||
|
expect(limitTo(items, '3')).toEqual(['a', 'b', 'c']);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return the last X items when X is negative', function() {
|
||||||
|
expect(limitTo(items, -3)).toEqual(['f', 'g', 'h']);
|
||||||
|
expect(limitTo(items, '-3')).toEqual(['f', 'g', 'h']);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return an empty array when X cannot be parsed', function() {
|
||||||
|
expect(limitTo(items, 'bogus')).toEqual([]);
|
||||||
|
expect(limitTo(items, 'null')).toEqual([]);
|
||||||
|
expect(limitTo(items, 'undefined')).toEqual([]);
|
||||||
|
expect(limitTo(items, null)).toEqual([]);
|
||||||
|
expect(limitTo(items, undefined)).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return an empty array when input is not Array type', function() {
|
||||||
|
expect(limitTo('bogus', 1)).toEqual('bogus');
|
||||||
|
expect(limitTo(null, 1)).toEqual(null);
|
||||||
|
expect(limitTo(undefined, 1)).toEqual(undefined);
|
||||||
|
expect(limitTo(null, 1)).toEqual(null);
|
||||||
|
expect(limitTo(undefined, 1)).toEqual(undefined);
|
||||||
|
expect(limitTo({}, 1)).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return a copy of input array if X is exceeds array length', function () {
|
||||||
|
expect(limitTo(items, 19)).toEqual(items);
|
||||||
|
expect(limitTo(items, '9')).toEqual(items);
|
||||||
|
expect(limitTo(items, -9)).toEqual(items);
|
||||||
|
expect(limitTo(items, '-9')).toEqual(items);
|
||||||
|
|
||||||
|
expect(limitTo(items, 9)).not.toBe(items);
|
||||||
|
});
|
||||||
|
});
|
||||||
37
test/service/filter/orderBySpec.js
Normal file
37
test/service/filter/orderBySpec.js
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('Filter: orderBy', function() {
|
||||||
|
var orderBy;
|
||||||
|
beforeEach(inject(function($filter) {
|
||||||
|
orderBy = $filter('orderBy');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should return same array if predicate is falsy', function() {
|
||||||
|
var array = [1, 2, 3];
|
||||||
|
expect(orderBy(array)).toBe(array);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shouldSortArrayInReverse', function() {
|
||||||
|
assertJsonEquals([{a:15},{a:2}], orderBy([{a:15},{a:2}], 'a', true));
|
||||||
|
assertJsonEquals([{a:15},{a:2}], orderBy([{a:15},{a:2}], 'a', "T"));
|
||||||
|
assertJsonEquals([{a:15},{a:2}], orderBy([{a:15},{a:2}], 'a', "reverse"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sort array by predicate', function() {
|
||||||
|
assertJsonEquals([{a:2, b:1},{a:15, b:1}],
|
||||||
|
orderBy([{a:15, b:1},{a:2, b:1}], ['a', 'b']));
|
||||||
|
assertJsonEquals([{a:2, b:1},{a:15, b:1}],
|
||||||
|
orderBy([{a:15, b:1},{a:2, b:1}], ['b', 'a']));
|
||||||
|
assertJsonEquals([{a:15, b:1},{a:2, b:1}],
|
||||||
|
orderBy([{a:15, b:1},{a:2, b:1}], ['+b', '-a']));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use function', function() {
|
||||||
|
expect(
|
||||||
|
orderBy(
|
||||||
|
[{a:15, b:1},{a:2, b:1}],
|
||||||
|
function(value) { return value.a; })).
|
||||||
|
toEqual([{a:2, b:1},{a:15, b:1}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue