2011-08-29 01:28:46 +00:00
|
|
|
(function() {
|
2012-10-14 00:53:12 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
var slice = Array.prototype.slice;
|
2012-10-14 00:53:12 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
if (!Array.prototype.indexOf) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Finds index of an element in an array
|
|
|
|
|
* @param {Any} searchElement
|
|
|
|
|
* @param {Number} [fromIndex]
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Number}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-29 01:28:46 +00:00
|
|
|
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
|
|
|
|
|
if (this === void 0 || this === null) {
|
|
|
|
|
throw new TypeError();
|
|
|
|
|
}
|
|
|
|
|
var t = Object(this), len = t.length >>> 0;
|
|
|
|
|
if (len === 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
var n = 0;
|
|
|
|
|
if (arguments.length > 0) {
|
|
|
|
|
n = Number(arguments[1]);
|
|
|
|
|
if (n !== n) { // shortcut for verifying if it's NaN
|
|
|
|
|
n = 0;
|
|
|
|
|
}
|
2013-03-08 17:41:33 +00:00
|
|
|
else if (n !== 0 && n !== Number.POSITIVE_INFINITY && n !== Number.NEGATIVE_INFINITY) {
|
2011-08-29 01:28:46 +00:00
|
|
|
n = (n > 0 || -1) * Math.floor(Math.abs(n));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (n >= len) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
|
|
|
|
|
for (; k < len; k++) {
|
|
|
|
|
if (k in t && t[k] === searchElement) {
|
|
|
|
|
return k;
|
2011-08-14 21:35:36 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
2012-10-14 00:53:12 +00:00
|
|
|
};
|
2011-08-14 21:35:36 +00:00
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
if (!Array.prototype.forEach) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Iterates an array, invoking callback for each element
|
|
|
|
|
* @param {Function} fn Callback to invoke for each element
|
|
|
|
|
* @param {Object} [context] Context to invoke callback in
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Array}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
Array.prototype.forEach = function(fn, context) {
|
|
|
|
|
for (var i = 0, len = this.length >>> 0; i < len; i++) {
|
|
|
|
|
if (i in this) {
|
|
|
|
|
fn.call(context, this[i], i, this);
|
2012-10-14 00:53:12 +00:00
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
};
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
if (!Array.prototype.map) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Returns a result of iterating over an array, invoking callback for each element
|
|
|
|
|
* @param {Function} fn Callback to invoke for each element
|
|
|
|
|
* @param {Object} [context] Context to invoke callback in
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Array}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
Array.prototype.map = function(fn, context) {
|
|
|
|
|
var result = [ ];
|
|
|
|
|
for (var i = 0, len = this.length >>> 0; i < len; i++) {
|
|
|
|
|
if (i in this) {
|
|
|
|
|
result[i] = fn.call(context, this[i], i, this);
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
if (!Array.prototype.every) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Returns true if a callback returns truthy value for all elements in an array
|
|
|
|
|
* @param {Function} fn Callback to invoke for each element
|
|
|
|
|
* @param {Object} [context] Context to invoke callback in
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Boolean}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
Array.prototype.every = function(fn, context) {
|
|
|
|
|
for (var i = 0, len = this.length >>> 0; i < len; i++) {
|
|
|
|
|
if (i in this && !fn.call(context, this[i], i, this)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
if (!Array.prototype.some) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Returns true if a callback returns truthy value for at least one element in an array
|
|
|
|
|
* @param {Function} fn Callback to invoke for each element
|
|
|
|
|
* @param {Object} [context] Context to invoke callback in
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Boolean}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
Array.prototype.some = function(fn, context) {
|
|
|
|
|
for (var i = 0, len = this.length >>> 0; i < len; i++) {
|
|
|
|
|
if (i in this && fn.call(context, this[i], i, this)) {
|
|
|
|
|
return true;
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
if (!Array.prototype.filter) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Returns the result of iterating over elements in an array
|
|
|
|
|
* @param {Function} fn Callback to invoke for each element
|
|
|
|
|
* @param {Object} [context] Context to invoke callback in
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Array}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
Array.prototype.filter = function(fn, context) {
|
|
|
|
|
var result = [ ], val;
|
|
|
|
|
for (var i = 0, len = this.length >>> 0; i < len; i++) {
|
2010-06-17 14:00:47 +00:00
|
|
|
if (i in this) {
|
2011-08-14 21:35:36 +00:00
|
|
|
val = this[i]; // in case fn mutates this
|
|
|
|
|
if (fn.call(context, val, i, this)) {
|
|
|
|
|
result.push(val);
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Array.prototype.reduce) {
|
2012-12-16 19:44:26 +00:00
|
|
|
/**
|
|
|
|
|
* Returns "folded" (reduced) result of iterating over elements in an array
|
|
|
|
|
* @param {Function} fn Callback to invoke for each element
|
|
|
|
|
* @param {Object} [context] Context to invoke callback in
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Any}
|
2012-12-16 19:44:26 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
Array.prototype.reduce = function(fn /*, initial*/) {
|
|
|
|
|
var len = this.length >>> 0,
|
|
|
|
|
i = 0,
|
|
|
|
|
rv;
|
|
|
|
|
|
|
|
|
|
if (arguments.length > 1) {
|
|
|
|
|
rv = arguments[1];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
do {
|
|
|
|
|
if (i in this) {
|
|
|
|
|
rv = this[i++];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// if array contains no values, no initial value to return
|
|
|
|
|
if (++i >= len) {
|
|
|
|
|
throw new TypeError();
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
while (true);
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
for (; i < len; i++) {
|
|
|
|
|
if (i in this) {
|
|
|
|
|
rv = fn.call(null, rv, this[i], i, this);
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
return rv;
|
|
|
|
|
};
|
|
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
/**
|
|
|
|
|
* Invokes method on all items in a given array
|
|
|
|
|
* @memberOf fabric.util.array
|
|
|
|
|
* @param {Array} array Array to iterate over
|
|
|
|
|
* @param {String} method Name of a method to invoke
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Array}
|
2011-08-14 21:35:36 +00:00
|
|
|
*/
|
|
|
|
|
function invoke(array, method) {
|
|
|
|
|
var args = slice.call(arguments, 2), result = [ ];
|
|
|
|
|
for (var i = 0, len = array.length; i < len; i++) {
|
|
|
|
|
result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
|
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
/**
|
|
|
|
|
* Finds maximum value in array (not necessarily "first" one)
|
|
|
|
|
* @memberOf fabric.util.array
|
|
|
|
|
* @param {Array} array Array to iterate over
|
|
|
|
|
* @param {String} byProperty
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Any}
|
2011-08-14 21:35:36 +00:00
|
|
|
*/
|
|
|
|
|
function max(array, byProperty) {
|
2011-09-20 18:25:25 +00:00
|
|
|
if (!array || array.length === 0) return undefined;
|
2012-10-14 00:53:12 +00:00
|
|
|
|
|
|
|
|
var i = array.length - 1,
|
2011-08-14 21:35:36 +00:00
|
|
|
result = byProperty ? array[i][byProperty] : array[i];
|
|
|
|
|
if (byProperty) {
|
|
|
|
|
while (i--) {
|
|
|
|
|
if (array[i][byProperty] >= result) {
|
|
|
|
|
result = array[i][byProperty];
|
|
|
|
|
}
|
2010-07-09 14:21:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
else {
|
|
|
|
|
while (i--) {
|
|
|
|
|
if (array[i] >= result) {
|
|
|
|
|
result = array[i];
|
|
|
|
|
}
|
2010-07-09 14:21:40 +00:00
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
return result;
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
|
|
|
|
|
2011-08-14 21:35:36 +00:00
|
|
|
/**
|
|
|
|
|
* Finds minimum value in array (not necessarily "first" one)
|
|
|
|
|
* @memberOf fabric.util.array
|
|
|
|
|
* @param {Array} array Array to iterate over
|
|
|
|
|
* @param {String} byProperty
|
2013-04-24 16:58:04 +00:00
|
|
|
* @return {Any}
|
2011-08-14 21:35:36 +00:00
|
|
|
*/
|
|
|
|
|
function min(array, byProperty) {
|
2011-09-20 18:25:25 +00:00
|
|
|
if (!array || array.length === 0) return undefined;
|
2012-10-14 00:53:12 +00:00
|
|
|
|
|
|
|
|
var i = array.length - 1,
|
2011-08-14 21:35:36 +00:00
|
|
|
result = byProperty ? array[i][byProperty] : array[i];
|
|
|
|
|
|
|
|
|
|
if (byProperty) {
|
|
|
|
|
while (i--) {
|
|
|
|
|
if (array[i][byProperty] < result) {
|
|
|
|
|
result = array[i][byProperty];
|
|
|
|
|
}
|
2010-07-09 14:21:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
else {
|
|
|
|
|
while (i--) {
|
|
|
|
|
if (array[i] < result) {
|
|
|
|
|
result = array[i];
|
|
|
|
|
}
|
2010-07-09 14:21:40 +00:00
|
|
|
}
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
2011-08-14 21:35:36 +00:00
|
|
|
return result;
|
2010-06-17 14:00:47 +00:00
|
|
|
}
|
|
|
|
|
|
2013-02-26 23:48:27 +00:00
|
|
|
/**
|
2013-04-24 16:58:04 +00:00
|
|
|
* @namespace fabric.util.array
|
2013-02-26 23:48:27 +00:00
|
|
|
*/
|
2011-08-14 21:35:36 +00:00
|
|
|
fabric.util.array = {
|
|
|
|
|
invoke: invoke,
|
|
|
|
|
min: min,
|
|
|
|
|
max: max
|
|
|
|
|
};
|
2012-10-14 00:53:12 +00:00
|
|
|
|
2013-04-24 16:58:04 +00:00
|
|
|
})();
|