Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat(sliceFilter): create slice filter - more powerful limitTo filter #6399

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions angularFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ angularFiles = {
'src/ng/filter/filters.js',
'src/ng/filter/limitTo.js',
'src/ng/filter/orderBy.js',
'src/ng/filter/slice.js',

'src/ng/directive/directives.js',
'src/ng/directive/a.js',
Expand Down
2 changes: 2 additions & 0 deletions src/ng/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ function $FilterProvider($provide) {
lowercaseFilter: false,
numberFilter: false,
orderByFilter: false,
sliceFilter: false,
uppercaseFilter: false,
*/

Expand All @@ -127,5 +128,6 @@ function $FilterProvider($provide) {
register('lowercase', lowercaseFilter);
register('number', numberFilter);
register('orderBy', orderByFilter);
register('slice', sliceFilter);
register('uppercase', uppercaseFilter);
}
85 changes: 85 additions & 0 deletions src/ng/filter/slice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
'use strict';

/**
* @ngdoc filter
* @name slice
* @function
*
* @description
* Creates a new array or string containing only the elements specified. The elements are extracted
* from an index value up to either the end of the array or string, or to the optional end index specified.
*
* @param {Array|string} input Source array or string to be limited.
* @param {string|number} begin The zero-based index to begin extracting from the array or string.
* If the `begin` number is positive, slice counts to `begin` starting with 0. If the `begin`
* number is negative, `slice` extracts that number of items from the end of the source array/string.
* @param {string|number} end The zero-based index to end extracting from the array or string.
* @returns {Array|string} A new sub-array or substring starting at the index `begin` or less if input array
* had less than `limit` elements.
*
* @example
<example>
<file name="index.html">
<script>
function Ctrl($scope) {
$scope.numbers = [1,2,3,4,5,6,7,8,9];
$scope.letters = "abcdefghi";
$scope.begin = 3;
$scope.end = 6;
}
</script>
<div ng-controller="Ctrl">
Slice input from index <input type="integer" ng-model="begin"> to <input type="integer" ng-model="end">
<p>Output numbers: {{ numbers | slice:begin:end }}</p>
<p>Output letters: {{ letters | slice:begin:end }}</p>
</div>
</file>
<file name="protractor.js" type="protractor">
var beginInput = element(by.model('begin'));
var endInput = element(by.model('end'));
var slicedNumbers = element(by.binding('numbers | slice:begin:end'));
var slicedLetters = element(by.binding('letters | slice:begin:end'));

it('should limit the number array to first three items', function() {
expect(beginInput.getAttribute('value')).toBe('3');
expect(endInput.getAttribute('value')).toBe('6');
expect(slicedNumbers.getText()).toEqual('Output numbers: [4,5,6]');
expect(slicedLetters.getText()).toEqual('Output letters: def');
});

it('should update the output when -3 is entered', function() {
beginInput.clear();
beginInput.sendKeys('-3');
endInput.clear();
endInput.sendKeys('');
expect(slicedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
expect(slicedLetters.getText()).toEqual('Output letters: ghi');
});

it('should not exceed the maximum size of input array', function() {
beginInput.clear();
beginInput.sendKeys('0');
endInput.clear();
endInput.sendKeys('100');
expect(slicedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
expect(slicedLetters.getText()).toEqual('Output letters: abcdefghi');
});
</file>
</example>
*/
function sliceFilter(){
return function(input, begin, end) {
if (!isArray(input) && !isString(input)) return input;

begin = int(begin);

// Slice needs end to be undefined if blank or invalid, or it can give it a value of 0
if ((isString(end) && end) || isNumber(end)) {
end = int(end);
} else {
end = undefined;
}

return input.slice(begin, end);
};
}
92 changes: 92 additions & 0 deletions test/ng/filter/sliceSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
'use strict';

describe('Filter: slice', function() {
var items;
var str
var slice;

beforeEach(inject(function($filter) {
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
str = "stuvwxyz";
slice = $filter('slice');
}));

it('should return all items after index X when X is positive', function() {
expect(slice(items, 4)).toEqual(['e', 'f', 'g', 'h']);
expect(slice(items, '4')).toEqual(['e', 'f', 'g', 'h']);

expect(slice(str, 4)).toEqual("wxyz");
expect(slice(str, '4')).toEqual("wxyz");
});

it('should return the last X items when X is negative', function() {
expect(slice(items, -3)).toEqual(['f', 'g', 'h']);
expect(slice(items, '-3')).toEqual(['f', 'g', 'h']);

expect(slice(str, -3)).toEqual("xyz");
expect(slice(str, '-3')).toEqual("xyz");
});

it('should return an extracted array between index X and X', function () {
expect(slice(items, 3, 6)).toEqual(['d', 'e', 'f']);
expect(slice(items, '3', '6')).toEqual(['d', 'e', 'f']);

expect(slice(str, 3, 6)).toEqual("vwx");
expect(slice(str, '3', '6')).toEqual("vwx");
});

it('should return a string or array the same as slice()', function () {
expect(slice(items, -2, -4)).toEqual([]);
expect(slice(items, -4, -2)).toEqual(['e', 'f']);
expect(slice(items, 2, -2)).toEqual(['c', 'd', 'e', 'f']);
expect(slice(items, 2, -8)).toEqual([]);

expect(slice(str, -2, -4)).toEqual("");
expect(slice(str, -4, -2)).toEqual("wx");
expect(slice(str, 2, -2)).toEqual("uvwx");
expect(slice(str, -2, -8)).toEqual("");
});

it('should return the source array when X cannot be parsed', function() {
expect(slice(items, 'bogus')).toEqual(items);
expect(slice(items, 'null')).toEqual(items);
expect(slice(items, 'undefined')).toEqual(items);
expect(slice(items, null)).toEqual(items);
expect(slice(items, undefined)).toEqual(items);
});

it('should return the source string when X cannot be parsed', function() {
expect(slice(str, 'bogus')).toEqual(str);
expect(slice(str, 'null')).toEqual(str);
expect(slice(str, 'undefined')).toEqual(str);
expect(slice(str, null)).toEqual(str);
expect(slice(str, undefined)).toEqual(str);
});

it('should return input if not String or Array', function() {
expect(slice(1,1)).toEqual(1);
expect(slice(null, 1)).toEqual(null);
expect(slice(undefined, 1)).toEqual(undefined);
expect(slice({}, 1)).toEqual({});
});

it('should return an empty array or string if X is positive and exceeds input length', function () {
expect(slice(items, 9)).toEqual([]);
expect(slice(items, '9')).toEqual([]);

expect(slice(str, 9)).toEqual("");
expect(slice(str, '9')).toEqual("");

expect(slice(items, 9)).not.toBe(items);
expect(slice(str, 9)).not.toBe(str);
});

it('should return the source array or string if X is negative and exceeds input length', function() {
expect(slice(items, -9)).toEqual(items);
expect(slice(items, '-9')).toEqual(items);

expect(slice(str, -9)).toEqual(str);
expect(slice(str, '-9')).toEqual(str);
});

});