diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js index 8ae08eb81dc6..13a236b65cc7 100644 --- a/src/ng/filter/orderBy.js +++ b/src/ng/filter/orderBy.js @@ -32,6 +32,10 @@ * If the predicate is missing or empty then it defaults to `'+'`. * * @param {boolean=} reverse Reverse the order of the array. + * @param {function(object1, object2, defaultCompare)} compare The custom compare function to use. + * Should return -1 if object2 is bigger than object1. 0 if the same. 1 if object2 is smaller than + * object1. The third variable is the default compare function which can be reused. It accepts + * object1, and object2 as parameter. * @returns {Array} Sorted copy of the source array. * * @example @@ -47,6 +51,16 @@ {name:'Adam', phone:'555-5678', age:35}, {name:'Julie', phone:'555-8765', age:29}]; $scope.predicate = '-age'; + $scope.ladiesFirst = function(name1, name2, defaultComparator) { + if (name1 === 'Julie' || name1 === 'Mary') { + return -1; + } + if (name2 === 'Julie' || name2 === 'Mary') { + return 1; + } + return defaultComparator(name1, name2); + }; + $scope.customSort; }]);
Name - (^) | -Phone Number | -Age | +Name + (^) | +Phone Number | +Age | +Ladies First |
---|---|---|---|---|---|---|
{{friend.name}} | {{friend.phone}} | {{friend.age}} | @@ -86,6 +101,7 @@ (^)Phone Number | Age | +Ladies First | |
{{friend.name}} | @@ -107,8 +123,17 @@ { name: 'Adam', phone: '555-5678', age: 35 }, { name: 'Julie', phone: '555-8765', age: 29 } ]; - $scope.order = function(predicate, reverse) { - $scope.friends = orderBy($scope.friends, predicate, reverse); + $scope.ladiesFirst = function(name1, name2, defaultComparator) { + if (name1 === 'Julie' || name1 === 'Mary') { + return -1; + } + if (name2 === 'Julie' || name2 === 'Mary') { + return 1; + } + return defaultComparator(name1, name2); + }; + $scope.order = function(predicate, reverse, customSort) { + $scope.friends = orderBy($scope.friends, predicate, reverse, customSort); }; $scope.order('-age',false); }]); @@ -117,9 +142,10 @@ */ orderByFilter.$inject = ['$parse']; function orderByFilter($parse) { - return function(array, sortPredicate, reverseOrder) { + return function(array, sortPredicate, reverseOrder, compare) { if (!(isArrayLike(array))) return array; sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate]; + compare = isFunction(compare) ? compare : defaultCompare; if (sortPredicate.length === 0) { sortPredicate = ['+']; } sortPredicate = sortPredicate.map(function(predicate) { var descending = false, get = predicate || identity; @@ -131,19 +157,19 @@ function orderByFilter($parse) { if (predicate === '') { // Effectively no predicate was passed so we compare identity return reverseComparator(function(a, b) { - return compare(a, b); + return compare(a, b, defaultCompare); }, descending); } get = $parse(predicate); if (get.constant) { var key = get(); return reverseComparator(function(a, b) { - return compare(a[key], b[key]); + return compare(a[key], b[key], defaultCompare); }, descending); } } return reverseComparator(function(a, b) { - return compare(get(a),get(b)); + return compare(get(a), get(b), defaultCompare); }, descending); }); return slice.call(array).sort(reverseComparator(comparator, reverseOrder)); @@ -155,6 +181,7 @@ function orderByFilter($parse) { } return 0; } + function reverseComparator(comp, descending) { return descending ? function(a, b) {return comp(b,a);} @@ -185,7 +212,7 @@ function orderByFilter($parse) { return ''; } - function compare(v1, v2) { + function defaultCompare(v1, v2) { var t1 = typeof v1; var t2 = typeof v2; if (t1 === t2 && t1 === "object") { diff --git a/test/ng/filter/orderBySpec.js b/test/ng/filter/orderBySpec.js index 120425ba78ea..5011ae7549a7 100644 --- a/test/ng/filter/orderBySpec.js +++ b/test/ng/filter/orderBySpec.js @@ -105,7 +105,6 @@ describe('Filter: orderBy', function() { }).toThrow(); }); - it('should not reverse array of objects with no predicate', function() { var array = [ { id: 2 }, @@ -116,7 +115,6 @@ describe('Filter: orderBy', function() { expect(orderBy(array)).toEqualData(array); }); - it('should not reverse array of objects with null prototype and no predicate', function() { var array = [2,1,4,3].map(function(id) { var obj = Object.create(null); @@ -126,7 +124,6 @@ describe('Filter: orderBy', function() { expect(orderBy(array)).toEqualData(array); }); - it('should sort nulls as Array.prototype.sort', function() { var array = [ { id: 2 }, @@ -141,6 +138,40 @@ describe('Filter: orderBy', function() { null ]); }); + + it('should use a custom compare function', function() { + function localeCompareTo(v1, v2) { + return v1.localeCompare(v2); + } + + function landCompare(v1, v2, defaultCompare) { + if (v1 === 'Dreamland') { + return -1; + } + if (v2 === 'Dreamland') { + return 1; + } + return defaultCompare(v1, v2); + } + + expect(orderBy(['abc', 'äbc', 'öpq', 'opq'], null, false, localeCompareTo)) + .toEqualData(['abc', 'äbc', 'opq', 'öpq']); + expect(orderBy(['abc', 'äbc', 'öpq', 'opq'], null, true, localeCompareTo)) + .toEqualData(['öpq', 'opq', 'äbc', 'abc']); + expect(orderBy([ + {'text': 'abc'}, + {'text': 'äbc'}, + {'text': 'öpq'}, + {'text': 'opq'}], + 'text', false, localeCompareTo)) + .toEqualData([ + {'text': 'abc'}, + {'text': 'äbc'}, + {'text': 'opq'}, + {'text': 'öpq'}]); + expect(orderBy(['Germany', 'United States', 'Dreamland', 'Badland'], null, false, landCompare)) + .toEqualData(['Dreamland', 'Badland', 'Germany', 'United States']); + }); });