client/lib/underscore.js
changeset 262 f6d0fa1db02a
parent 211 d87f6bdee43d
equal deleted inserted replaced
261:c6aa9772269c 262:f6d0fa1db02a
     1 //     Underscore.js 1.5.2
     1 //     Underscore.js 1.6.0
     2 //     http://underscorejs.org
     2 //     http://underscorejs.org
     3 //     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     3 //     (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
     4 //     Underscore may be freely distributed under the MIT license.
     4 //     Underscore may be freely distributed under the MIT license.
     5 
     5 
     6 (function() {
     6 (function() {
     7 
     7 
     8   // Baseline setup
     8   // Baseline setup
    63   } else {
    63   } else {
    64     root._ = _;
    64     root._ = _;
    65   }
    65   }
    66 
    66 
    67   // Current version.
    67   // Current version.
    68   _.VERSION = '1.5.2';
    68   _.VERSION = '1.6.0';
    69 
    69 
    70   // Collection Functions
    70   // Collection Functions
    71   // --------------------
    71   // --------------------
    72 
    72 
    73   // The cornerstone, an `each` implementation, aka `forEach`.
    73   // The cornerstone, an `each` implementation, aka `forEach`.
    74   // Handles objects with the built-in `forEach`, arrays, and raw objects.
    74   // Handles objects with the built-in `forEach`, arrays, and raw objects.
    75   // Delegates to **ECMAScript 5**'s native `forEach` if available.
    75   // Delegates to **ECMAScript 5**'s native `forEach` if available.
    76   var each = _.each = _.forEach = function(obj, iterator, context) {
    76   var each = _.each = _.forEach = function(obj, iterator, context) {
    77     if (obj == null) return;
    77     if (obj == null) return obj;
    78     if (nativeForEach && obj.forEach === nativeForEach) {
    78     if (nativeForEach && obj.forEach === nativeForEach) {
    79       obj.forEach(iterator, context);
    79       obj.forEach(iterator, context);
    80     } else if (obj.length === +obj.length) {
    80     } else if (obj.length === +obj.length) {
    81       for (var i = 0, length = obj.length; i < length; i++) {
    81       for (var i = 0, length = obj.length; i < length; i++) {
    82         if (iterator.call(context, obj[i], i, obj) === breaker) return;
    82         if (iterator.call(context, obj[i], i, obj) === breaker) return;
    85       var keys = _.keys(obj);
    85       var keys = _.keys(obj);
    86       for (var i = 0, length = keys.length; i < length; i++) {
    86       for (var i = 0, length = keys.length; i < length; i++) {
    87         if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
    87         if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
    88       }
    88       }
    89     }
    89     }
       
    90     return obj;
    90   };
    91   };
    91 
    92 
    92   // Return the results of applying the iterator to each element.
    93   // Return the results of applying the iterator to each element.
    93   // Delegates to **ECMAScript 5**'s native `map` if available.
    94   // Delegates to **ECMAScript 5**'s native `map` if available.
    94   _.map = _.collect = function(obj, iterator, context) {
    95   _.map = _.collect = function(obj, iterator, context) {
   150     if (!initial) throw new TypeError(reduceError);
   151     if (!initial) throw new TypeError(reduceError);
   151     return memo;
   152     return memo;
   152   };
   153   };
   153 
   154 
   154   // Return the first value which passes a truth test. Aliased as `detect`.
   155   // Return the first value which passes a truth test. Aliased as `detect`.
   155   _.find = _.detect = function(obj, iterator, context) {
   156   _.find = _.detect = function(obj, predicate, context) {
   156     var result;
   157     var result;
   157     any(obj, function(value, index, list) {
   158     any(obj, function(value, index, list) {
   158       if (iterator.call(context, value, index, list)) {
   159       if (predicate.call(context, value, index, list)) {
   159         result = value;
   160         result = value;
   160         return true;
   161         return true;
   161       }
   162       }
   162     });
   163     });
   163     return result;
   164     return result;
   164   };
   165   };
   165 
   166 
   166   // Return all the elements that pass a truth test.
   167   // Return all the elements that pass a truth test.
   167   // Delegates to **ECMAScript 5**'s native `filter` if available.
   168   // Delegates to **ECMAScript 5**'s native `filter` if available.
   168   // Aliased as `select`.
   169   // Aliased as `select`.
   169   _.filter = _.select = function(obj, iterator, context) {
   170   _.filter = _.select = function(obj, predicate, context) {
   170     var results = [];
   171     var results = [];
   171     if (obj == null) return results;
   172     if (obj == null) return results;
   172     if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
   173     if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
   173     each(obj, function(value, index, list) {
   174     each(obj, function(value, index, list) {
   174       if (iterator.call(context, value, index, list)) results.push(value);
   175       if (predicate.call(context, value, index, list)) results.push(value);
   175     });
   176     });
   176     return results;
   177     return results;
   177   };
   178   };
   178 
   179 
   179   // Return all the elements for which a truth test fails.
   180   // Return all the elements for which a truth test fails.
   180   _.reject = function(obj, iterator, context) {
   181   _.reject = function(obj, predicate, context) {
   181     return _.filter(obj, function(value, index, list) {
   182     return _.filter(obj, function(value, index, list) {
   182       return !iterator.call(context, value, index, list);
   183       return !predicate.call(context, value, index, list);
   183     }, context);
   184     }, context);
   184   };
   185   };
   185 
   186 
   186   // Determine whether all of the elements match a truth test.
   187   // Determine whether all of the elements match a truth test.
   187   // Delegates to **ECMAScript 5**'s native `every` if available.
   188   // Delegates to **ECMAScript 5**'s native `every` if available.
   188   // Aliased as `all`.
   189   // Aliased as `all`.
   189   _.every = _.all = function(obj, iterator, context) {
   190   _.every = _.all = function(obj, predicate, context) {
   190     iterator || (iterator = _.identity);
   191     predicate || (predicate = _.identity);
   191     var result = true;
   192     var result = true;
   192     if (obj == null) return result;
   193     if (obj == null) return result;
   193     if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
   194     if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
   194     each(obj, function(value, index, list) {
   195     each(obj, function(value, index, list) {
   195       if (!(result = result && iterator.call(context, value, index, list))) return breaker;
   196       if (!(result = result && predicate.call(context, value, index, list))) return breaker;
   196     });
   197     });
   197     return !!result;
   198     return !!result;
   198   };
   199   };
   199 
   200 
   200   // Determine if at least one element in the object matches a truth test.
   201   // Determine if at least one element in the object matches a truth test.
   201   // Delegates to **ECMAScript 5**'s native `some` if available.
   202   // Delegates to **ECMAScript 5**'s native `some` if available.
   202   // Aliased as `any`.
   203   // Aliased as `any`.
   203   var any = _.some = _.any = function(obj, iterator, context) {
   204   var any = _.some = _.any = function(obj, predicate, context) {
   204     iterator || (iterator = _.identity);
   205     predicate || (predicate = _.identity);
   205     var result = false;
   206     var result = false;
   206     if (obj == null) return result;
   207     if (obj == null) return result;
   207     if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
   208     if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
   208     each(obj, function(value, index, list) {
   209     each(obj, function(value, index, list) {
   209       if (result || (result = iterator.call(context, value, index, list))) return breaker;
   210       if (result || (result = predicate.call(context, value, index, list))) return breaker;
   210     });
   211     });
   211     return !!result;
   212     return !!result;
   212   };
   213   };
   213 
   214 
   214   // Determine if the array or object contains a given value (using `===`).
   215   // Determine if the array or object contains a given value (using `===`).
   230     });
   231     });
   231   };
   232   };
   232 
   233 
   233   // Convenience version of a common use case of `map`: fetching a property.
   234   // Convenience version of a common use case of `map`: fetching a property.
   234   _.pluck = function(obj, key) {
   235   _.pluck = function(obj, key) {
   235     return _.map(obj, function(value){ return value[key]; });
   236     return _.map(obj, _.property(key));
   236   };
   237   };
   237 
   238 
   238   // Convenience version of a common use case of `filter`: selecting only objects
   239   // Convenience version of a common use case of `filter`: selecting only objects
   239   // containing specific `key:value` pairs.
   240   // containing specific `key:value` pairs.
   240   _.where = function(obj, attrs, first) {
   241   _.where = function(obj, attrs) {
   241     if (_.isEmpty(attrs)) return first ? void 0 : [];
   242     return _.filter(obj, _.matches(attrs));
   242     return _[first ? 'find' : 'filter'](obj, function(value) {
       
   243       for (var key in attrs) {
       
   244         if (attrs[key] !== value[key]) return false;
       
   245       }
       
   246       return true;
       
   247     });
       
   248   };
   243   };
   249 
   244 
   250   // Convenience version of a common use case of `find`: getting the first object
   245   // Convenience version of a common use case of `find`: getting the first object
   251   // containing specific `key:value` pairs.
   246   // containing specific `key:value` pairs.
   252   _.findWhere = function(obj, attrs) {
   247   _.findWhere = function(obj, attrs) {
   253     return _.where(obj, attrs, true);
   248     return _.find(obj, _.matches(attrs));
   254   };
   249   };
   255 
   250 
   256   // Return the maximum element or (element-based computation).
   251   // Return the maximum element or (element-based computation).
   257   // Can't optimize arrays of integers longer than 65,535 elements.
   252   // Can't optimize arrays of integers longer than 65,535 elements.
   258   // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
   253   // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
   259   _.max = function(obj, iterator, context) {
   254   _.max = function(obj, iterator, context) {
   260     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
   255     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
   261       return Math.max.apply(Math, obj);
   256       return Math.max.apply(Math, obj);
   262     }
   257     }
   263     if (!iterator && _.isEmpty(obj)) return -Infinity;
   258     var result = -Infinity, lastComputed = -Infinity;
   264     var result = {computed : -Infinity, value: -Infinity};
       
   265     each(obj, function(value, index, list) {
   259     each(obj, function(value, index, list) {
   266       var computed = iterator ? iterator.call(context, value, index, list) : value;
   260       var computed = iterator ? iterator.call(context, value, index, list) : value;
   267       computed > result.computed && (result = {value : value, computed : computed});
   261       if (computed > lastComputed) {
   268     });
   262         result = value;
   269     return result.value;
   263         lastComputed = computed;
       
   264       }
       
   265     });
       
   266     return result;
   270   };
   267   };
   271 
   268 
   272   // Return the minimum element (or element-based computation).
   269   // Return the minimum element (or element-based computation).
   273   _.min = function(obj, iterator, context) {
   270   _.min = function(obj, iterator, context) {
   274     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
   271     if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
   275       return Math.min.apply(Math, obj);
   272       return Math.min.apply(Math, obj);
   276     }
   273     }
   277     if (!iterator && _.isEmpty(obj)) return Infinity;
   274     var result = Infinity, lastComputed = Infinity;
   278     var result = {computed : Infinity, value: Infinity};
       
   279     each(obj, function(value, index, list) {
   275     each(obj, function(value, index, list) {
   280       var computed = iterator ? iterator.call(context, value, index, list) : value;
   276       var computed = iterator ? iterator.call(context, value, index, list) : value;
   281       computed < result.computed && (result = {value : value, computed : computed});
   277       if (computed < lastComputed) {
   282     });
   278         result = value;
   283     return result.value;
   279         lastComputed = computed;
   284   };
   280       }
   285 
   281     });
   286   // Shuffle an array, using the modern version of the 
   282     return result;
       
   283   };
       
   284 
       
   285   // Shuffle an array, using the modern version of the
   287   // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
   286   // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
   288   _.shuffle = function(obj) {
   287   _.shuffle = function(obj) {
   289     var rand;
   288     var rand;
   290     var index = 0;
   289     var index = 0;
   291     var shuffled = [];
   290     var shuffled = [];
   295       shuffled[rand] = value;
   294       shuffled[rand] = value;
   296     });
   295     });
   297     return shuffled;
   296     return shuffled;
   298   };
   297   };
   299 
   298 
   300   // Sample **n** random values from an array.
   299   // Sample **n** random values from a collection.
   301   // If **n** is not specified, returns a single random element from the array.
   300   // If **n** is not specified, returns a single random element.
   302   // The internal `guard` argument allows it to work with `map`.
   301   // The internal `guard` argument allows it to work with `map`.
   303   _.sample = function(obj, n, guard) {
   302   _.sample = function(obj, n, guard) {
   304     if (arguments.length < 2 || guard) {
   303     if (n == null || guard) {
       
   304       if (obj.length !== +obj.length) obj = _.values(obj);
   305       return obj[_.random(obj.length - 1)];
   305       return obj[_.random(obj.length - 1)];
   306     }
   306     }
   307     return _.shuffle(obj).slice(0, Math.max(0, n));
   307     return _.shuffle(obj).slice(0, Math.max(0, n));
   308   };
   308   };
   309 
   309 
   310   // An internal function to generate lookup iterators.
   310   // An internal function to generate lookup iterators.
   311   var lookupIterator = function(value) {
   311   var lookupIterator = function(value) {
   312     return _.isFunction(value) ? value : function(obj){ return obj[value]; };
   312     if (value == null) return _.identity;
       
   313     if (_.isFunction(value)) return value;
       
   314     return _.property(value);
   313   };
   315   };
   314 
   316 
   315   // Sort the object's values by a criterion produced by an iterator.
   317   // Sort the object's values by a criterion produced by an iterator.
   316   _.sortBy = function(obj, value, context) {
   318   _.sortBy = function(obj, iterator, context) {
   317     var iterator = lookupIterator(value);
   319     iterator = lookupIterator(iterator);
   318     return _.pluck(_.map(obj, function(value, index, list) {
   320     return _.pluck(_.map(obj, function(value, index, list) {
   319       return {
   321       return {
   320         value: value,
   322         value: value,
   321         index: index,
   323         index: index,
   322         criteria: iterator.call(context, value, index, list)
   324         criteria: iterator.call(context, value, index, list)
   332     }), 'value');
   334     }), 'value');
   333   };
   335   };
   334 
   336 
   335   // An internal function used for aggregate "group by" operations.
   337   // An internal function used for aggregate "group by" operations.
   336   var group = function(behavior) {
   338   var group = function(behavior) {
   337     return function(obj, value, context) {
   339     return function(obj, iterator, context) {
   338       var result = {};
   340       var result = {};
   339       var iterator = value == null ? _.identity : lookupIterator(value);
   341       iterator = lookupIterator(iterator);
   340       each(obj, function(value, index) {
   342       each(obj, function(value, index) {
   341         var key = iterator.call(context, value, index, obj);
   343         var key = iterator.call(context, value, index, obj);
   342         behavior(result, key, value);
   344         behavior(result, key, value);
   343       });
   345       });
   344       return result;
   346       return result;
   346   };
   348   };
   347 
   349 
   348   // Groups the object's values by a criterion. Pass either a string attribute
   350   // Groups the object's values by a criterion. Pass either a string attribute
   349   // to group by, or a function that returns the criterion.
   351   // to group by, or a function that returns the criterion.
   350   _.groupBy = group(function(result, key, value) {
   352   _.groupBy = group(function(result, key, value) {
   351     (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
   353     _.has(result, key) ? result[key].push(value) : result[key] = [value];
   352   });
   354   });
   353 
   355 
   354   // Indexes the object's values by a criterion, similar to `groupBy`, but for
   356   // Indexes the object's values by a criterion, similar to `groupBy`, but for
   355   // when you know that your index values will be unique.
   357   // when you know that your index values will be unique.
   356   _.indexBy = group(function(result, key, value) {
   358   _.indexBy = group(function(result, key, value) {
   365   });
   367   });
   366 
   368 
   367   // Use a comparator function to figure out the smallest index at which
   369   // Use a comparator function to figure out the smallest index at which
   368   // an object should be inserted so as to maintain order. Uses binary search.
   370   // an object should be inserted so as to maintain order. Uses binary search.
   369   _.sortedIndex = function(array, obj, iterator, context) {
   371   _.sortedIndex = function(array, obj, iterator, context) {
   370     iterator = iterator == null ? _.identity : lookupIterator(iterator);
   372     iterator = lookupIterator(iterator);
   371     var value = iterator.call(context, obj);
   373     var value = iterator.call(context, obj);
   372     var low = 0, high = array.length;
   374     var low = 0, high = array.length;
   373     while (low < high) {
   375     while (low < high) {
   374       var mid = (low + high) >>> 1;
   376       var mid = (low + high) >>> 1;
   375       iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
   377       iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
   397   // Get the first element of an array. Passing **n** will return the first N
   399   // Get the first element of an array. Passing **n** will return the first N
   398   // values in the array. Aliased as `head` and `take`. The **guard** check
   400   // values in the array. Aliased as `head` and `take`. The **guard** check
   399   // allows it to work with `_.map`.
   401   // allows it to work with `_.map`.
   400   _.first = _.head = _.take = function(array, n, guard) {
   402   _.first = _.head = _.take = function(array, n, guard) {
   401     if (array == null) return void 0;
   403     if (array == null) return void 0;
   402     return (n == null) || guard ? array[0] : slice.call(array, 0, n);
   404     if ((n == null) || guard) return array[0];
       
   405     if (n < 0) return [];
       
   406     return slice.call(array, 0, n);
   403   };
   407   };
   404 
   408 
   405   // Returns everything but the last entry of the array. Especially useful on
   409   // Returns everything but the last entry of the array. Especially useful on
   406   // the arguments object. Passing **n** will return all the values in
   410   // the arguments object. Passing **n** will return all the values in
   407   // the array, excluding the last N. The **guard** check allows it to work with
   411   // the array, excluding the last N. The **guard** check allows it to work with
   412 
   416 
   413   // Get the last element of an array. Passing **n** will return the last N
   417   // Get the last element of an array. Passing **n** will return the last N
   414   // values in the array. The **guard** check allows it to work with `_.map`.
   418   // values in the array. The **guard** check allows it to work with `_.map`.
   415   _.last = function(array, n, guard) {
   419   _.last = function(array, n, guard) {
   416     if (array == null) return void 0;
   420     if (array == null) return void 0;
   417     if ((n == null) || guard) {
   421     if ((n == null) || guard) return array[array.length - 1];
   418       return array[array.length - 1];
   422     return slice.call(array, Math.max(array.length - n, 0));
   419     } else {
       
   420       return slice.call(array, Math.max(array.length - n, 0));
       
   421     }
       
   422   };
   423   };
   423 
   424 
   424   // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
   425   // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
   425   // Especially useful on the arguments object. Passing an **n** will return
   426   // Especially useful on the arguments object. Passing an **n** will return
   426   // the rest N values in the array. The **guard**
   427   // the rest N values in the array. The **guard**
   455   };
   456   };
   456 
   457 
   457   // Return a version of the array that does not contain the specified value(s).
   458   // Return a version of the array that does not contain the specified value(s).
   458   _.without = function(array) {
   459   _.without = function(array) {
   459     return _.difference(array, slice.call(arguments, 1));
   460     return _.difference(array, slice.call(arguments, 1));
       
   461   };
       
   462 
       
   463   // Split an array into two arrays: one whose elements all satisfy the given
       
   464   // predicate, and one whose elements all do not satisfy the predicate.
       
   465   _.partition = function(array, predicate, context) {
       
   466     predicate = lookupIterator(predicate);
       
   467     var pass = [], fail = [];
       
   468     each(array, function(elem) {
       
   469       (predicate.call(context, elem) ? pass : fail).push(elem);
       
   470     });
       
   471     return [pass, fail];
   460   };
   472   };
   461 
   473 
   462   // Produce a duplicate-free version of the array. If the array has already
   474   // Produce a duplicate-free version of the array. If the array has already
   463   // been sorted, you have the option of using a faster algorithm.
   475   // been sorted, you have the option of using a faster algorithm.
   464   // Aliased as `unique`.
   476   // Aliased as `unique`.
   490   // passed-in arrays.
   502   // passed-in arrays.
   491   _.intersection = function(array) {
   503   _.intersection = function(array) {
   492     var rest = slice.call(arguments, 1);
   504     var rest = slice.call(arguments, 1);
   493     return _.filter(_.uniq(array), function(item) {
   505     return _.filter(_.uniq(array), function(item) {
   494       return _.every(rest, function(other) {
   506       return _.every(rest, function(other) {
   495         return _.indexOf(other, item) >= 0;
   507         return _.contains(other, item);
   496       });
   508       });
   497     });
   509     });
   498   };
   510   };
   499 
   511 
   500   // Take the difference between one array and a number of other arrays.
   512   // Take the difference between one array and a number of other arrays.
   505   };
   517   };
   506 
   518 
   507   // Zip together multiple lists into a single array -- elements that share
   519   // Zip together multiple lists into a single array -- elements that share
   508   // an index go together.
   520   // an index go together.
   509   _.zip = function() {
   521   _.zip = function() {
   510     var length = _.max(_.pluck(arguments, "length").concat(0));
   522     var length = _.max(_.pluck(arguments, 'length').concat(0));
   511     var results = new Array(length);
   523     var results = new Array(length);
   512     for (var i = 0; i < length; i++) {
   524     for (var i = 0; i < length; i++) {
   513       results[i] = _.pluck(arguments, '' + i);
   525       results[i] = _.pluck(arguments, '' + i);
   514     }
   526     }
   515     return results;
   527     return results;
   611       return self;
   623       return self;
   612     };
   624     };
   613   };
   625   };
   614 
   626 
   615   // Partially apply a function by creating a version that has had some of its
   627   // Partially apply a function by creating a version that has had some of its
   616   // arguments pre-filled, without changing its dynamic `this` context.
   628   // arguments pre-filled, without changing its dynamic `this` context. _ acts
       
   629   // as a placeholder, allowing any combination of arguments to be pre-filled.
   617   _.partial = function(func) {
   630   _.partial = function(func) {
   618     var args = slice.call(arguments, 1);
   631     var boundArgs = slice.call(arguments, 1);
   619     return function() {
   632     return function() {
   620       return func.apply(this, args.concat(slice.call(arguments)));
   633       var position = 0;
   621     };
   634       var args = boundArgs.slice();
   622   };
   635       for (var i = 0, length = args.length; i < length; i++) {
   623 
   636         if (args[i] === _) args[i] = arguments[position++];
   624   // Bind all of an object's methods to that object. Useful for ensuring that
   637       }
   625   // all callbacks defined on an object belong to it.
   638       while (position < arguments.length) args.push(arguments[position++]);
       
   639       return func.apply(this, args);
       
   640     };
       
   641   };
       
   642 
       
   643   // Bind a number of an object's methods to that object. Remaining arguments
       
   644   // are the method names to be bound. Useful for ensuring that all callbacks
       
   645   // defined on an object belong to it.
   626   _.bindAll = function(obj) {
   646   _.bindAll = function(obj) {
   627     var funcs = slice.call(arguments, 1);
   647     var funcs = slice.call(arguments, 1);
   628     if (funcs.length === 0) throw new Error("bindAll must be passed function names");
   648     if (funcs.length === 0) throw new Error('bindAll must be passed function names');
   629     each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
   649     each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
   630     return obj;
   650     return obj;
   631   };
   651   };
   632 
   652 
   633   // Memoize an expensive function by storing its results.
   653   // Memoize an expensive function by storing its results.
   662     var context, args, result;
   682     var context, args, result;
   663     var timeout = null;
   683     var timeout = null;
   664     var previous = 0;
   684     var previous = 0;
   665     options || (options = {});
   685     options || (options = {});
   666     var later = function() {
   686     var later = function() {
   667       previous = options.leading === false ? 0 : new Date;
   687       previous = options.leading === false ? 0 : _.now();
   668       timeout = null;
   688       timeout = null;
   669       result = func.apply(context, args);
   689       result = func.apply(context, args);
       
   690       context = args = null;
   670     };
   691     };
   671     return function() {
   692     return function() {
   672       var now = new Date;
   693       var now = _.now();
   673       if (!previous && options.leading === false) previous = now;
   694       if (!previous && options.leading === false) previous = now;
   674       var remaining = wait - (now - previous);
   695       var remaining = wait - (now - previous);
   675       context = this;
   696       context = this;
   676       args = arguments;
   697       args = arguments;
   677       if (remaining <= 0) {
   698       if (remaining <= 0) {
   678         clearTimeout(timeout);
   699         clearTimeout(timeout);
   679         timeout = null;
   700         timeout = null;
   680         previous = now;
   701         previous = now;
   681         result = func.apply(context, args);
   702         result = func.apply(context, args);
       
   703         context = args = null;
   682       } else if (!timeout && options.trailing !== false) {
   704       } else if (!timeout && options.trailing !== false) {
   683         timeout = setTimeout(later, remaining);
   705         timeout = setTimeout(later, remaining);
   684       }
   706       }
   685       return result;
   707       return result;
   686     };
   708     };
   690   // be triggered. The function will be called after it stops being called for
   712   // be triggered. The function will be called after it stops being called for
   691   // N milliseconds. If `immediate` is passed, trigger the function on the
   713   // N milliseconds. If `immediate` is passed, trigger the function on the
   692   // leading edge, instead of the trailing.
   714   // leading edge, instead of the trailing.
   693   _.debounce = function(func, wait, immediate) {
   715   _.debounce = function(func, wait, immediate) {
   694     var timeout, args, context, timestamp, result;
   716     var timeout, args, context, timestamp, result;
       
   717 
       
   718     var later = function() {
       
   719       var last = _.now() - timestamp;
       
   720       if (last < wait) {
       
   721         timeout = setTimeout(later, wait - last);
       
   722       } else {
       
   723         timeout = null;
       
   724         if (!immediate) {
       
   725           result = func.apply(context, args);
       
   726           context = args = null;
       
   727         }
       
   728       }
       
   729     };
       
   730 
   695     return function() {
   731     return function() {
   696       context = this;
   732       context = this;
   697       args = arguments;
   733       args = arguments;
   698       timestamp = new Date();
   734       timestamp = _.now();
   699       var later = function() {
       
   700         var last = (new Date()) - timestamp;
       
   701         if (last < wait) {
       
   702           timeout = setTimeout(later, wait - last);
       
   703         } else {
       
   704           timeout = null;
       
   705           if (!immediate) result = func.apply(context, args);
       
   706         }
       
   707       };
       
   708       var callNow = immediate && !timeout;
   735       var callNow = immediate && !timeout;
   709       if (!timeout) {
   736       if (!timeout) {
   710         timeout = setTimeout(later, wait);
   737         timeout = setTimeout(later, wait);
   711       }
   738       }
   712       if (callNow) result = func.apply(context, args);
   739       if (callNow) {
       
   740         result = func.apply(context, args);
       
   741         context = args = null;
       
   742       }
       
   743 
   713       return result;
   744       return result;
   714     };
   745     };
   715   };
   746   };
   716 
   747 
   717   // Returns a function that will be executed at most one time, no matter how
   748   // Returns a function that will be executed at most one time, no matter how
   729 
   760 
   730   // Returns the first function passed as an argument to the second,
   761   // Returns the first function passed as an argument to the second,
   731   // allowing you to adjust arguments, run code before and after, and
   762   // allowing you to adjust arguments, run code before and after, and
   732   // conditionally execute the original function.
   763   // conditionally execute the original function.
   733   _.wrap = function(func, wrapper) {
   764   _.wrap = function(func, wrapper) {
   734     return function() {
   765     return _.partial(wrapper, func);
   735       var args = [func];
       
   736       push.apply(args, arguments);
       
   737       return wrapper.apply(this, args);
       
   738     };
       
   739   };
   766   };
   740 
   767 
   741   // Returns a function that is the composition of a list of functions, each
   768   // Returns a function that is the composition of a list of functions, each
   742   // consuming the return value of the function that follows.
   769   // consuming the return value of the function that follows.
   743   _.compose = function() {
   770   _.compose = function() {
   763   // Object Functions
   790   // Object Functions
   764   // ----------------
   791   // ----------------
   765 
   792 
   766   // Retrieve the names of an object's properties.
   793   // Retrieve the names of an object's properties.
   767   // Delegates to **ECMAScript 5**'s native `Object.keys`
   794   // Delegates to **ECMAScript 5**'s native `Object.keys`
   768   _.keys = nativeKeys || function(obj) {
   795   _.keys = function(obj) {
   769     if (obj !== Object(obj)) throw new TypeError('Invalid object');
   796     if (!_.isObject(obj)) return [];
       
   797     if (nativeKeys) return nativeKeys(obj);
   770     var keys = [];
   798     var keys = [];
   771     for (var key in obj) if (_.has(obj, key)) keys.push(key);
   799     for (var key in obj) if (_.has(obj, key)) keys.push(key);
   772     return keys;
   800     return keys;
   773   };
   801   };
   774 
   802 
   919     }
   947     }
   920     // Objects with different constructors are not equivalent, but `Object`s
   948     // Objects with different constructors are not equivalent, but `Object`s
   921     // from different frames are.
   949     // from different frames are.
   922     var aCtor = a.constructor, bCtor = b.constructor;
   950     var aCtor = a.constructor, bCtor = b.constructor;
   923     if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
   951     if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
   924                              _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
   952                              _.isFunction(bCtor) && (bCtor instanceof bCtor))
       
   953                         && ('constructor' in a && 'constructor' in b)) {
   925       return false;
   954       return false;
   926     }
   955     }
   927     // Add the first object to the stack of traversed objects.
   956     // Add the first object to the stack of traversed objects.
   928     aStack.push(a);
   957     aStack.push(a);
   929     bStack.push(b);
   958     bStack.push(b);
  1059   // Keep the identity function around for default iterators.
  1088   // Keep the identity function around for default iterators.
  1060   _.identity = function(value) {
  1089   _.identity = function(value) {
  1061     return value;
  1090     return value;
  1062   };
  1091   };
  1063 
  1092 
       
  1093   _.constant = function(value) {
       
  1094     return function () {
       
  1095       return value;
       
  1096     };
       
  1097   };
       
  1098 
       
  1099   _.property = function(key) {
       
  1100     return function(obj) {
       
  1101       return obj[key];
       
  1102     };
       
  1103   };
       
  1104 
       
  1105   // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
       
  1106   _.matches = function(attrs) {
       
  1107     return function(obj) {
       
  1108       if (obj === attrs) return true; //avoid comparing an object to itself.
       
  1109       for (var key in attrs) {
       
  1110         if (attrs[key] !== obj[key])
       
  1111           return false;
       
  1112       }
       
  1113       return true;
       
  1114     }
       
  1115   };
       
  1116 
  1064   // Run a function **n** times.
  1117   // Run a function **n** times.
  1065   _.times = function(n, iterator, context) {
  1118   _.times = function(n, iterator, context) {
  1066     var accum = Array(Math.max(0, n));
  1119     var accum = Array(Math.max(0, n));
  1067     for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
  1120     for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
  1068     return accum;
  1121     return accum;
  1074       max = min;
  1127       max = min;
  1075       min = 0;
  1128       min = 0;
  1076     }
  1129     }
  1077     return min + Math.floor(Math.random() * (max - min + 1));
  1130     return min + Math.floor(Math.random() * (max - min + 1));
  1078   };
  1131   };
       
  1132 
       
  1133   // A (possibly faster) way to get the current timestamp as an integer.
       
  1134   _.now = Date.now || function() { return new Date().getTime(); };
  1079 
  1135 
  1080   // List of HTML entities for escaping.
  1136   // List of HTML entities for escaping.
  1081   var entityMap = {
  1137   var entityMap = {
  1082     escape: {
  1138     escape: {
  1083       '&': '&amp;',
  1139       '&': '&amp;',
  1271       return this._wrapped;
  1327       return this._wrapped;
  1272     }
  1328     }
  1273 
  1329 
  1274   });
  1330   });
  1275 
  1331 
       
  1332   // AMD registration happens at the end for compatibility with AMD loaders
       
  1333   // that may not enforce next-turn semantics on modules. Even though general
       
  1334   // practice for AMD registration is to be anonymous, underscore registers
       
  1335   // as a named module because, like jQuery, it is a base library that is
       
  1336   // popular enough to be bundled in a third party lib, but not be part of
       
  1337   // an AMD load request. Those cases could generate an error when an
       
  1338   // anonymous define() is called outside of a loader request.
       
  1339   if (typeof define === 'function' && define.amd) {
       
  1340     define('underscore', [], function() {
       
  1341       return _;
       
  1342     });
       
  1343   }
  1276 }).call(this);
  1344 }).call(this);