      1 if (!Array.prototype.indexOf) {
      2   Array.prototype.indexOf = function(value, from) {
      3     var len = this.length >>> 0;
      4     from = Number(from) || 0;
      5     from = Math[from < 0 ? 'ceil' : 'floor'](from);
      6     if (from < 0) {
      7       from += len;
      8     }
      9     for (; from < len; from++) {
     10       if (from in this && this[from] === value) {
     11         return from;
     12       }
     13     }
     14     return -1;
     15   };
     16 }
     17
     18 if (!Array.prototype.forEach) {
     19   Array.prototype.forEach = function(fn, context) {
     20     for (var i = 0, len = this.length >>> 0; i < len; i++) {
     21       if (i in this) {
     22         fn.call(context, this[i], i, this);
     23       }
     24     }
     25   };
     26 }
     27
     28 if (!Array.prototype.map) {
     29   Array.prototype.map = function(fn, context) {
     30     var result = [ ];
     31     for (var i = 0, len = this.length >>> 0; i < len; i++) {
     32       if (i in this) {
     33         result[i] = fn.call(context, this[i], i, this);
     34       }
     35     }
     36     return result;
     37   };
     38 }
     39
     40 if (!Array.prototype.every) {
     41   Array.prototype.every = function(fn, context) {
     42     for (var i = 0, len = this.length >>> 0; i < len; i++) {
     43       if (i in this && !fn.call(context, this[i], i, this)) {
     44         return false;
     45       }
     46     }
     47     return true;
     48   };
     49 }
     50
     51 if (!Array.prototype.some) {
     52   Array.prototype.some = function(fn, context) {
     53     for (var i = 0, len = this.length >>> 0; i < len; i++) {
     54       if (i in this && fn.call(context, this[i], i, this)) {
     55         return true;
     56       }
     57     }
     58     return false;
     59   };
     60 }
     61
     62 if (!Array.prototype.filter) {
     63   Array.prototype.filter = function(fn, context) {
     64     var result = [ ], val;
     65     for (var i = 0, len = this.length >>> 0; i < len; i++) {
     66       if (i in this) {
     67         val = this[i]; // in case fn mutates this
     68         if (fn.call(context, val, i, this)) {
     69           result.push(val);
     70         }
     71       }
     72     }
     73     return result;
     74   };
     75 }
     76
     77 if (!Array.prototype.reduce) {
     78   Array.prototype.reduce = function(fn /*, initial*/) {
     79     var len = this.length >>> 0,
     80         i = 0,
     81         rv;
     82
     83     if (arguments.length > 1) {
     84       rv = arguments[1];
     85     }
     86     else {
     87       do {
     88         if (i in this) {
     89           rv = this[i++];
     90           break;
     91         }
     92         // if array contains no values, no initial value to return
     93         if (++i >= len) {
     94           throw new TypeError();
     95         }
     96       }
     97       while (true);
     98     }
     99     for (; i < len; i++) {
    100       if (i in this) {
    101         rv = fn.call(null, rv, this[i], i, this);
    102       }
    103     }
    104     return rv;
    105   };
    106 }
    107
    108 /**
    109  * Invokes method on all items in a given array
    110  * @method invoke
    111  * @memberOf fabric.util.array
    112  * @param {Array} array Array to iterate over
    113  * @param {String} method Name of a method to invoke
    114  */
    115 function invoke(array, method) {
    116   var args = slice.call(arguments, 2), result = [ ];
    117   for (var i = 0, len = array.length; i < len; i++) {
    118     result[i] = args.length ? array[i][method].apply(array[i], args) : array[i][method].call(array[i]);
    119   }
    120   return result;
    121 }
    122
    123 /**
    124  * Finds maximum value in array (not necessarily "first" one)
    125  * @method max
    126  * @memberOf fabric.util.array
    127  * @param {Array} array Array to iterate over
    128  * @param {String} byProperty
    129  */
    130 function max(array, byProperty) {
    131   var i = array.length - 1,
    132       result = byProperty ? array[i][byProperty] : array[i];
    133   if (byProperty) {
    134     while (i--) {
    135       if (array[i][byProperty] >= result) {
    136         result = array[i][byProperty];
    137       }
    138     }
    139   }
    140   else {
    141     while (i--) {
    142       if (array[i] >= result) {
    143         result = array[i];
    144       }
    145     }
    146   }
    147   return result;
    148 }
    149
    150 /**
    151  * Finds minimum value in array (not necessarily "first" one)
    152  * @method min
    153  * @memberOf fabric.util.array
    154  * @param {Array} array Array to iterate over
    155  * @param {String} byProperty
    156  */
    157 function min(array, byProperty) {
    158   var i = array.length - 1,
    159       result = byProperty ? array[i][byProperty] : array[i];
    160
    161   if (byProperty) {
    162     while (i--) {
    163       if (array[i][byProperty] < result) {
    164         result = array[i][byProperty];
    165       }
    166     }
    167   }
    168   else {
    169     while (i--) {
    170       if (array[i] < result) {
    171         result = array[i];
    172       }
    173     }
    174   }
    175   return result;
    176 }
    177
    178 /** @namespace */
    179 fabric.util.array = {
    180   invoke: invoke,
    181   min: min,
    182   max: max
    183 };