feat(limitTo): add support for array-like objects
Fixes #14657 Closes #14694
This commit is contained in:
committed by
Georgios Kalpakas
parent
3360b44be6
commit
f467dc3dd5
+21
-14
@@ -6,21 +6,22 @@
|
||||
* @kind function
|
||||
*
|
||||
* @description
|
||||
* Creates a new array or string containing only a specified number of elements. The elements
|
||||
* are taken from either the beginning or the end of the source array, string or number, as specified by
|
||||
* the value and sign (positive or negative) of `limit`. If a number is used as input, it is
|
||||
* converted to a string.
|
||||
* Creates a new array or string containing only a specified number of elements. The elements are
|
||||
* taken from either the beginning or the end of the source array, string or number, as specified by
|
||||
* the value and sign (positive or negative) of `limit`. Other array-like objects are also supported
|
||||
* (e.g. array subclasses, NodeLists, jqLite/jQuery collections etc). If a number is used as input,
|
||||
* it is converted to a string.
|
||||
*
|
||||
* @param {Array|string|number} input Source array, string or number to be limited.
|
||||
* @param {string|number} limit The length of the returned array or string. If the `limit` number
|
||||
* @param {Array|ArrayLike|string|number} input - Array/array-like, string or number to be limited.
|
||||
* @param {string|number} limit - The length of the returned array or string. If the `limit` number
|
||||
* is positive, `limit` number of items from the beginning of the source array/string are copied.
|
||||
* If the number is negative, `limit` number of items from the end of the source array/string
|
||||
* are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,
|
||||
* the input will be returned unchanged.
|
||||
* @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin`
|
||||
* indicates an offset from the end of `input`. Defaults to `0`.
|
||||
* @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
|
||||
* had less than `limit` elements.
|
||||
* @param {(string|number)=} begin - Index at which to begin limitation. As a negative index,
|
||||
* `begin` indicates an offset from the end of `input`. Defaults to `0`.
|
||||
* @returns {Array|string} A new sub-array or substring of length `limit` or less if the input had
|
||||
* less than `limit` elements.
|
||||
*
|
||||
* @example
|
||||
<example module="limitToExample">
|
||||
@@ -108,19 +109,25 @@ function limitToFilter() {
|
||||
if (isNaN(limit)) return input;
|
||||
|
||||
if (isNumber(input)) input = input.toString();
|
||||
if (!isArray(input) && !isString(input)) return input;
|
||||
if (!isArrayLike(input)) return input;
|
||||
|
||||
begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
|
||||
begin = (begin < 0) ? Math.max(0, input.length + begin) : begin;
|
||||
|
||||
if (limit >= 0) {
|
||||
return input.slice(begin, begin + limit);
|
||||
return sliceFn(input, begin, begin + limit);
|
||||
} else {
|
||||
if (begin === 0) {
|
||||
return input.slice(limit, input.length);
|
||||
return sliceFn(input, limit, input.length);
|
||||
} else {
|
||||
return input.slice(Math.max(0, begin + limit), begin);
|
||||
return sliceFn(input, Math.max(0, begin + limit), begin);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function sliceFn(input, begin, end) {
|
||||
if (isString(input)) return input.slice(begin, end);
|
||||
|
||||
return slice.call(input, begin, end);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,26 @@ describe('Filter: limitTo', function() {
|
||||
var items;
|
||||
var str;
|
||||
var number;
|
||||
var arrayLike;
|
||||
var limitTo;
|
||||
|
||||
beforeEach(inject(function($filter) {
|
||||
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
|
||||
str = "tuvwxyz";
|
||||
number = 100.045;
|
||||
arrayLike = {
|
||||
0: 'a',
|
||||
1: 'b',
|
||||
2: 'c',
|
||||
3: 'd',
|
||||
4: 'e',
|
||||
5: 'f',
|
||||
6: 'g',
|
||||
7: 'h',
|
||||
get length() {
|
||||
return Object.keys(this).length - 1;
|
||||
}
|
||||
};
|
||||
limitTo = $filter('limitTo');
|
||||
}));
|
||||
|
||||
@@ -21,6 +35,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(str, '3')).toEqual("tuv");
|
||||
expect(limitTo(number, 3)).toEqual("100");
|
||||
expect(limitTo(number, '3')).toEqual("100");
|
||||
expect(limitTo(arrayLike, 3)).toEqual(['a', 'b', 'c']);
|
||||
expect(limitTo(arrayLike, '3')).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
|
||||
it('should return the first X items beginning from index Y when X and Y are positive', function() {
|
||||
@@ -28,6 +44,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, '3', 3)).toEqual(['d', 'e', 'f']);
|
||||
expect(limitTo(str, 3, 3)).toEqual("wxy");
|
||||
expect(limitTo(str, '3', '3')).toEqual("wxy");
|
||||
expect(limitTo(arrayLike, 3, 3)).toEqual(['d', 'e', 'f']);
|
||||
expect(limitTo(arrayLike, '3', '3')).toEqual(['d', 'e', 'f']);
|
||||
});
|
||||
|
||||
it('should return the first X items beginning from index Y when X is positive and Y is negative', function() {
|
||||
@@ -35,6 +53,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, '3', -3)).toEqual(['f', 'g', 'h']);
|
||||
expect(limitTo(str, 3, -3)).toEqual("xyz");
|
||||
expect(limitTo(str, '3', '-3')).toEqual("xyz");
|
||||
expect(limitTo(arrayLike, 3, '-3')).toEqual(['f', 'g', 'h']);
|
||||
expect(limitTo(arrayLike, '3', -3)).toEqual(['f', 'g', 'h']);
|
||||
});
|
||||
|
||||
it('should return the last X items when X is negative', function() {
|
||||
@@ -44,6 +64,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(str, '-3')).toEqual("xyz");
|
||||
expect(limitTo(number, -3)).toEqual("045");
|
||||
expect(limitTo(number, '-3')).toEqual("045");
|
||||
expect(limitTo(arrayLike, -3)).toEqual(['f', 'g', 'h']);
|
||||
expect(limitTo(arrayLike, '-3')).toEqual(['f', 'g', 'h']);
|
||||
});
|
||||
|
||||
it('should return the last X items until index Y when X and Y are negative', function() {
|
||||
@@ -51,6 +73,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, '-3', -3)).toEqual(['c', 'd', 'e']);
|
||||
expect(limitTo(str, -3, -3)).toEqual("uvw");
|
||||
expect(limitTo(str, '-3', '-3')).toEqual("uvw");
|
||||
expect(limitTo(arrayLike, -3, '-3')).toEqual(['c', 'd', 'e']);
|
||||
expect(limitTo(arrayLike, '-3', -3)).toEqual(['c', 'd', 'e']);
|
||||
});
|
||||
|
||||
it('should return the last X items until index Y when X is negative and Y is positive', function() {
|
||||
@@ -58,19 +82,28 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, '-3', 4)).toEqual(['b', 'c', 'd']);
|
||||
expect(limitTo(str, -3, 4)).toEqual("uvw");
|
||||
expect(limitTo(str, '-3', '4')).toEqual("uvw");
|
||||
expect(limitTo(arrayLike, -3, '4')).toEqual(['b', 'c', 'd']);
|
||||
expect(limitTo(arrayLike, '-3', 4)).toEqual(['b', 'c', 'd']);
|
||||
});
|
||||
|
||||
it('should return an empty array when X = 0', function() {
|
||||
expect(limitTo(items, 0)).toEqual([]);
|
||||
expect(limitTo(items, '0')).toEqual([]);
|
||||
expect(limitTo(arrayLike, 0)).toEqual([]);
|
||||
expect(limitTo(arrayLike, '0')).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return entire array when X cannot be parsed', function() {
|
||||
expect(limitTo(items, 'bogus')).toEqual(items);
|
||||
expect(limitTo(items, 'null')).toEqual(items);
|
||||
expect(limitTo(items, 'undefined')).toEqual(items);
|
||||
expect(limitTo(items, null)).toEqual(items);
|
||||
expect(limitTo(items, undefined)).toEqual(items);
|
||||
expect(limitTo(items, 'bogus')).toBe(items);
|
||||
expect(limitTo(items, 'null')).toBe(items);
|
||||
expect(limitTo(items, 'undefined')).toBe(items);
|
||||
expect(limitTo(items, null)).toBe(items);
|
||||
expect(limitTo(items, undefined)).toBe(items);
|
||||
expect(limitTo(arrayLike, 'bogus')).toBe(arrayLike);
|
||||
expect(limitTo(arrayLike, 'null')).toBe(arrayLike);
|
||||
expect(limitTo(arrayLike, 'undefined')).toBe(arrayLike);
|
||||
expect(limitTo(arrayLike, null)).toBe(arrayLike);
|
||||
expect(limitTo(arrayLike, undefined)).toBe(arrayLike);
|
||||
});
|
||||
|
||||
it('should return an empty string when X = 0', function() {
|
||||
@@ -97,9 +130,14 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(str, '3', 'undefined')).toEqual(limitTo(str, '3'));
|
||||
expect(limitTo(str, '-3', null)).toEqual(limitTo(str, '-3', 0));
|
||||
expect(limitTo(str, 3, undefined)).toEqual(limitTo(str, 3));
|
||||
expect(limitTo(arrayLike, 3, 'bogus')).toEqual(limitTo(arrayLike, 3, 0));
|
||||
expect(limitTo(arrayLike, -3, 'null')).toEqual(limitTo(arrayLike, -3));
|
||||
expect(limitTo(arrayLike, '3', 'undefined')).toEqual(limitTo(arrayLike, '3', 0));
|
||||
expect(limitTo(arrayLike, '-3', null)).toEqual(limitTo(arrayLike, '-3'));
|
||||
expect(limitTo(arrayLike, 3, undefined)).toEqual(limitTo(arrayLike, 3, 0));
|
||||
});
|
||||
|
||||
it('should return input if not String or Array or Number', function() {
|
||||
it('should return input if not array-like or Number', function() {
|
||||
expect(limitTo(null, 1)).toEqual(null);
|
||||
expect(limitTo(undefined, 1)).toEqual(undefined);
|
||||
expect(limitTo({}, 1)).toEqual({});
|
||||
@@ -111,8 +149,13 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, '9')).toEqual(items);
|
||||
expect(limitTo(items, -9)).toEqual(items);
|
||||
expect(limitTo(items, '-9')).toEqual(items);
|
||||
expect(limitTo(arrayLike, 9)).toEqual(items);
|
||||
expect(limitTo(arrayLike, '9')).toEqual(items);
|
||||
expect(limitTo(arrayLike, -9)).toEqual(items);
|
||||
expect(limitTo(arrayLike, '-9')).toEqual(items);
|
||||
|
||||
expect(limitTo(items, 9)).not.toBe(items);
|
||||
expect(limitTo(arrayLike, 9)).not.toBe(arrayLike);
|
||||
});
|
||||
|
||||
it('should return the entire string if X exceeds input length', function() {
|
||||
@@ -129,6 +172,10 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, 'Infinity')).toEqual(items);
|
||||
expect(limitTo(items, -Infinity)).toEqual(items);
|
||||
expect(limitTo(items, '-Infinity')).toEqual(items);
|
||||
expect(limitTo(arrayLike, Infinity)).toEqual(items);
|
||||
expect(limitTo(arrayLike, 'Infinity')).toEqual(items);
|
||||
expect(limitTo(arrayLike, -Infinity)).toEqual(items);
|
||||
expect(limitTo(arrayLike, '-Infinity')).toEqual(items);
|
||||
});
|
||||
|
||||
it('should return the entire string when limited by Infinity', function() {
|
||||
@@ -141,6 +188,8 @@ describe('Filter: limitTo', function() {
|
||||
it('should return an empty array if Y exceeds input length', function() {
|
||||
expect(limitTo(items, '3', 12)).toEqual([]);
|
||||
expect(limitTo(items, -3, '12')).toEqual([]);
|
||||
expect(limitTo(arrayLike, '3', 12)).toEqual([]);
|
||||
expect(limitTo(arrayLike, -3, '12')).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return an empty string if Y exceeds input length', function() {
|
||||
@@ -153,6 +202,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, '-4', -12)).toEqual(['e', 'f', 'g', 'h']);
|
||||
expect(limitTo(str, 4, '-12')).toEqual("tuvw");
|
||||
expect(limitTo(str, '-4', -12)).toEqual("wxyz");
|
||||
expect(limitTo(arrayLike, 4, '-12')).toEqual(['a', 'b', 'c', 'd']);
|
||||
expect(limitTo(arrayLike, '-4', -12)).toEqual(['e', 'f', 'g', 'h']);
|
||||
});
|
||||
|
||||
it('should return the entire string beginning from Y if X is positive and X+Y exceeds input length', function() {
|
||||
@@ -160,6 +211,8 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, 7, -3)).toEqual(['f', 'g', 'h']);
|
||||
expect(limitTo(str, 6, 3)).toEqual("wxyz");
|
||||
expect(limitTo(str, 6, -3)).toEqual("xyz");
|
||||
expect(limitTo(arrayLike, 7, 3)).toEqual(['d', 'e', 'f', 'g', 'h']);
|
||||
expect(limitTo(arrayLike, 7, -3)).toEqual(['f', 'g', 'h']);
|
||||
});
|
||||
|
||||
it('should return the entire string until index Y if X is negative and X+Y exceeds input length', function() {
|
||||
@@ -167,5 +220,20 @@ describe('Filter: limitTo', function() {
|
||||
expect(limitTo(items, -7, -3)).toEqual(['a', 'b', 'c', 'd', 'e']);
|
||||
expect(limitTo(str, -6, 3)).toEqual("tuv");
|
||||
expect(limitTo(str, -6, -3)).toEqual("tuvw");
|
||||
expect(limitTo(arrayLike, -7, 3)).toEqual(['a', 'b', 'c']);
|
||||
expect(limitTo(arrayLike, -7, -3)).toEqual(['a', 'b', 'c', 'd', 'e']);
|
||||
});
|
||||
|
||||
it('should not throw an error if used with an array like object', function() {
|
||||
function getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
var argsObj = getArguments({name: 'Misko'}, {name: 'Igor'}, {name: 'Brad'});
|
||||
|
||||
var nodeList = jqLite("<p><span>Misko</span><span>Igor</span><span>Brad</span></p>")[0].childNodes;
|
||||
|
||||
expect(limitTo(argsObj, 2).length).toBe(2);
|
||||
expect(limitTo('abc', 1).length).toBe(1);
|
||||
expect(limitTo(nodeList, 2).length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user