aeq = ( function ( aeq ) {
/**
* Array with some extensions that mimics modern JavaScript.
* @memberof aeq
* @class
* @param {Array} arr The array object to extend. If not supplied, an empty
* arrayEx will be returned.
*/
var arrayEx = {
/**
* Loops through the elements in the array and executes a function.
* @memberof aeq.arrayEx
* @method
* @param {forEachArrayCallback} callback Function to execute for each element
*/
forEach: function ( callback ) {
var len = this.length;
for ( var i = 0; i < len; i++ ) {
callback( this[i], i, this );
}
},
/**
* Loops through the elements in the array and returns `true` if callback
* returns true for any element
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to execute for each element
* @return {boolean} Whether the function returned true for any
* element
*/
some: function ( callback ) {
var len = this.length;
for ( var i = 0; i < len; i++ ) {
if ( callback( this[i], i, this ) ) {
return true;
}
}
return false;
},
/**
* Loops through the elements in the array and returns `true` if callback
* returns true for all elements
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to execute for each element
* @return {boolean} Whether the function returned true for ALL
* elements
*/
every: function ( callback ) {
var len = this.length;
for ( var i = 0; i < len; i++ ) {
if ( !callback( this[i], i, this ) ) {
return false;
}
}
return true;
},
/**
* Gets first element in array
* @method
* @memberof aeq.arrayEx
* @return {any} First element in array
*/
first: function () {
if ( this.length === 0 ) {
throw new Error( 'There are no items in this array' );
}
return this[0];
},
/**
* Returns array element that triggers callback === true
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to execute for each element
* @param {any} [def] Default element to return if target be found
* @return {any} Array element that triggered callback, or default
*/
find: function ( callback, def ) {
var len = this.length;
for ( var i = 0; i < len; i++ ) {
if ( callback( this[i], i, this ) ) {
return this[i];
}
}
return def;
},
/**
* Returns index of array element that triggers callback === true
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to execute for each element
* @return {any} Index of array element that triggered callback, or -1
*/
findIndex: function ( callback ) {
var len = this.length;
for ( var i = 0; i < len; i++ ) {
if ( callback( this[i], i, this ) ) {
return i;
}
}
return -1;
},
/**
* Runs callback on each element, and returns a new arrayEx of elements that
* trigger callback === true
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to execute for each element
* @return {aeq.arrayEx} ArrayEx of filtered elements
*/
filter: function ( callback ) {
var filteredArr = [];
var len = this.length;
for ( var i = 0; i < len; i++ ) {
if ( callback( this[i], i, this ) ) {
filteredArr.push( this[i] );
}
}
return aeq.arrayEx( filteredArr );
},
/**
* Returns index of searchElement in an array, or -1 if not found
* @method
* @memberof aeq.arrayEx
* @param {any} searchElement Element to find in arrayEx
* @param {number} [fromIndex=0] Index to start searching from, or 0 if not passed
* @return {number} `-1` if element is not found, else index number
*/
indexOf: function ( searchElement, fromIndex ) {
var k;
// 1. Let o be the result of calling ToObject passing
// the this value as the argument.
if ( this === null ) {
throw new TypeError( '"this" is null or not defined' );
}
var o = Object( this );
// 2. Let lenValue be the result of calling the Get
// internal method of o with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = o.length >>> 0;
// 4. If len is 0, return -1.
if ( len === 0 ) {
return -1;
}
// 5. If argument fromIndex was passed let n be
// ToInteger(fromIndex); else let n be 0.
var n = +fromIndex || 0;
if ( Math.abs( n ) === Infinity ) {
n = 0;
}
// 6. If n >= len, return -1.
if ( n >= len ) {
return -1;
}
// 7. If n >= 0, then Let k be n.
// 8. Else, n<0, Let k be len - abs(n).
// If k is less than 0, then let k be 0.
k = Math.max( n >= 0 ? n : len - Math.abs( n ), 0 );
// 9. Repeat, while k < len
while ( k < len ) {
// A. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the
// HasProperty internal method of o with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
// i. Let elementK be the result of calling the Get
// internal method of o with the argument ToString(k).
// ii. Let same be the result of applying the
// Strict Equality Comparison Algorithm to
// searchElement and elementK.
// iii. If same is true, return k.
if ( k in o && o[k] === searchElement ) {
return k;
}
k++;
}
return -1;
},
/**
* Creates a new array with the results of calling a provided function on every
* element in the calling array
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to execute for each element
* @return {aeq.arrayEx} A new array with each element being the result
* of the callback function
* @see [Array.prototype.map()]{@link
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map/}
* for more info
*/
map: function ( callback ) {
var selectedArr = [];
var len = this.length;
for ( var i = 0; i < len; i++ ) {
selectedArr.push( callback( this[i], i, this ) );
}
return aeq.arrayEx( selectedArr );
},
/**
* Groups an array by some condition as determined by each element
* @method
* @memberof aeq.arrayEx
* @param {Function} callback Function to determine the key to group by
* @return {object} An object whose keys are the result of callback and each
* value is an array of elements matching key
*/
groupBy: function ( callback ) {
var obj = {};
var len = this.length;
for ( var i = 0; i < len; i++ ) {
var key = callback( this[i], i, this ) || 'undefined';
var arr = obj[key] || [];
arr.push( this[i] );
obj[key.toString()] = arr;
}
return obj;
},
/**
* Inserts an element into arrayEx at specified index
* @method
* @memberof aeq.arrayEx
* @param {any} insert Element to insert
* @param {number} index Index to insert element at
*/
insertAt: function ( insert, index ) {
this.splice( index, 0, insert );
},
/**
* Sets or gets an attribute value for all objects in the array. When getting a
* value, it only returns the valure from the first object.
* @method
* @memberof aeq.arrayEx
* @param {string} attributeName The name of the attribute to get or set.
* @param {Any} [newValue] The value to set. If not given, will only get
* the value of the first object.
* @return {Any} when getting, the value of the attribute.
* When setting, `undefined`.
* @see aeq.attr
*/
attr: function () {
// Add this array object to the beginning of arguments
[].unshift.call( arguments, this );
return aeq.attr.apply( this, arguments );
}
};
aeq.arrayEx = function ( arr ) {
arr = setDefault( arr, [] );
if ( arr._init ) return arr;
/**
* Used to check if array is already extended.
* @memberof aeq.arrayEx
* @private
* @type {Boolean}
* @default
*/
arr._init = true;
/**
* @memberof aeq.arrayEx
* @private
* @type {Boolean}
* @default
*/
arr.isAeq = true;
aeq.extend( arr, arrayEx );
return arr;
};
return aeq;
}( aeq || {}) );