diff --git a/README.md b/README.md
index a6564a2a2..2b49cb4a0 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,88 @@
- __
- /\ \ __
- __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____
- /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\
- \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\
- \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/
- \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/
- \ \____/
- \/___/
-
-Underscore.js is a utility-belt library for JavaScript that provides
-support for the usual functional suspects (each, map, reduce, filter...)
-without extending any core JavaScript objects.
+# Lo-Dash v0.1.0
-For Docs, License, Tests, and pre-packed downloads, see:
-http://documentcloud.github.com/underscore/
+TBD
-Many thanks to our contributors:
-https://github.com/documentcloud/underscore/contributors
+## BestieJS
+
+Lo-Dash is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation.
+
+## Documentation
+
+The documentation for Lo-Dash can be viewed here: [lodash/doc](https://github.com/bestiejs/lodash/doc/README.md)
+
+For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
+
+## Installation and usage
+
+In a browser:
+
+~~~ html
+
+~~~
+
+Via [npm](http://npmjs.org/):
+
+~~~ bash
+npm install lodash
+~~~
+
+In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
+
+~~~ js
+var _ = require('lodash');
+~~~
+
+In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
+
+~~~ js
+var _ = require('lodash')._;
+~~~
+
+In [Rhino](http://www.mozilla.org/rhino/):
+
+~~~ js
+load('lodash.js');
+~~~
+
+In an AMD loader like [RequireJS](http://requirejs.org/):
+
+~~~ js
+require({
+ 'paths': {
+ 'lodash': 'path/to/lodash'
+ }
+},
+['lodash'], function(_) {
+ console.log(_.VERSION);
+});
+~~~
+
+Usage example:
+
+~~~ js
+// TBD
+~~~
+
+## Cloning this repo
+
+To clone this repository including all submodules, using Git 1.6.5 or later:
+
+~~~ bash
+git clone --recursive https://github.com/bestiejs/lodash.git
+cd lodash.js
+~~~
+
+For older Git versions, just use:
+
+~~~ bash
+git clone https://github.com/bestiejs/lodash.git
+cd lodash
+git submodule update --init
+~~~
+
+Feel free to fork if you see possible improvements!
+
+## Author
+
+* [John-David Dalton](http://allyoucanleet.com/)
+ [](https://twitter.com/jdalton "Follow @jdalton on Twitter")
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 000000000..6c1581137
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,2131 @@
+# Lo-Dash v0.1.0
+
+
+
+
+
+
+## `_`
+* [`_`](#_)
+* [`_.VERSION`](#_.VERSION)
+* [`_.after`](#_.after)
+* [`_.bind`](#_.bind)
+* [`_.bindAll`](#_.bindAll)
+* [`_.chain`](#_.chain)
+* [`_.clone`](#_.clone)
+* [`_.compact`](#_.compact)
+* [`_.compose`](#_.compose)
+* [`_.contains`](#_.contains)
+* [`_.debounce`](#_.debounce)
+* [`_.defaults`](#_.defaults)
+* [`_.defer`](#_.defer)
+* [`_.delay`](#_.delay)
+* [`_.difference`](#_.difference)
+* [`_.escape`](#_.escape)
+* [`_.every`](#_.every)
+* [`_.extend`](#_.extend)
+* [`_.filter`](#_.filter)
+* [`_.find`](#_.find)
+* [`_.first`](#_.first)
+* [`_.flatten`](#_.flatten)
+* [`_.forEach`](#_.forEach)
+* [`_.functions`](#_.functions)
+* [`_.groupBy`](#_.groupBy)
+* [`_.has`](#_.has)
+* [`_.identity`](#_.identity)
+* [`_.indexOf`](#_.indexOf)
+* [`_.initial`](#_.initial)
+* [`_.intersection`](#_.intersection)
+* [`_.invoke`](#_.invoke)
+* [`_.isArguments`](#_.isArguments)
+* [`_.isArray`](#_.isArray)
+* [`_.isBoolean`](#_.isBoolean)
+* [`_.isDate`](#_.isDate)
+* [`_.isElement`](#_.isElement)
+* [`_.isEmpty`](#_.isEmpty)
+* [`_.isEqual`](#_.isEqual)
+* [`_.isFinite`](#_.isFinite)
+* [`_.isFunction`](#_.isFunction)
+* [`_.isNaN`](#_.isNaN)
+* [`_.isNull`](#_.isNull)
+* [`_.isNumber`](#_.isNumber)
+* [`_.isObject`](#_.isObject)
+* [`_.isRegExp`](#_.isRegExp)
+* [`_.isString`](#_.isString)
+* [`_.isUndefined`](#_.isUndefined)
+* [`_.keys`](#_.keys)
+* [`_.last`](#_.last)
+* [`_.lastIndexOf`](#_.lastIndexOf)
+* [`_.map`](#_.map)
+* [`_.max`](#_.max)
+* [`_.memoize`](#_.memoize)
+* [`_.min`](#_.min)
+* [`_.mixin`](#_.mixin)
+* [`_.noConflict`](#_.noConflict)
+* [`_.once`](#_.once)
+* [`_.pick`](#_.pick)
+* [`_.pluck`](#_.pluck)
+* [`_.range`](#_.range)
+* [`_.reduce`](#_.reduce)
+* [`_.reduceRight`](#_.reduceRight)
+* [`_.reject`](#_.reject)
+* [`_.rest`](#_.rest)
+* [`_.result`](#_.result)
+* [`_.shuffle`](#_.shuffle)
+* [`_.size`](#_.size)
+* [`_.some`](#_.some)
+* [`_.sortBy`](#_.sortBy)
+* [`_.sortedIndex`](#_.sortedIndex)
+* [`_.tap`](#_.tap)
+* [`_.template`](#_.template)
+* [`_.throttle`](#_.throttle)
+* [`_.times`](#_.times)
+* [`_.toArray`](#_.toArray)
+* [`_.union`](#_.union)
+* [`_.uniq`](#_.uniq)
+* [`_.uniqueId`](#_.uniqueId)
+* [`_.values`](#_.values)
+* [`_.without`](#_.without)
+* [`_.wrap`](#_.wrap)
+* [`_.zip`](#_.zip)
+
+
+
+
+
+
+## `_.prototype`
+* [`_#chain`](#_:chain)
+* [`_#value`](#_:value)
+
+
+
+
+
+
+## `_.templateSettings`
+* [`_.templateSettings`](#_.templateSettings)
+
+
+
+
+
+
+
+
+
+
+
+
+## `_`
+
+
+
+### `_(value)`
+The Lodash function.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to wrap in a chainable `lowdash` object.
+
+#### Returns
+*(Object)*: Returns a `lodash` instance.
+
+#### Example
+~~~ js
+
+~~~
+
+
+
+
+
+
+## `_`
+### `_(value)`
+The Lodash function.
+[▲][1]
+
+
+
+### `_.VERSION`
+*(String)*: The semantic version number.
+[▲][1]
+
+
+
+
+
+
+### `_.after(times, func)`
+Creates a new function that is restricted to executing only after it is called a given number of `times`.
+[▲][1]
+
+#### Arguments
+1. `times` *(Number)*: The number of times the function must be called before it is executed.
+2. `func` *(Function)*: The function to restrict.
+
+#### Returns
+*(Function)*: Returns the new restricted function.
+
+#### Example
+~~~ js
+var renderNotes = _.after(notes.length, render);
+_.forEach(notes, function(note) {
+ note.asyncSave({ 'success': renderNotes });
+});
+// renderNotes is run once, after all notes have saved.
+~~~
+
+
+
+
+
+
+### `_.bind(func [, arg1, arg2, ...])`
+Creates a new function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends additional arguments to those passed to the bound function.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to bind.
+2. `[arg1, arg2, ...]` *(Mixed)*: Arguments to prepend to those passed to the bound function.
+
+#### Returns
+*(Function)*: Returns the new bound function.
+
+#### Example
+~~~ js
+var func = function(greeting){ return greeting + ': ' + this.name; };
+func = _.bind(func, { 'name': 'moe' }, 'hi');
+func();
+// => 'hi: moe'
+~~~
+
+
+
+
+
+
+### `_.bindAll(object [, methodName1, methodName2, ...])`
+Binds methods on the `object` to the object, overwriting the non-bound method. If no method names are provided, all the function properties of the `object` will be bound.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to bind and assign the bound methods to.
+2. `[methodName1, methodName2, ...]` *(Mixed)*: Method names on the object to bind.
+
+#### Returns
+*(Object)*: Returns the `object`.
+
+#### Example
+~~~ js
+var buttonView = {
+ 'label': 'lodash',
+ 'onClick': function() { alert('clicked: ' + this.label); },
+ 'onHover': function() { console.log('hovering: ' + this.label); }
+};
+
+_.bindAll(buttonView);
+jQuery('#lodash_button').on('click', buttonView.onClick);
+// => When the button is clicked, `this.label` will have the correct value
+~~~
+
+
+
+
+
+
+### `_.chain(value)`
+Wraps the value in a `lodash` chainable object.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to wrap.
+
+#### Returns
+*(Object)*: Returns the `lodash` chainable object.
+
+#### Example
+~~~ js
+var stooges = [
+ { 'name' : 'moe', 'age' : 40},
+ { 'name' : 'larry', 'age' : 50},
+ { 'name' : 'curly', 'age' : 60}
+];
+
+var youngest = _.chain(stooges)
+ .sortBy(function(stooge){ return stooge.age; })
+ .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
+ .first()
+ .value();
+// => 'moe is 40'
+~~~
+
+
+
+
+
+
+### `_.clone(value)`
+Create a shallow clone of the `value`. Any nested objects or arrays will be assigned by reference and not cloned.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to clone.
+
+#### Returns
+*(Mixed)*: Returns the cloned `value`.
+
+#### Example
+~~~ js
+_.clone({ 'name': 'moe' });
+// => { 'name': 'moe' };
+~~~
+
+
+
+
+
+
+### `_.compact(array)`
+Produces a new array with all falsey values of `array` removed. The values `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to compact.
+
+#### Returns
+*(Array)*: Returns a new filtered array.
+
+#### Example
+~~~ js
+_.compact([0, 1, false, 2, '', 3]);
+// => [1, 2, 3]
+~~~
+
+
+
+
+
+
+### `_.compose([func1, func2, ...])`
+Creates a new function that is the composition of the passed functions, where each function consumes the return value of the function that follows. In math terms, composing thefunctions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+[▲][1]
+
+#### Arguments
+1. `[func1, func2, ...]` *(Mixed)*: Functions to compose.
+
+#### Returns
+*(Function)*: Returns the new composed function.
+
+#### Example
+~~~ js
+var greet = function(name) { return 'hi: ' + name; };
+var exclaim = function(statement) { return statement + '!'; };
+var welcome = _.compose(exclaim, greet);
+welcome('moe');
+// => 'hi: moe!'
+~~~
+
+
+
+
+
+
+### `_.contains(collection, target)`
+Checks if a given `target` value is present in a `collection` using strict equality for comparisons, i.e. `===`.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `target` *(Mixed)*: The value to check for.
+
+#### Returns
+*(Boolean)*: Returns `true` if `target` value is found, else `false`.
+
+#### Example
+~~~ js
+_.contains([1, 2, 3], 3);
+// => true
+~~~
+
+
+
+
+
+
+### `_.debounce(func, wait, immediate)`
+Creates a new function that will postpone its execution until after `wait` milliseconds have elapsed since the last time it was invoked. Pass `true` for `immediate` to cause debounce to invoke the function on the leading, intead of the trailing, edge of the wait timeout.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to debounce.
+2. `wait` *(Number)*: The number of milliseconds to postone.
+3. `immediate` *(Boolean)*: A flag to indicate execution is on the leading edge of the wait timeout.
+
+#### Returns
+*(Function)*: Returns the new debounced function.
+
+#### Example
+~~~ js
+var lazyLayout = _.debounce(calculateLayout, 300);
+jQuery(window).on('resize', lazyLayout);
+~~~
+
+
+
+
+
+
+### `_.defaults(object [, defaults1, defaults2, ..])`
+Assigns missing properties in `object` with default values from the defaults objects. As soon as a property is set, additional defaults of the same property will be ignored.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to populate.
+2. `[defaults1, defaults2, ..]` *(Object)*: The defaults objects to apply to `object`.
+
+#### Returns
+*(Object)*: Returns `object`.
+
+#### Example
+~~~ js
+var iceCream = { 'flavor': 'chocolate' };
+_.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'lots' });
+// => { 'flavor': 'chocolate', 'sprinkles': 'lots' }
+~~~
+
+
+
+
+
+
+### `_.defer(func [, arg1, arg2, ...])`
+Defers invoking the `func` function until the current call stack has cleared. Additional arguments are passed to `func` when it is invoked.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to defer.
+2. `[arg1, arg2, ...]` *(Mixed)*: Arguments to invoke the function with.
+
+#### Returns
+*(Number)*: Returns the `setTimeout` timeout id.
+
+#### Example
+~~~ js
+_.defer(function(){ alert('deferred'); });
+// Returns from the function before the alert runs.
+~~~
+
+
+
+
+
+
+### `_.delay(func, wait [, arg1, arg2, ...])`
+Invokes the `func` function after `wait` milliseconds. Additional arguments are passed `func` when it is invoked.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to delay.
+2. `wait` *(Number)*: The number of milliseconds to delay execution.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to invoke the function with.
+
+#### Returns
+*(Number)*: Returns the `setTimeout` timeout id.
+
+#### Example
+~~~ js
+var log = _.bind(console.log, console);
+_.delay(log, 1000, 'logged later');
+// => 'logged later' (Appears after one second.)
+~~~
+
+
+
+
+
+
+### `_.difference(array [, array1, array2, ...])`
+Produces a new array of `array` values not present in the other arrays using strict equality for comparisons, i.e. `===`.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to process.
+2. `[array1, array2, ...]` *(Mixed)*: Arrays to check.
+
+#### Returns
+*(Array)*: Returns a new array of `array` values not present in the other arrays.
+
+#### Example
+~~~ js
+_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+// => [1, 3, 4]
+~~~
+
+
+
+
+
+
+### `_.escape(string)`
+Escapes a string for insertion into HTML, replacing `&`, `<`, `>`, `"`, `'`, and `/` characters.
+[▲][1]
+
+#### Arguments
+1. `string` *(String)*: The string to escape.
+
+#### Returns
+*(String)*: Returns the escaped string.
+
+#### Example
+~~~ js
+_.escape('Curly, Larry & Moe');
+// => "Curly, Larry & Moe"
+~~~
+
+
+
+
+
+
+### `_.every(collection, callback [, thisArg])`
+Checks if the `callback` returns truthy for **all** values of a `collection`. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Boolean)*: Returns `true` if all values pass the callback check, else `false`.
+
+#### Example
+~~~ js
+_.every([true, 1, null, 'yes'], Boolean);
+=> false
+~~~
+
+
+
+
+
+
+### `_.extend(destination [, source1, source2, ..])`
+Copies enumerable properties from the source objects to the `destination` object. Subsequent sources will overwrite propery assignments of previous sources.
+[▲][1]
+
+#### Arguments
+1. `destination` *(Object)*: The destination object.
+2. `[source1, source2, ..]` *(Object)*: The source objects.
+
+#### Returns
+*(Object)*: Returns the `destination` object.
+
+#### Example
+~~~ js
+_.extend({ 'name': 'moe' }, { 'age': 40 });
+// => { 'name': 'moe', 'age': 40 }
+~~~
+
+
+
+
+
+
+### `_.filter(collection, callback [, thisArg])`
+Examines each value in a `collection`, returning an array of all values the `callback` returns truthy for. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Array)*: Returns a new array of values that passed callback check.
+
+#### Example
+~~~ js
+var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+// => [2, 4, 6]
+~~~
+
+
+
+
+
+
+### `_.find(collection, callback [, thisArg])`
+Examines each value in a `collection`, returning the first one the `callback` returns truthy for. The function returns as soon as it finds an acceptable value, and does not iterate over the entire `collection`. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Mixed)*: Returns the value that passed the callback check.
+
+#### Example
+~~~ js
+var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+// => 2
+~~~
+
+
+
+
+
+
+### `_.first(array [, n, guard])`
+Gets the first value of the `array`. Pass `n` to return the first `n` values of the `array`.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[n]` *(Number)*: The number of elements to return.
+3. `[guard]` *(Object)*: Used to allow the function to work with other iteration methods like `_.map` without using their callback `index` argument for `n`.
+
+#### Returns
+*(Mixed)*: Returns the first value or an array of the first `n` values of the `array`.
+
+#### Example
+~~~ js
+_.first([5, 4, 3, 2, 1]);
+// => 5
+~~~
+
+
+
+
+
+
+### `_.flatten(array, shallow)`
+Flattens a nested array *(the nesting can be to any depth)*. If `shallow` is truthy, `array` will only be flattened a single level.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to compact.
+2. `shallow` *(Boolean)*: A flag to indicate only flattening a single level.
+
+#### Returns
+*(Array)*: Returns a new flattened array.
+
+#### Example
+~~~ js
+_.flatten([1, [2], [3, [[4]]]]);
+// => [1, 2, 3, 4];
+
+_.flatten([1, [2], [3, [[4]]]], true);
+// => [1, 2, 3, [[4]]];
+~~~
+
+
+
+
+
+
+### `_.forEach(collection, callback [, thisArg])`
+Iterates over a `collection`, executing the `callback` for each value in the `collection`. The `callback` is bound to the `thisArg` value, if one is passed. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Array, Object)*: Returns the `collection`.
+
+#### Example
+~~~ js
+_.forforEach([1, 2, 3], function(num) { alert(num); });
+// => alerts each number in turn...
+
+_.forforEach({ 'one' : 1, 'two' : 2, 'three' : 3}, function(num) { alert(num); });
+// => alerts each number in turn...
+~~~
+
+
+
+
+
+
+### `_.functions(object)`
+Produces a sorted array of the `object`'s enumerable own property names that have function values.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns a new array of property names that have function values.
+
+#### Example
+~~~ js
+_.functions(_);
+// => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+~~~
+
+
+
+
+
+
+### `_.groupBy(collection, callback [, thisArg])`
+Splits a `collection` into sets, grouped by the result of running each value through `callback`. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*. The `callback` argument may also be the name of a property to group by.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function|String)*: The function called per iteration or property name to group by.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Object)*: Returns an object of grouped values.
+
+#### Example
+~~~ js
+_.groupBy([1.3, 2.1, 2.4], function(num) { return Math.floor(num); });
+// => { '1': [1.3], '2': [2.1, 2.4] }
+
+_.groupBy(['one', 'two', 'three'], 'length');
+// => { '3': ['one', 'two'], '5': ['three'] }
+~~~
+
+
+
+
+
+
+### `_.has(object, key)`
+Checks if an object has the specified key as a direct property.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to check.
+2. `key` *(String)*: The key to check for.
+
+#### Returns
+*(Boolean)*: Returns `true` if key is a direct property, else `false`.
+
+#### Example
+~~~ js
+_.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+// => true
+~~~
+
+
+
+
+
+
+### `_.identity(value)`
+This function simply returns the first argument passed to it. Note: It is used throughout Lodash as a default callback.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: Any value.
+
+#### Returns
+*(Mixed)*: Returns `value`.
+
+#### Example
+~~~ js
+var moe = { 'name': 'moe' };
+moe === _.identity(moe);
+// => true
+~~~
+
+
+
+
+
+
+### `_.indexOf(array, value [, isSorted=false])`
+Gets the index at which the first occurrence of `value` is found using strict equality for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` for `isSorted` will run a faster binary search.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to search.
+2. `value` *(Mixed)*: The value to search for.
+3. `[isSorted=false]` *(Boolean)*: A flag to indicate that the `array` is already sorted.
+
+#### Returns
+*(Number)*: Returns the index of the matched value or `-1`.
+
+#### Example
+~~~ js
+_.indexOf([1, 2, 3], 2);
+// => 1
+~~~
+
+
+
+
+
+
+### `_.initial(array [, n, guard])`
+Gets all but the last value of the `array`. Pass `n` to exclude the last `n` values from the result.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[n]` *(Number)*: The number of elements to return.
+3. `[guard]` *(Object)*: Used to allow the function to work with other iteration methods like `_.map` without using their callback `index` argument for `n`.
+
+#### Returns
+*(Array)*: Returns all but the last value or `n` values of the `array`.
+
+#### Example
+~~~ js
+_.initial([5, 4, 3, 2, 1]);
+// => [5, 4, 3, 2]
+~~~
+
+
+
+
+
+
+### `_.intersection([array1, array2, ...])`
+Computes the intersection of all the passed-in arrays.
+[▲][1]
+
+#### Arguments
+1. `[array1, array2, ...]` *(Mixed)*: Arrays to process.
+
+#### Returns
+*(Array)*: Returns a new array of unique values, in order, that are present in **all** of the arrays.
+
+#### Example
+~~~ js
+_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+// => [1, 2]
+~~~
+
+
+
+
+
+
+### `_.invoke(collection, methodName [, arg1, arg2, ...])`
+Calls the method named by `methodName` for each value of the `collection`. Additional arguments will be passed to each invoked method.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `methodName` *(String)*: The name of the method to invoke.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to invoke the method with.
+
+#### Returns
+*(Array)*: Returns a new array of values returned from each invoked method.
+
+#### Example
+~~~ js
+_.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+// => [[1, 5, 7], [1, 2, 3]]
+~~~
+
+
+
+
+
+
+### `_.isArguments(value)`
+Checks if a `value` is an `arguments` object.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is an `arguments` object, else `false`.
+
+#### Example
+~~~ js
+(function() { return _.isArguments(arguments); })(1, 2, 3);
+// => true
+
+_.isArguments([1, 2, 3]);
+// => false
+~~~
+
+
+
+
+
+
+### `_.isArray(value)`
+Checks if a `value` is an array.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is an array, else `false`.
+
+#### Example
+~~~ js
+(function() { return _.isArray(arguments); })();
+// => false
+
+_.isArray([1, 2, 3]);
+// => true
+~~~
+
+
+
+
+
+
+### `_.isBoolean(value)`
+Checks if a `value` is a boolean *(`true` or `false`)* value.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a boolean value, else `false`.
+
+#### Example
+~~~ js
+_.isBoolean(null);
+// => false
+~~~
+
+
+
+
+
+
+### `_.isDate(value)`
+Checks if a `value` is a date.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a date, else `false`.
+
+#### Example
+~~~ js
+_.isDate(new Date);
+// => true
+~~~
+
+
+
+
+
+
+### `_.isElement(value)`
+Checks if a `value` is a DOM element.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a DOM element, else `false`.
+
+#### Example
+~~~ js
+_.isElement(document.body);
+// => true
+~~~
+
+
+
+
+
+
+### `_.isEmpty(value)`
+Checks if a `value` is empty. Arrays or strings with a length of `0` and objects with no enumerable own properties are considered "empty".
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is empty, else `false`.
+
+#### Example
+~~~ js
+_.isEmpty([1, 2, 3]);
+// => false
+
+_.isEmpty({});
+// => true
+~~~
+
+
+
+
+
+
+### `_.isEqual(value, other)`
+Performs a deep comparison between two values to determine if they are equivalent to each other.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to compare.
+2. `other` *(Mixed)*: The other value to compare.
+
+#### Returns
+*(Boolean)*: Returns `true` if the values are equvalent, else `false`.
+
+#### Example
+~~~ js
+var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
+var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
+
+moe == clone;
+// => false
+
+_.isEqual(moe, clone);
+// => true
+~~~
+
+
+
+
+
+
+### `_.isFinite(value)`
+Checks if a `value` is a finite number.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a finite number, else `false`.
+
+#### Example
+~~~ js
+_.isFinite(-101);
+// => true
+
+_.isFinite('10');
+// => false
+
+_.isFinite(Infinity);
+// => false
+~~~
+
+
+
+
+
+
+### `_.isFunction(value)`
+Checks if a `value` is a function.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a function, else `false`.
+
+#### Example
+~~~ js
+_.isFunction(''.concat);
+// => true
+~~~
+
+
+
+
+
+
+### `_.isNaN(value)`
+Checks if a `value` is `NaN`. Note: this is not the same as native `isNaN`, which will return true for `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is `NaN`, else `false`.
+
+#### Example
+~~~ js
+_.isNaN(NaN);
+// => true
+
+isNaN(undefined);
+// => true
+
+_.isNaN(undefined);
+// => false
+~~~
+
+
+
+
+
+
+### `_.isNull(value)`
+Checks if a `value` is `null`.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is `null`, else `false`.
+
+#### Example
+~~~ js
+_.isNull(null);
+// => true
+
+_.isNull(undefined);
+// => false
+~~~
+
+
+
+
+
+
+### `_.isNumber(value)`
+Checks if a `value` is a number.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a number, else `false`.
+
+#### Example
+~~~ js
+_.isNumber(8.4 * 5;
+// => true
+~~~
+
+
+
+
+
+
+### `_.isObject(value)`
+Checks if a `value` is an object.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is an object, else `false`.
+
+#### Example
+~~~ js
+_.isObject({});
+// => true
+
+_.isObject(1);
+// => false
+~~~
+
+
+
+
+
+
+### `_.isRegExp(value)`
+Checks if a `value` is a regular expression.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a regular expression, else `false`.
+
+#### Example
+~~~ js
+_.isRegExp(/moe/);
+// => true
+~~~
+
+
+
+
+
+
+### `_.isString(value)`
+Checks if a `value` is a string.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is a string, else `false`.
+
+#### Example
+~~~ js
+_.isString('moe');
+// => true
+~~~
+
+
+
+
+
+
+### `_.isUndefined(value)`
+Checks if a `value` is `undefined`.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to check.
+
+#### Returns
+*(Boolean)*: Returns `true` if the `value` is `undefined`, else `false`.
+
+#### Example
+~~~ js
+_.isUndefined(void 0);
+// => true
+~~~
+
+
+
+
+
+
+### `_.keys(object)`
+Produces an array of the `object`'s enumerable own property names.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns a new array of property names.
+
+#### Example
+~~~ js
+_.keys({ 'one': 1, 'two': 2, 'three': 3 });
+// => ['one', 'two', 'three']
+~~~
+
+
+
+
+
+
+### `_.last(array [, n, guard])`
+Gets the last value of the `array`. Pass `n` to return the lasy `n` values of the `array`.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[n]` *(Number)*: The number of elements to return.
+3. `[guard]` *(Object)*: Used to allow the function to work with other iteration methods like `_.map` without using their callback `index` argument for `n`.
+
+#### Returns
+*(Array)*: Returns all but the last value or `n` values of the `array`.
+
+#### Example
+~~~ js
+_.last([5, 4, 3, 2, 1]);
+// => 1
+~~~
+
+
+
+
+
+
+### `_.lastIndexOf(array, value)`
+Gets the index at which the last occurrence of `value` is found using strict equality for comparisons, i.e. `===`.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to search.
+2. `value` *(Mixed)*: The value to search for.
+
+#### Returns
+*(Number)*: Returns the index of the matched value or `-1`.
+
+#### Example
+~~~ js
+_.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+// => 4
+~~~
+
+
+
+
+
+
+### `_.map(collection, callback [, thisArg])`
+Produces a new array of values by mapping each value in the `collection` through a transformation `callback`. The `callback` is bound to the `thisArg` value, if one is passed. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Array)*: Returns a new array of values returned by the callback.
+
+#### Example
+~~~ js
+_.map([1, 2, 3], function(num) { return num * 3; });
+// => [3, 6, 9]
+
+_.map({ 'one' : 1, 'two' : 2, 'three' : 3 }, function(num) { return num * 3; });
+// => [3, 6, 9]
+~~~
+
+
+
+
+
+
+### `_.max(collection [, callback, thisArg])`
+Retrieves the maximum value of a `collection`. If `callback` is passed, it will be executed for each value in the `collection` to generate the criterion by which the value is ranked. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `[callback]` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Mixed)*: Returns the maximum value.
+
+#### Example
+~~~ js
+var stooges = [
+ { 'name' : 'moe', 'age' : 40},
+ { 'name' : 'larry', 'age' : 50},
+ { 'name' : 'curly', 'age' : 60}
+];
+
+_.max(stooges, function(stooge) { return stooge.age; });
+// => { 'name' : 'curly', 'age' : 60 };
+~~~
+
+
+
+
+
+
+### `_.memoize(func [, hasher=_.identity])`
+Creates a new function that memoizes the result of `func`. If `hasher` is passed, it will be used to compute the hash key for storing the result, based on the arguments to the original function. The default `hasher` uses the first argument to the memoized function as the cache key.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to memoize the output of.
+2. `[hasher=_.identity]` *(Function)*: A function used to resolve the cache keyW.
+
+#### Returns
+*(Function)*: Returns the new memoizing function.
+
+#### Example
+~~~ js
+var fibonacci = _.memoize(function(n) {
+ return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+});
+~~~
+
+
+
+
+
+
+### `_.min(collection [, callback, thisArg])`
+Retrieves the minimum value of a `collection`. If `callback` is passed, it will be executed for each value in the `collection` to generate the criterion by which the value is ranked. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `[callback]` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Mixed)*: Returns the minimum value.
+
+#### Example
+~~~ js
+_.min([10, 5, 100, 2, 1000]);
+// => 2
+~~~
+
+
+
+
+
+
+### `_.mixin(object)`
+Adds functions properties of `object` to the `lodash` function and chainable wrapper.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object of function properties to add to `lodash`.
+
+#### Example
+~~~ js
+_.mixin({
+ 'capitalize': function(string) {
+ return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+ }
+});
+
+_.capitalize('curly');
+// => 'Curly'
+
+_('larry').capitalize();
+// => 'Larry'
+~~~
+
+
+
+
+
+
+### `_.noConflict()`
+Reverts the '_' variable to its previous value and returns a reference to the `lodash` function.
+[▲][1]
+
+#### Returns
+*(Function)*: Returns the `lodash` function.
+
+#### Example
+~~~ js
+var lodash = _.noConflict();
+~~~
+
+
+
+
+
+
+### `_.once(func)`
+Creates a new function that is restricted to one execution. Repeat calls to the function will return the value of the first call.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to restrict.
+
+#### Returns
+*(Function)*: Returns the new restricted function.
+
+#### Example
+~~~ js
+var initialize = _.once(createApplication);
+initialize();
+initialize();
+// Application is only created once.
+~~~
+
+
+
+
+
+
+### `_.pick(object [, prop1, prop2, ..])`
+Creates an object composed of the specified properties. Property names may be specified as individual arguments or as arrays of property names.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to pluck.
+2. `[prop1, prop2, ..]` *(Object)*: The properties to pick.
+
+#### Returns
+*(Object)*: Returns an object composed of the picked properties.
+
+#### Example
+~~~ js
+_.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
+// => { 'name': 'moe', 'age': 40 }
+~~~
+
+
+
+
+
+
+### `_.pluck(collection, property)`
+Retrieves the value of a specified property from all values in a `collection`.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `property` *(String)*: The property to pluck.
+
+#### Returns
+*(Array)*: Returns a new array of property values.
+
+#### Example
+~~~ js
+var stooges = [
+ { 'name' : 'moe', 'age' : 40},
+ { 'name' : 'larry', 'age' : 50},
+ { 'name' : 'curly', 'age' : 60}
+];
+
+_.pluck(stooges, 'name');
+// => ['moe', 'larry', 'curly']
+~~~
+
+
+
+
+
+
+### `_.range([start=0], end [, step=1])`
+Creates an array of numbers *(positive and/or negative)* progressing from `start` up to but not including `stop`. This method is a port of Python's `range()` function. See http://docs.python.org/library/functions.html#range.
+[▲][1]
+
+#### Arguments
+1. `[start=0]` *(Number)*: The start of the range.
+2. `end` *(Number)*: The end of the range.
+3. `[step=1]` *(Number)*: The value to increment or descrement by.
+
+#### Returns
+*(Array)*: Returns a new range array.
+
+#### Example
+~~~ js
+_.range(10);
+// => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+_.range(1, 11);
+// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+
+_.range(0, 30, 5);
+// => [0, 5, 10, 15, 20, 25]
+
+_.range(0, -10, -1);
+// => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+
+_.range(0);
+// => []
+~~~
+
+
+
+
+
+
+### `_.reduce(collection, callback [, accumulator, thisArg])`
+Boils down a `collection` to a single value. The initial state of the reduction is `accumulator` and each successive step of it should be returned by the `callback`. The `callback` is bound to the `thisArg` value, if one is passed. The `callback` is invoked with `4` arguments; for arrays they are *(accumulator, value, index, array)* and for objects they are *(accumulator, value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[accumulator]` *(Mixed)*: Initial value of the accumulator.
+4. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Mixed)*: Returns the accumulated value.
+
+#### Example
+~~~ js
+var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
+// => 6
+~~~
+
+
+
+
+
+
+### `_.reduceRight(collection, callback [, accumulator, thisArg])`
+The right-associative version of `_.reduce`. The `callback` is bound to the `thisArg` value, if one is passed. The `callback` is invoked with `4` arguments; for arrays they are *(accumulator, value, index, array)* and for objects they are *(accumulator, value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[accumulator]` *(Mixed)*: Initial value of the accumulator.
+4. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Mixed)*: Returns the accumulated value.
+
+#### Example
+~~~ js
+var list = [[0, 1], [2, 3], [4, 5]];
+var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+// => [4, 5, 2, 3, 0, 1]
+~~~
+
+
+
+
+
+
+### `_.reject(collection, callback [, thisArg])`
+The opposite of `_.filter`, this method returns the values of a `collection` that `callback` does **not** return truthy for. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Array)*: Returns a new array of values that did **not** pass the callback check.
+
+#### Example
+~~~ js
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+// => [1, 3, 5]
+~~~
+
+
+
+
+
+
+### `_.rest(array [, n, guard])`
+The opposite of `_.initial`, this method gets all but the first value of the `array`. Pass `n` to exclude the first `n` values from the result.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to query.
+2. `[n]` *(Number)*: The number of elements to return.
+3. `[guard]` *(Object)*: Used to allow the function to work with other iteration methods like `_.map` without using their callback `index` argument for `n`.
+
+#### Returns
+*(Array)*: Returns all but the first value or `n` values of the `array`.
+
+#### Example
+~~~ js
+_.rest([5, 4, 3, 2, 1]);
+// => [4, 3, 2, 1]
+~~~
+
+
+
+
+
+
+### `_.result(object, property)`
+Resolves the value of `property` on `object`. If the property is a function it will be invoked and its result returned, else the property value is returned.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+2. `property` *(String)*: The property to get the result of.
+
+#### Returns
+*(Mixed)*: Returns the resolved.
+
+#### Example
+~~~ js
+var object = {
+ 'cheese': 'crumpets',
+ 'stuff': function() {
+ return 'nonsense';
+ }
+};
+
+_.result(object, 'cheese');
+// => 'crumpets'
+
+_.result(object, 'stuff');
+// => 'nonsense'
+~~~
+
+
+
+
+
+
+### `_.shuffle(collection)`
+Produces a new array of shuffled `collection` values, using a version of the Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to shuffle.
+
+#### Returns
+*(Array)*: Returns a new shuffled array.
+
+#### Example
+~~~ js
+_.shuffle([1, 2, 3, 4, 5, 6]);
+// => [4, 1, 6, 3, 5, 2]
+~~~
+
+
+
+
+
+
+### `_.size(collection)`
+Gets the number of values in the `collection`.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection inspect.
+
+#### Returns
+*(Number)*: Returns the number of values in the collection.
+
+#### Example
+~~~ js
+_.size({ 'one': 1, 'two': 2, 'three': 3 });
+// => 3
+~~~
+
+
+
+
+
+
+### `_.some(collection, callback [, thisArg])`
+Checks if the `callback` returns truthy for **any** value of a `collection`. The function returns as soon as it finds passing value, and does not iterate over the entire `collection`. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Boolean)*: Returns `true` if any value passes the callback check, else `false`.
+
+#### Example
+~~~ js
+_.some([null, 0, 'yes', false]);
+// => true
+~~~
+
+
+
+
+
+
+### `_.sortBy(collection, callback [, thisArg])`
+Produces a new sorted array, ranked in ascending order by the results of running each value of a `collection` through `callback`. The `callback` is invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*. The `callback` argument may also be the name of a property to sort by *(e.g. 'length')*.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to iterate over.
+2. `callback` *(Function|String)*: The function called per iteration or property name to sort by.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Returns
+*(Array)*: Returns a new array of sorted values.
+
+#### Example
+~~~ js
+_.sortBy([1, 2, 3, 4, 5, 6], function(num) { return Math.sin(num); });
+// => [5, 4, 6, 3, 1, 2]
+~~~
+
+
+
+
+
+
+### `_.sortedIndex(array, value [, callback])`
+Uses a binary search to determine the index at which the `value` should be inserted into the `collection` in order to maintain the `collection`'s sorted order. If `callback` is passed, it will be executed for each value in the `collection` to compute their sort ranking. The `callback` is invoked with `1` arguments.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to iterate over.
+2. `value` *(Mixed)*: The value to evaluate.
+3. `[callback]` *(Function)*: The function called per iteration.
+
+#### Returns
+*(Number)*: Returns the index at which the value should be inserted into the collection.
+
+#### Example
+~~~ js
+_.sortedIndex([10, 20, 30, 40, 50], 35);
+// => 3
+~~~
+
+
+
+
+
+
+### `_.tap(value, interceptor)`
+Invokes `interceptor` with the `value` as the first argument, and then returns `value`. The primary purpose of this method is to "tap into" a method chain, in order to performoperations on intermediate results within the chain.
+[▲][1]
+
+#### Arguments
+1. `value` *(Mixed)*: The value to pass to `callback`.
+2. `interceptor` *(Function)*: The function to invoke.
+
+#### Returns
+*(Mixed)*: Returns `value`.
+
+#### Example
+~~~ js
+_.chain([1,2,3,200])
+ .filter(function(num) { return num % 2 == 0; })
+ .tap(alert)
+ .map(function(num) { return num * num })
+ .value();
+// => // [2, 200] (alerted)
+// => [4, 40000]
+~~~
+
+
+
+
+
+
+### `_.template(text, data, settings)`
+JavaScript micro-templating, similar to John Resig's implementation. Lo-Dash templating handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code.
+[▲][1]
+
+#### Arguments
+1. `text` *(String)*: The
+2. `data` *(Obect)*: The
+3. `settings` *(Object)*:
+
+#### Returns
+*(String)*: Returns....
+
+#### Example
+~~~ js
+var compiled = _.template('hello: <%= name %>');
+compiled({ 'name': 'moe' });
+// => 'hello: moe'
+
+var list = '% _.forEach(people, function(name) { %>
'
+
+var template = _.template('<%- value %>');
+template({ 'value': '
+~~~
+
+
+
+
+
+
+### `_.throttle(func, wait)`
+Creates a new function that, when invoked, will only call the original function at most once per every `wait` milliseconds.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to throttle.
+2. `wait` *(Number)*: The number of milliseconds to throttle executions to.
+
+#### Returns
+*(Function)*: Returns the new throttled function.
+
+#### Example
+~~~ js
+var throttled = _.throttle(updatePosition, 100);
+jQuery(window).on('scroll', throttled);
+~~~
+
+
+
+
+
+
+### `_.times(n, callback [, thisArg])`
+Executes the `callback` function `n` times.
+[▲][1]
+
+#### Arguments
+1. `n` *(Number)*: The number of times to execute the callback.
+2. `callback` *(Function)*: The function called per iteration.
+3. `[thisArg]` *(Mixed)*: The `this` binding for the callback.
+
+#### Example
+~~~ js
+_.times(3, function() { genie.grantWish(); });
+~~~
+
+
+
+
+
+
+### `_.toArray(collection)`
+Converts the `collection`, into an array. Useful for converting the `arguments` object.
+[▲][1]
+
+#### Arguments
+1. `collection` *(Array|Object)*: The collection to convert.
+
+#### Returns
+*(Array)*: Returns the new converted array.
+
+#### Example
+~~~ js
+(function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+// => [2, 3, 4]
+~~~
+
+
+
+
+
+
+### `_.union([array1, array2, ...])`
+Computes the union of the passed-in arrays.
+[▲][1]
+
+#### Arguments
+1. `[array1, array2, ...]` *(Mixed)*: Arrays to process.
+
+#### Returns
+*(Array)*: Returns a new array of unique values, in order, that are present in one or more of the arrays.
+
+#### Example
+~~~ js
+_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+// => [1, 2, 3, 101, 10]
+~~~
+
+
+
+
+
+
+### `_.uniq(array [, isSorted=false, callback])`
+Produces a duplicate-value-free version of the `array` using strict equality for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` for `isSorted` will run a faster algorithm. If `callback` is passed, each value of `array` is passed through a transformation `callback` before uniqueness is computed. The `callback` is invoked with `3` arguments; *(value, index, array)*.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to process.
+2. `[isSorted=false]` *(Boolean)*: A flag to indicate that the `array` is already sorted.
+3. `[callback]` *(Function)*: A
+
+#### Returns
+*(Array)*: Returns a duplicate-value-free array.
+
+#### Example
+~~~ js
+_.uniq([1, 2, 1, 3, 1, 4]);
+// => [1, 2, 3, 4]
+~~~
+
+
+
+
+
+
+### `_.uniqueId([prefix])`
+Generates a unique id. If `prefix` is passed, the id will be appended to it.
+[▲][1]
+
+#### Arguments
+1. `[prefix]` *(String)*: The value to prefix the id with.
+
+#### Returns
+*(Number, String)*: Returns a numeric id if no prefix is passed, else a string id may be returned.
+
+#### Example
+~~~ js
+_.uniqueId('contact_');
+// => 'contact_104'
+~~~
+
+
+
+
+
+
+### `_.values(object)`
+Produces an array of the `object`'s enumerable own property values.
+[▲][1]
+
+#### Arguments
+1. `object` *(Object)*: The object to inspect.
+
+#### Returns
+*(Array)*: Returns a new array of property values.
+
+#### Example
+~~~ js
+_.values({ 'one': 1, 'two': 2, 'three': 3 });
+// => [1, 2, 3]
+~~~
+
+
+
+
+
+
+### `_.without(array [, value1, value2, ...])`
+Produces a new array with all occurrences of the values removed using strict equality for comparisons, i.e. `===`.
+[▲][1]
+
+#### Arguments
+1. `array` *(Array)*: The array to filter.
+2. `[value1, value2, ...]` *(Mixed)*: Values to remove.
+
+#### Returns
+*(Array)*: Returns a new filtered array.
+
+#### Example
+~~~ js
+_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+// => [2, 3, 4]
+~~~
+
+
+
+
+
+
+### `_.wrap(func, wrapper [, arg1, arg2, ...])`
+Create a new function that passes the `func` function to the `wrapper` function as its first argument. Additional arguments are appended to those passed to the `wrapper` function.
+[▲][1]
+
+#### Arguments
+1. `func` *(Function)*: The function to wrap.
+2. `wrapper` *(Function)*: The wrapper function.
+3. `[arg1, arg2, ...]` *(Mixed)*: Arguments to append to those passed to the wrapper.
+
+#### Returns
+*(Function)*: Returns the new function.
+
+#### Example
+~~~ js
+var hello = function(name) { return 'hello: ' + name; };
+hello = _.wrap(hello, function(func) {
+ return 'before, ' + func('moe') + ', after';
+});
+hello();
+// => 'before, hello: moe, after'
+~~~
+
+
+
+
+
+
+### `_.zip([array1, array2, ...])`
+Merges together the values of each of the arrays with the value at the corresponding position. Useful for separate data sources that are coordinated through matching array indexes. For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix in a similar fashion.
+[▲][1]
+
+#### Arguments
+1. `[array1, array2, ...]` *(Mixed)*: Arrays to process.
+
+#### Returns
+*(Array)*: Returns a new array of merged arrays.
+
+#### Example
+~~~ js
+_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+// => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
+~~~
+
+
+
+
+
+
+
+
+
+## `_.prototype`
+### `_(value)`
+The Lodash function.
+[▲][1]
+
+
+
+### `_#chain()`
+Extracts the value from a wrapped chainable object.
+[▲][1]
+
+#### Returns
+*(Mixed)*: Returns the wrapped object.
+
+#### Example
+~~~ js
+_([1, 2, 3]).value();
+// => [1, 2, 3]
+~~~
+
+
+
+
+
+
+### `_#value()`
+Extracts the value from a wrapped chainable object.
+[▲][1]
+
+#### Returns
+*(Mixed)*: Returns the wrapped object.
+
+#### Example
+~~~ js
+_([1, 2, 3]).value();
+// => [1, 2, 3]
+~~~
+
+
+
+
+
+
+
+
+
+## `_.templateSettings`
+
+
+
+### `_.templateSettings`
+*(Object)*: By default, Lodash uses ERB-style template delimiters, change the following template settings to use alternative delimiters.
+[▲][1]
+
+
+
+
+
+
+
+
+
+
+ [1]: #readme "Jump back to the TOC."
\ No newline at end of file
diff --git a/doc/parse.php b/doc/parse.php
index b50de5796..658c1ffb2 100644
--- a/doc/parse.php
+++ b/doc/parse.php
@@ -1,7 +1,7 @@
'../' . $file,
- 'title' => 'LowDash.js v0.1.0',
- 'url' => 'https://github.com/bestiejs/lowdash/blob/master/lowdash.js'
+ 'title' => 'Lo-Dash v0.1.0',
+ 'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
));
// save to a .md file
diff --git a/lodash.js b/lodash.js
new file mode 100644
index 000000000..875d5ff74
--- /dev/null
+++ b/lodash.js
@@ -0,0 +1,2596 @@
+/*!
+ * Lo-Dash v0.1.0
+ * Copyright 2012 John-David Dalton
+ * Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+ *
+ * Available under MIT license
+ */
+;(function(window, undefined) {
+ 'use strict';
+
+ /** Used to assign each benchmark an incrimented id */
+ var idCounter = 0;
+
+ /** Detect free variable `exports` */
+ var freeExports = typeof exports == 'object' && exports &&
+ (typeof global == 'object' && global && global == global.global && (window = global), exports);
+
+ // Establish the object that gets returned to break out of a loop iteration.
+ var breaker = {};
+
+ var oldDash = window._;
+
+ // Save bytes in the minified (but not gzipped) version:
+ var ArrayProto = Array.prototype,
+ ObjProto = Object.prototype;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var concat = ArrayProto.concat,
+ hasOwnProperty = ObjProto.hasOwnProperty,
+ push = ArrayProto.push,
+ slice = ArrayProto.slice,
+ toString = ObjProto.toString,
+ unshift = ArrayProto.unshift;
+
+ // All **ECMAScript 5** native function implementations that we hope to use
+ // are declared here.
+ var nativeIsArray = Array.isArray,
+ nativeIsFinite = window.isFinite,
+ nativeKeys = Object.keys;
+
+ // When customizing `templateSettings`, if you don't want to define an
+ // interpolation, evaluation or escaping regex, we need one that is
+ // guaranteed not to match.
+ var noMatch = /.^/;
+
+ // Certain characters need to be escaped so that they can be put into a
+ // string literal.
+ var escapes = {
+ '\\': '\\',
+ "'": "'",
+ 'r': '\r',
+ 'n': '\n',
+ 't': '\t',
+ 'u2028': '\u2028',
+ 'u2029': '\u2029'
+ };
+
+ for (var p in escapes) escapes[escapes[p]] = p;
+ var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
+ var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
+
+ // Within an interpolation, evaluation, or escaping, remove HTML escaping
+ // that had been previously added.
+ var unescape = function(code) {
+ return code.replace(unescaper, function(match, escape) {
+ return escapes[escape];
+ });
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * The Lodash function.
+ *
+ * @name _
+ * @constructor
+ * @param {Mixed} value The value to wrap in a chainable `lowdash` object.
+ * @returns {Object} Returns a `lodash` instance.
+ * @example
+ */
+ function lodash(value) {
+ // allow invoking `lodash` without the `new` operator
+ return new Wrapper(value);
+ }
+
+ /**
+ * Creates a wrapped collection that can be used OO-style. This wrapper holds
+ * altered versions of all the Lo-Dash functions. Wrapped objects may be chained.
+ *
+ * @private
+ * @constructor
+ * @param {Mixed} value The value to wrap in a chainable `lodash` object.
+ * @example
+ */
+ function Wrapper(collection) {
+ this._wrapped = collection;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Helper function to continue chaining intermediate results.
+ function resultWrapper(collection, chain) {
+ return chain ? lodash(collection).chain() : collection;
+ }
+
+ // A method to easily add functions to the OOP wrapper.
+ function addToWrapper(name, func) {
+ Wrapper.prototype[name] = function() {
+ var args = slice.call(arguments);
+ unshift.call(args, this._wrapped);
+ return resultWrapper(func.apply(lodash, args), this._chain);
+ };
+ }
+
+ /**
+ * Internal recursive comparison function
+ *
+ * @private
+ * @param {Mixed} a A value.
+ * @param {Mixed} b Another value.
+ * @param {Array} stack Holds seen objects to avoid circular references.
+ * @example
+ */
+ function eq(a, b, stack) {
+ // identical objects are equal. `0 === -0`, but they aren't identical
+ // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal
+ if (a === b) {
+ return a !== 0 || (1 / a == 1 / b);
+ }
+ // a strict comparison is necessary because `null == undefined`
+ if (a == null || b == null) {
+ return a === b;
+ }
+ // unwrap any wrapped objects
+ if (a._chain) {
+ a = a._wrapped;
+ }
+ if (b._chain) {
+ b = b._wrapped;
+ }
+ // invoke a custom `isEqual` method if one is provided
+ if (a.isEqual && isFunction(a.isEqual)) {
+ return a.isEqual(b);
+ }
+ if (b.isEqual && isFunction(b.isEqual)) {
+ return b.isEqual(a);
+ }
+
+ // compare `[[Class]]` names
+ var className = toString.call(a);
+ if (className != toString.call(b)) {
+ return false;
+ }
+ switch (className) {
+ // strings, numbers, dates, and booleans are compared by value
+ case '[object String]':
+ // primitives and their corresponding collection wrappers are equivalent; thus, `"5"` is
+ // equivalent to `new String("5")`
+ return a == String(b);
+
+ case '[object Number]':
+ // `NaN`s are equivalent, but non-reflexive;
+ // an `egal` comparison is performed for other numeric values
+ return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
+
+ case '[object Date]':
+ case '[object Boolean]':
+ // Coerce dates and booleans to numeric primitive values.
+ // Dates are compared by their millisecond representations.
+ // Note that invalid dates with millisecond representations of `NaN` are not equivalent.
+ return +a == +b;
+
+ // regexps are compared by their source and flags
+ case '[object RegExp]':
+ return a.source == b.source &&
+ a.global == b.global &&
+ a.multiline == b.multiline &&
+ a.ignoreCase == b.ignoreCase;
+ }
+
+ if (typeof a != 'object' || typeof b != 'object') {
+ return false;
+ }
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
+ var length = stack.length;
+ while (length--) {
+ // Linear search. Performance is inversely proportional to the number of
+ // unique nested structures.
+ if (stack[length] == a) {
+ return true;
+ }
+ }
+
+ // add the first collection to the stack of traversed objects
+ stack.push(a);
+ var size = 0, result = true;
+
+ // recursively compare objects and arrays
+ if (className == '[object Array]') {
+ // compare array lengths to determine if a deep comparison is necessary
+ size = a.length;
+ result = size == b.length;
+
+ if (result) {
+ // deep compare the contents, ignoring non-numeric properties
+ while (size--) {
+ // ensure commutative equality for sparse arrays
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) {
+ break;
+ }
+ }
+ }
+ } else {
+ // objects with different constructors are not equivalent
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
+ return false;
+ }
+ // deep compare objects
+ for (var key in a) {
+ if (hasOwnProperty.call(a, key)) {
+ // count the expected number of properties
+ size++;
+ // deep compare each member
+ if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) {
+ break;
+ }
+ }
+ }
+ // ensure that both objects contain the same number of properties
+ if (result) {
+ for (key in b) {
+ if (hasOwnProperty.call(b, key) && !(size--)) {
+ break;
+ }
+ }
+ result = !size;
+ }
+ }
+ // remove the first collection from the stack of traversed objects
+ stack.pop();
+ return result;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Checks if a given `target` value is present in a `collection` using strict
+ * equality for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @alias include
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Mixed} target The value to check for.
+ * @returns {Boolean} Returns `true` if `target` value is found, else `false`.
+ * @example
+ *
+ * _.contains([1, 2, 3], 3);
+ * // => true
+ */
+ function contains(collection, target) {
+ return collection == null
+ ? false
+ : some(collection, function(value) { return value === target; });
+ }
+
+ /**
+ * Checks if the `callback` returns truthy for **all** values of a `collection`.
+ * The `callback` is invoked with 3 arguments; for arrays they are
+ * (value, index, array) and for objects they are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias all
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Boolean} Returns `true` if all values pass the callback check, else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * => false
+ */
+ function every(collection, callback, thisArg) {
+ var result = true;
+ if (collection == null) return result;
+ forEach(collection, function(value, index, array) {
+ if (!(result = result && callback.call(thisArg, value, index, array))) return breaker;
+ });
+ return !!result;
+ }
+
+ /**
+ * Examines each value in a `collection`, returning an array of all values the
+ * `callback` returns truthy for. The `callback` is invoked with 3 arguments;
+ * for arrays they are (value, index, array) and for objects they are
+ * (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias select
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Array} Returns a new array of values that passed callback check.
+ * @example
+ *
+ * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ * // => [2, 4, 6]
+ */
+ function filter(collection, callback, thisArg) {
+ var result = [];
+ if (collection == null) return result;
+ forEach(collection, function(value, index, array) {
+ if (callback.call(thisArg, value, index, array)) result[result.length] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Examines each value in a `collection`, returning the first one the `callback`
+ * returns truthy for. The function returns as soon as it finds an acceptable
+ * value, and does not iterate over the entire `collection`. The `callback` is
+ * invoked with 3 arguments; for arrays they are (value, index, array) and for
+ * objects they are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias detect
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Mixed} Returns the value that passed the callback check.
+ * @example
+ *
+ * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ * // => 2
+ */
+ function find(collection, callback, thisArg) {
+ var result;
+ some(collection, function(value, index, array) {
+ if (callback.call(thisArg, value, index, array)) {
+ result = value;
+ return true;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Iterates over a `collection`, executing the `callback` for each value in the
+ * `collection`. The `callback` is bound to the `thisArg` value, if one is passed.
+ * The `callback` is invoked with 3 arguments; for arrays they are
+ * (value, index, array) and for objects they are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias each
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Array|Object} Returns the `collection`.
+ * @example
+ *
+ * _.forforEach([1, 2, 3], function(num) { alert(num); });
+ * // => alerts each number in turn...
+ *
+ * _.forforEach({ 'one' : 1, 'two' : 2, 'three' : 3}, function(num) { alert(num); });
+ * // => alerts each number in turn...
+ */
+ function forEach(collection, callback, thisArg) {
+ if (collection != null) {
+ if (collection.length === +collection.length) {
+ for (var index = 0, length = collection.length; index < length; index++) {
+ if (index in collection && callback.call(thisArg, collection[index], index, collection) === breaker) {
+ break;
+ }
+ }
+ } else {
+ for (var key in collection) {
+ if (hasOwnProperty.call(collection, key)) {
+ if (callback.call(thisArg, collection[key], key, collection) === breaker) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return collection;
+ }
+
+ /**
+ * Splits a `collection` into sets, grouped by the result of running each value
+ * through `callback`. The `callback` is invoked with 3 arguments; for arrays
+ * they are (value, index, array) and for objects they are (value, key, object).
+ * The `callback` argument may also be the name of a property to group by.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|String} callback The function called per iteration or
+ * property name to group by.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Object} Returns an object of grouped values.
+ * @example
+ *
+ * _.groupBy([1.3, 2.1, 2.4], function(num) { return Math.floor(num); });
+ * // => { '1': [1.3], '2': [2.1, 2.4] }
+ *
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
+ */
+ function groupBy(collection, callback, thisArg) {
+ var result = {};
+ if (!isFunction(callback)) {
+ var key = callback;
+ callback = function(collection) { return collection[key]; };
+ }
+ forEach(collection, function(value, index) {
+ var key = callback(value, index);
+ (result[key] || (result[key] = [])).push(value);
+ });
+ return result;
+ }
+
+ /**
+ * Calls the method named by `methodName` for each value of the `collection`.
+ * Additional arguments will be passed to each invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {String} methodName The name of the method to invoke.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+ * @returns {Array} Returns a new array of values returned from each invoked method.
+ * @example
+ *
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ */
+ function invoke(collection, methodName) {
+ var args = slice.call(arguments, 2),
+ isFunc = isFunction(methodName);
+
+ return map(collection, function(value) {
+ return (isFunc ? methodName || value : value[methodName]).apply(value, args);
+ });
+ }
+
+ /**
+ * Produces a new array of values by mapping each value in the `collection`
+ * through a transformation `callback`. The `callback` is bound to the `thisArg`
+ * value, if one is passed. The `callback` is invoked with 3 arguments; for
+ * arrays they are (value, index, array) and for objects they are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias collect
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Array} Returns a new array of values returned by the callback.
+ * @example
+ *
+ * _.map([1, 2, 3], function(num) { return num * 3; });
+ * // => [3, 6, 9]
+ *
+ * _.map({ 'one' : 1, 'two' : 2, 'three' : 3 }, function(num) { return num * 3; });
+ * // => [3, 6, 9]
+ */
+ function map(collection, callback, thisArg) {
+ var result = [];
+ if (collection == null) {
+ return result;
+ }
+ forEach(collection, function(value, index, array) {
+ result[result.length] = callback.call(thisArg, value, index, array);
+ });
+ if (collection.length === +collection.length) result.length = collection.length;
+ return result;
+ }
+
+ /**
+ * Retrieves the maximum value of a `collection`. If `callback` is passed,
+ * it will be executed for each value in the `collection` to generate the
+ * criterion by which the value is ranked. The `callback` is invoked with 3
+ * arguments; for arrays they are (value, index, array) and for objects they
+ * are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [callback] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Mixed} Returns the maximum value.
+ * @example
+ *
+ * var stooges = [
+ * { 'name' : 'moe', 'age' : 40},
+ * { 'name' : 'larry', 'age' : 50},
+ * { 'name' : 'curly', 'age' : 60}
+ * ];
+ *
+ * _.max(stooges, function(stooge) { return stooge.age; });
+ * // => { 'name' : 'curly', 'age' : 60 };
+ */
+ function max(collection, callback, thisArg) {
+ if (!callback && isArray(collection) && collection[0] === +collection[0])
+ return Math.max.apply(Math, collection);
+ if (!callback && isEmpty(collection))
+ return -Infinity;
+ var result = {computed : -Infinity};
+ forEach(collection, function(value, index, array) {
+ var computed = callback ? callback.call(thisArg, value, index, array) : value;
+ computed >= result.computed && (result = { 'computed': computed, 'value': value });
+ });
+ return result.value;
+ }
+
+ /**
+ * Retrieves the minimum value of a `collection`. If `callback` is passed,
+ * it will be executed for each value in the `collection` to generate the
+ * criterion by which the value is ranked. The `callback` is invoked with 3
+ * arguments; for arrays they are (value, index, array) and for objects they
+ * are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} [callback] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Mixed} Returns the minimum value.
+ * @example
+ *
+ * _.min([10, 5, 100, 2, 1000]);
+ * // => 2
+ */
+ function min(collection, callback, thisArg) {
+ if (!callback && isArray(collection) && collection[0] === +collection[0]) return Math.min.apply(Math, collection);
+ if (!callback && isEmpty(collection)) return Infinity;
+ var result = {computed : Infinity};
+ forEach(collection, function(value, index, array) {
+ var computed = callback ? callback.call(thisArg, value, index, array) : value;
+ computed < result.computed && (result = { 'computed': computed, 'value': value });
+ });
+ return result.value;
+ }
+
+ /**
+ * Retrieves the value of a specified property from all values in a `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {String} property The property to pluck.
+ * @returns {Array} Returns a new array of property values.
+ * @example
+ *
+ * var stooges = [
+ * { 'name' : 'moe', 'age' : 40},
+ * { 'name' : 'larry', 'age' : 50},
+ * { 'name' : 'curly', 'age' : 60}
+ * ];
+ *
+ * _.pluck(stooges, 'name');
+ * // => ['moe', 'larry', 'curly']
+ */
+ function pluck(collection, key) {
+ return map(collection, function(value){ return value[key]; });
+ }
+
+ /**
+ * Boils down a `collection` to a single value. The initial state of the
+ * reduction is `accumulator` and each successive step of it should be returned
+ * by the `callback`. The `callback` is bound to the `thisArg` value, if one is
+ * passed. The `callback` is invoked with 4 arguments; for arrays they are
+ * (accumulator, value, index, array) and for objects they are
+ * (accumulator, value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias foldl, inject
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Mixed} Returns the accumulated value.
+ * @example
+ *
+ * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
+ * // => 6
+ */
+ function reduce(collection, callback, accumulator, thisArg) {
+ var initial = arguments.length > 2;
+ if (collection == null) collection = [];
+ forEach(collection, function(value, index, array) {
+ if (!initial) {
+ accumulator = value;
+ initial = true;
+ } else {
+ accumulator = callback.call(thisArg, accumulator, value, index, array);
+ }
+ });
+ if (!initial) throw new TypeError('Reduce of empty array with no initial value');
+ return accumulator;
+ }
+
+ /**
+ * The right-associative version of `_.reduce`. The `callback` is bound to the
+ * `thisArg` value, if one is passed. The `callback` is invoked with 4 arguments;
+ * for arrays they are (accumulator, value, index, array) and for objects they
+ * are (accumulator, value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias foldr
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Mixed} Returns the accumulated value.
+ * @example
+ *
+ * var list = [[0, 1], [2, 3], [4, 5]];
+ * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+ * // => [4, 5, 2, 3, 0, 1]
+ */
+ function reduceRight(collection, callback, accumulator, thisArg) {
+ var initial = arguments.length > 2;
+ if (collection == null) collection = [];
+ var reversed = toArray(collection).reverse();
+ if (thisArg && !initial) callback = bind(callback, thisArg);
+ return initial ? reduce(reversed, callback, accumulator, thisArg) : reduce(reversed, callback);
+ }
+
+ /**
+ * The opposite of `_.filter`, this method returns the values of a `collection`
+ * that `callback` does **not** return truthy for. The `callback` is invoked
+ * with 3 arguments; for arrays they are (value, index, array) and for objects
+ * they are (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Array} Returns a new array of values that did **not** pass the callback check.
+ * @example
+ *
+ * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ * // => [1, 3, 5]
+ */
+ function reject(collection, callback, thisArg) {
+ var result = [];
+ if (collection == null) return result;
+ forEach(collection, function(value, index, array) {
+ if (!callback.call(thisArg, value, index, array)) result[result.length] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Produces a new array of shuffled `collection` values, using a version of the
+ * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to shuffle.
+ * @returns {Array} Returns a new shuffled array.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4, 5, 6]);
+ * // => [4, 1, 6, 3, 5, 2]
+ */
+ function shuffle(collection) {
+ var shuffled = [], rand;
+ forEach(collection, function(value, index, array) {
+ rand = Math.floor(Math.random() * (index + 1));
+ shuffled[index] = shuffled[rand];
+ shuffled[rand] = value;
+ });
+ return shuffled;
+ }
+
+ /**
+ * Gets the number of values in the `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection inspect.
+ * @returns {Number} Returns the number of values in the collection.
+ * @example
+ *
+ * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => 3
+ */
+ function size(collection) {
+ return isArray(collection) ? collection.length : keys(collection).length;
+ }
+
+ /**
+ * Produces a new sorted array, ranked in ascending order by the results of
+ * running each value of a `collection` through `callback`. The `callback` is
+ * invoked with 3 arguments; for arrays they are (value, index, array) and for
+ * objects they are (value, key, object). The `callback` argument may also be
+ * the name of a property to sort by (e.g. 'length').
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function|String} callback The function called per iteration or
+ * property name to sort by.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Array} Returns a new array of sorted values.
+ * @example
+ *
+ * _.sortBy([1, 2, 3, 4, 5, 6], function(num) { return Math.sin(num); });
+ * // => [5, 4, 6, 3, 1, 2]
+ */
+ function sortBy(collection, callback, thisArg) {
+ if (!isFunction(callback)) {
+ var key = callback;
+ callback = function(collection) { return collection[key]; };
+ }
+ return pluck(map(collection, function(value, index, array) {
+ return {
+ 'value' : value,
+ 'criteria' : callback.call(thisArg, value, index, array)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ if (a === void 0) return 1;
+ if (b === void 0) return -1;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ }
+
+ /**
+ * Checks if the `callback` returns truthy for **any** value of a `collection`.
+ * The function returns as soon as it finds passing value, and does not iterate
+ * over the entire `collection`. The `callback` is invoked with 3 arguments; for
+ * arrays they are (value, index, array) and for objects they are
+ * (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @alias any
+ * @category Collections
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @returns {Boolean} Returns `true` if any value passes the callback check, else `false`.
+ * @example
+ *
+ * _.some([null, 0, 'yes', false]);
+ * // => true
+ */
+ function some(collection, callback, thisArg) {
+ callback || (callback = identity);
+ var result = false;
+ if (collection == null) return result;
+ forEach(collection, function(value, index, array) {
+ if (result || (result = callback.call(thisArg, value, index, array))) return breaker;
+ });
+ return !!result;
+ }
+
+ /**
+ * Uses a binary search to determine the index at which the `value` should be
+ * inserted into the `collection` in order to maintain the `collection`'s sorted
+ * order. If `callback` is passed, it will be executed for each value in the
+ * `collection` to compute their sort ranking. The `callback` is invoked with
+ * 1 arguments.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array} array The array to iterate over.
+ * @param {Mixed} value The value to evaluate.
+ * @param {Function} [callback] The function called per iteration.
+ * @returns {Number} Returns the index at which the value should be inserted
+ * into the collection.
+ * @example
+ *
+ * _.sortedIndex([10, 20, 30, 40, 50], 35);
+ * // => 3
+ */
+ function sortedIndex(array, object, callback) {
+ callback || (callback = identity);
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ callback(array[mid]) < callback(object) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ }
+
+ /**
+ * Converts the `collection`, into an array. Useful for converting the
+ * `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object} collection The collection to convert.
+ * @returns {Array} Returns the new converted array.
+ * @example
+ *
+ * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+ * // => [2, 3, 4]
+ */
+ function toArray(collection) {
+ if (!collection) {
+ return [];
+ }
+ if (isArray(collection) || isArguments(collection)) {
+ return slice.call(collection);
+ }
+ if (isFunction(collection.toArray)) {
+ return collection.toArray();
+ }
+ return values(collection);
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Produces a new array with all falsey values of `array` removed. The values
+ * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns a new filtered array.
+ * @example
+ *
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
+ */
+ function compact(array) {
+ return filter(array, Boolean);
+ }
+
+ /**
+ * Produces a new array of `array` values not present in the other arrays
+ * using strict equality for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to process.
+ * @param {Mixed} [array1, array2, ...] Arrays to check.
+ * @returns {Array} Returns a new array of `array` values not present in the
+ * other arrays.
+ * @example
+ *
+ * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+ * // => [1, 3, 4]
+ */
+ function difference(array) {
+ var values = concat.apply([], slice.call(arguments, 1));
+ return filter(array, function(value) { return indexOf(values, value) < 0; });
+ }
+
+ /**
+ * Gets the first value of the `array`. Pass `n` to return the first `n` values
+ * of the `array`.
+ *
+ * @static
+ * @memberOf _
+ * @alias head, take
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n] The number of elements to return.
+ * @param {Object} [guard] Used to allow the function to work with other iteration
+ * methods like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Mixed} Returns the first value or an array of the first `n`
+ * values of the `array`.
+ * @example
+ *
+ * _.first([5, 4, 3, 2, 1]);
+ * // => 5
+ */
+ function first(array, n, guard) {
+ return (n == null || guard) ? array[0] : slice.call(array, 0, n);
+ }
+
+ /**
+ * Flattens a nested array (the nesting can be to any depth). If `shallow` is
+ * truthy, `array` will only be flattened a single level.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to compact.
+ * @param {Boolean} shallow A flag to indicate only flattening a single level.
+ * @returns {Array} Returns a new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2], [3, [[4]]]]);
+ * // => [1, 2, 3, 4];
+ *
+ * _.flatten([1, [2], [3, [[4]]]], true);
+ * // => [1, 2, 3, [[4]]];
+ */
+ function flatten(array, shallow) {
+ if (shallow) {
+ return concat.apply([], array);
+ }
+ return reduce(array, function(accumulator, value) {
+ if (isArray(value)) {
+ push.apply(accumulator, flatten(value));
+ return accumulator;
+ }
+ accumulator[accumulator.length] = value;
+ return accumulator;
+ }, []);
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `value` is found using
+ * strict equality for comparisons, i.e. `===`. If the `array` is already
+ * sorted, passing `true` for `isSorted` will run a faster binary search.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to search.
+ * @param {Mixed} value The value to search for.
+ * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+ * @returns {Number} Returns the index of the matched value or `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 3], 2);
+ * // => 1
+ */
+ function indexOf(array, value, isSorted) {
+ var index, length;
+ if (array == null) {
+ return -1;
+ }
+ if (isSorted) {
+ index = sortedIndex(array, value);
+ return array[index] === value ? index : -1;
+ }
+ for (index = 0, length = array.length; index < length; index++) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Gets all but the last value of the `array`. Pass `n` to exclude the last `n`
+ * values from the result.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n] The number of elements to return.
+ * @param {Object} [guard] Used to allow the function to work with other iteration
+ * methods like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Array} Returns all but the last value or `n` values of the `array`.
+ * @example
+ *
+ * _.initial([5, 4, 3, 2, 1]);
+ * // => [5, 4, 3, 2]
+ */
+ function initial(array, n, guard) {
+ return slice.call(array, 0, -((n == null || guard) ? 1 : n));
+ }
+
+ /**
+ * Computes the intersection of all the passed-in arrays.
+ *
+ * @static
+ * @memberOf _
+ * @alias intersect
+ * @category Arrays
+ * @param {Mixed} [array1, array2, ...] Arrays to process.
+ * @returns {Array} Returns a new array of unique values, in order, that are
+ * present in **all** of the arrays.
+ * @example
+ *
+ * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+ * // => [1, 2]
+ */
+ function intersection(array) {
+ var rest = slice.call(arguments, 1);
+ return filter(uniq(array), function(value) {
+ return every(rest, function(other) {
+ return indexOf(other, value) >= 0;
+ });
+ });
+ }
+
+ /**
+ * Gets the last value of the `array`. Pass `n` to return the lasy `n` values
+ * of the `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n] The number of elements to return.
+ * @param {Object} [guard] Used to allow the function to work with other iteration
+ * methods like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Array} Returns all but the last value or `n` values of the `array`.
+ * @example
+ *
+ * _.last([5, 4, 3, 2, 1]);
+ * // => 1
+ */
+ function last(array, n, guard) {
+ var length = array.length;
+ return (n == null || guard) ? array[length - 1] : slice.call(array, -n || length);
+ }
+
+ /**
+ * Gets the index at which the last occurrence of `value` is found using
+ * strict equality for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to search.
+ * @param {Mixed} value The value to search for.
+ * @returns {Number} Returns the index of the matched value or `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+ * // => 4
+ */
+ function lastIndexOf(array, value) {
+ if (array != null) {
+ var index = array.length;
+ while (index--) {
+ if (array[index] === value) return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to but not including `stop`. This method is a port of Python's
+ * `range()` function. See http://docs.python.org/library/functions.html#range.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Number} [start=0] The start of the range.
+ * @param {Number} end The end of the range.
+ * @param {Number} [step=1] The value to increment or descrement by.
+ * @returns {Array} Returns a new range array.
+ * @example
+ *
+ * _.range(10);
+ * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ *
+ * _.range(1, 11);
+ * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ *
+ * _.range(0, 30, 5);
+ * // => [0, 5, 10, 15, 20, 25]
+ *
+ * _.range(0, -10, -1);
+ * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+ *
+ * _.range(0);
+ * // => []
+ */
+ function range(start, end, step) {
+ if (arguments.length <= 1) {
+ end = start || 0;
+ start = 0;
+ }
+ step = arguments[2] || 1;
+
+ var length = Math.max(Math.ceil((end - start) / step), 0);
+ var idx = 0;
+ var result = new Array(length);
+
+ while(idx < length) {
+ result[idx++] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * The opposite of `_.initial`, this method gets all but the first value of
+ * the `array`. Pass `n` to exclude the first `n` values from the result.
+ *
+ * @static
+ * @memberOf _
+ * @alias tail
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n] The number of elements to return.
+ * @param {Object} [guard] Used to allow the function to work with other iteration
+ * methods like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Array} Returns all but the first value or `n` values of the `array`.
+ * @example
+ *
+ * _.rest([5, 4, 3, 2, 1]);
+ * // => [4, 3, 2, 1]
+ */
+ function rest(array, index, guard) {
+ return slice.call(array, (index == null || guard) ? 1 : index);
+ }
+
+ /**
+ * Computes the union of the passed-in arrays.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Mixed} [array1, array2, ...] Arrays to process.
+ * @returns {Array} Returns a new array of unique values, in order, that are
+ * present in one or more of the arrays.
+ * @example
+ *
+ * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+ * // => [1, 2, 3, 101, 10]
+ */
+ function union() {
+ return uniq(flatten(arguments, true));
+ }
+
+ /**
+ * Produces a duplicate-value-free version of the `array` using strict equality
+ * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
+ * for `isSorted` will run a faster algorithm. If `callback` is passed,
+ * each value of `array` is passed through a transformation `callback` before
+ * uniqueness is computed. The `callback` is invoked with 3 arguments;
+ * (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @alias unique
+ * @category Arrays
+ * @param {Array} array The array to process.
+ * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+ * @param {Function} [callback] A
+ * @returns {Array} Returns a duplicate-value-free array.
+ * @example
+ *
+ * _.uniq([1, 2, 1, 3, 1, 4]);
+ * // => [1, 2, 3, 4]
+ */
+ function uniq(array, isSorted, callback) {
+ var initial = callback ? map(array, callback) : array,
+ result = [];
+
+ // the `isSorted` flag is irrelevant if the array only contains two elements.
+ if (array.length < 3) {
+ isSorted = true;
+ }
+ reduce(initial, function(accumulator, value, index) {
+ if (isSorted ? last(accumulator) !== value || !accumulator.length : indexOf(accumulator, value) < 0) {
+ accumulator.push(value);
+ result.push(array[index]);
+ }
+ return accumulator;
+ }, []);
+ return result;
+ }
+
+ /**
+ * Produces a new array with all occurrences of the values removed using strict
+ * equality for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to filter.
+ * @param {Mixed} [value1, value2, ...] Values to remove.
+ * @returns {Array} Returns a new filtered array.
+ * @example
+ *
+ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+ * // => [2, 3, 4]
+ */
+ function without(array) {
+ return difference(array, slice.call(arguments, 1));
+ }
+
+ /**
+ * Merges together the values of each of the arrays with the value at the
+ * corresponding position. Useful for separate data sources that are coordinated
+ * through matching array indexes. For a matrix of nested arrays, `_.zip.apply(...)`
+ * can transpose the matrix in a similar fashion.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Mixed} [array1, array2, ...] Arrays to process.
+ * @returns {Array} Returns a new array of merged arrays.
+ * @example
+ *
+ * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+ * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
+ */
+ function zip() {
+ var length = max(pluck(arguments, 'length')),
+ result = Array(length);
+
+ for (var index = 0; index < length; index++) {
+ result[index] = pluck(arguments, index);
+ }
+ return result;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a new function that is restricted to executing only after it is
+ * called a given number of `times`.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Number} times The number of times the function must be called before
+ * it is executed.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var renderNotes = _.after(notes.length, render);
+ * _.forEach(notes, function(note) {
+ * note.asyncSave({ 'success': renderNotes });
+ * });
+ * // renderNotes is run once, after all notes have saved.
+ */
+ function after(times, func) {
+ if (times < 1) {
+ return func();
+ }
+ return function() {
+ if (--times < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+
+ /**
+ * Creates a new function that, when called, invokes `func` with the `this`
+ * binding of `thisArg` and prepends additional arguments to those passed to
+ * the bound function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to bind.
+ * @param @param {Mixed} [thisArg] The `this` binding of `func`.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to prepend to those passed to the bound function.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var func = function(greeting){ return greeting + ': ' + this.name; };
+ * func = _.bind(func, { 'name': 'moe' }, 'hi');
+ * func();
+ * // => 'hi: moe'
+ */
+ function bind(func, thisArg) {
+ var args = args = slice.call(arguments, 2),
+ argsLength = args.length;
+
+ return function() {
+ args.length = argsLength;
+ push.apply(args, arguments);
+ return func.apply(thisArg, args);
+ };
+ }
+
+ /**
+ * Binds methods on the `object` to the object, overwriting the non-bound method.
+ * If no method names are provided, all the function properties of the `object`
+ * will be bound.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Object} object The object to bind and assign the bound methods to.
+ * @param {Mixed} [methodName1, methodName2, ...] Method names on the object to bind.
+ * @returns {Object} Returns the `object`.
+ * @example
+ *
+ * var buttonView = {
+ * 'label': 'lodash',
+ * 'onClick': function() { alert('clicked: ' + this.label); },
+ * 'onHover': function() { console.log('hovering: ' + this.label); }
+ * };
+ *
+ * _.bindAll(buttonView);
+ * jQuery('#lodash_button').on('click', buttonView.onClick);
+ * // => When the button is clicked, `this.label` will have the correct value
+ */
+ function bindAll(object) {
+ var funcs = slice.call(arguments, 1);
+ if (funcs.length == 0) funcs = functions(object);
+ forEach(funcs, function(f) { object[f] = bind(object[f], object); });
+ return object;
+ }
+
+ /**
+ * Creates a new function that is the composition of the passed functions,
+ * where each function consumes the return value of the function that follows.
+ * In math terms, composing thefunctions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Mixed} [func1, func2, ...] Functions to compose.
+ * @returns {Function} Returns the new composed function.
+ * @example
+ *
+ * var greet = function(name) { return 'hi: ' + name; };
+ * var exclaim = function(statement) { return statement + '!'; };
+ * var welcome = _.compose(exclaim, greet);
+ * welcome('moe');
+ * // => 'hi: moe!'
+ */
+ function compose() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments;
+ for (var index = funcs.length - 1; index >= 0; index--) {
+ args = [funcs[index].apply(this, args)];
+ }
+ return args[0];
+ };
+ }
+
+ /**
+ * Creates a new function that will postpone its execution until after `wait`
+ * milliseconds have elapsed since the last time it was invoked. Pass `true`
+ * for `immediate` to cause debounce to invoke the function on the leading,
+ * intead of the trailing, edge of the wait timeout.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to debounce.
+ * @param {Number} wait The number of milliseconds to postone.
+ * @param {Boolean} immediate A flag to indicate execution is on the leading
+ * edge of the wait timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * var lazyLayout = _.debounce(calculateLayout, 300);
+ * jQuery(window).on('resize', lazyLayout);
+ */
+ function debounce(func, wait, immediate) {
+ var timeout;
+ return function() {
+ var thisArg = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ if (!immediate) func.apply(thisArg, args);
+ };
+ if (immediate && !timeout) func.apply(thisArg, args);
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+ }
+
+ /**
+ * Invokes the `func` function after `wait` milliseconds. Additional arguments
+ * are passed `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to delay.
+ * @param {Number} wait The number of milliseconds to delay execution.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+ * @returns {Number} Returns the `setTimeout` timeout id.
+ * @example
+ *
+ * var log = _.bind(console.log, console);
+ * _.delay(log, 1000, 'logged later');
+ * // => 'logged later' (Appears after one second.)
+ */
+ function delay(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function(){ return func.apply(null, args); }, wait);
+ }
+
+ /**
+ * Defers invoking the `func` function until the current call stack has cleared.
+ * Additional arguments are passed to `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to defer.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+ * @returns {Number} Returns the `setTimeout` timeout id.
+ * @example
+ *
+ * _.defer(function(){ alert('deferred'); });
+ * // Returns from the function before the alert runs.
+ */
+ function defer(func) {
+ var args = [func, 1];
+ push.apply(args, slice.call(arguments, 1));
+ return delay.apply(lodash, args);
+ }
+
+ /**
+ * Creates a new function that memoizes the result of `func`. If `hasher` is
+ * passed, it will be used to compute the hash key for storing the result,
+ * based on the arguments to the original function. The default `hasher` uses
+ * the first argument to the memoized function as the cache key.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to memoize the output of.
+ * @param {Function} [hasher=_.identity] A function used to resolve the cache keyW.
+ * @returns {Function} Returns the new memoizing function.
+ * @example
+ *
+ * var fibonacci = _.memoize(function(n) {
+ * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+ * });
+ */
+ function memoize(func, hasher) {
+ var cache = {};
+ hasher || (hasher = identity);
+ return function() {
+ var key = hasher.apply(this, arguments);
+ return hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = func.apply(this, arguments));
+ };
+ }
+
+ /**
+ * Creates a new function that is restricted to one execution. Repeat calls to
+ * the function will return the value of the first call.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // Application is only created once.
+ */
+ function once(func) {
+ var result,
+ ran = false;
+
+ return function() {
+ if (ran) {
+ return result;
+ }
+ ran = true;
+ return (result = func.apply(this, arguments));
+ };
+ }
+
+ /**
+ * Creates a new function that, when invoked, will only call the original
+ * function at most once per every `wait` milliseconds.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to throttle.
+ * @param {Number} wait The number of milliseconds to throttle executions to.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * var throttled = _.throttle(updatePosition, 100);
+ * jQuery(window).on('scroll', throttled);
+ */
+ function throttle(func, wait) {
+ var thisArg, args, timeout, throttling, more, result;
+ var whenDone = debounce(function(){ more = throttling = false; }, wait);
+ return function() {
+ thisArg = this; args = arguments;
+ var later = function() {
+ timeout = null;
+ if (more) func.apply(thisArg, args);
+ whenDone();
+ };
+ if (!timeout) timeout = setTimeout(later, wait);
+ if (throttling) {
+ more = true;
+ } else {
+ result = func.apply(thisArg, args);
+ }
+ whenDone();
+ throttling = true;
+ return result;
+ };
+ }
+
+ /**
+ * Create a new function that passes the `func` function to the `wrapper`
+ * function as its first argument. Additional arguments are appended to those
+ * passed to the `wrapper` function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to wrap.
+ * @param {Function} wrapper The wrapper function.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to append to those passed to the wrapper.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var hello = function(name) { return 'hello: ' + name; };
+ * hello = _.wrap(hello, function(func) {
+ * return 'before, ' + func('moe') + ', after';
+ * });
+ * hello();
+ * // => 'before, hello: moe, after'
+ */
+ function wrap(func, wrapper) {
+ return function() {
+ var args = [func];
+ push.apply(args, arguments);
+ return wrapper.apply(this, args);
+ };
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Create a shallow clone of the `value`. Any nested objects or arrays will be
+ * assigned by reference and not cloned.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to clone.
+ * @returns {Mixed} Returns the cloned `value`.
+ * @example
+ *
+ * _.clone({ 'name': 'moe' });
+ * // => { 'name': 'moe' };
+ */
+ function clone(value) {
+ if (!isObject(value)) {
+ return value;
+ }
+ return isArray(value) ? value.slice() : extend({}, value);
+ }
+
+ /**
+ * Assigns missing properties in `object` with default values from the defaults
+ * objects. As soon as a property is set, additional defaults of the same
+ * property will be ignored.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to populate.
+ * @param {Object} [defaults1, defaults2, ..] The defaults objects to apply to `object`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var iceCream = { 'flavor': 'chocolate' };
+ * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'lots' });
+ * // => { 'flavor': 'chocolate', 'sprinkles': 'lots' }
+ */
+ function defaults(object) {
+ forEach(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ if (object[prop] == null) object[prop] = source[prop];
+ }
+ });
+ return object;
+ }
+
+ /**
+ * Copies enumerable properties from the source objects to the `destination` object.
+ * Subsequent sources will overwrite propery assignments of previous sources.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} destination The destination object.
+ * @param {Object} [source1, source2, ..] The source objects.
+ * @returns {Object} Returns the `destination` object.
+ * @example
+ *
+ * _.extend({ 'name': 'moe' }, { 'age': 40 });
+ * // => { 'name': 'moe', 'age': 40 }
+ */
+ function extend(destination) {
+ forEach(slice.call(arguments, 1), function(source) {
+ for (var prop in source) {
+ destination[prop] = source[prop];
+ }
+ });
+ return destination;
+ }
+
+ /**
+ * Produces a sorted array of the `object`'s enumerable own property names that
+ * have function values.
+ *
+ * @static
+ * @memberOf _
+ * @alias methods
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property names that have function values.
+ * @example
+ *
+ * _.functions(_);
+ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+ */
+ function functions(object) {
+ var names = [];
+ for (var key in object) {
+ if (isFunction(object[key])) names.push(key);
+ }
+ return names.sort();
+ }
+
+ /**
+ * Checks if an object has the specified key as a direct property.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to check.
+ * @param {String} key The key to check for.
+ * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+ * @example
+ *
+ * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+ * // => true
+ */
+ function has(object, key) {
+ return hasOwnProperty.call(object, key);
+ }
+
+ /**
+ * Checks if a `value` is an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+ * @example
+ *
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ function isArguments(value) {
+ return toString.call(value) == '[object Arguments]';
+ }
+
+ /**
+ * Checks if a `value` is an array.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
+ * @example
+ *
+ * (function() { return _.isArray(arguments); })();
+ * // => false
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ */
+ function isArray(value) {
+ return toString.call(value) == '[object Array]';
+ }
+
+ /**
+ * Checks if a `value` is a boolean (`true` or `false`) value.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
+ * @example
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+ function isBoolean(value) {
+ return value === true || value === false || toString.call(value) == '[object Boolean]';
+ }
+
+ /**
+ * Checks if a `value` is a date.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
+ * @example
+ *
+ * _.isDate(new Date);
+ * // => true
+ */
+ function isDate(value) {
+ return toString.call(value) == '[object Date]';
+ }
+
+ /**
+ * Checks if a `value` is a DOM element.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
+ * @example
+ *
+ * _.isElement(document.body);
+ * // => true
+ */
+ function isElement(value) {
+ return !!(value && value.nodeType == 1);
+ }
+
+ /**
+ * Checks if a `value` is empty. Arrays or strings with a length of 0 and
+ * objects with no enumerable own properties are considered "empty".
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({});
+ * // => true
+ */
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArray(value) || isString(value)) {
+ return value.length === 0;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent to each other.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to compare.
+ * @param {Mixed} other The other value to compare.
+ * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
+ * @example
+ *
+ * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
+ * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
+ *
+ * moe == clone;
+ * // => false
+ *
+ * _.isEqual(moe, clone);
+ * // => true
+ */
+ function isEqual(value, other) {
+ return eq(value, other, []);
+ }
+
+ /**
+ * Checks if a `value` is a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
+ * @example
+ *
+ * _.isFinite(-101);
+ * // => true
+ *
+ * _.isFinite('10');
+ * // => false
+ *
+ * _.isFinite(Infinity);
+ * // => false
+ */
+ function isFinite(value) {
+ return isNumber(value) && nativeIsFinite(value);
+ }
+
+ /**
+ * Checks if a `value` is a function.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(''.concat);
+ * // => true
+ */
+ function isFunction(value) {
+ return toString.call(value) == '[object Function]';
+ }
+
+ /**
+ * Checks if a `value` is an object.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
+ */
+ function isObject(value) {
+ return value === Object(value);
+ }
+
+ /**
+ * Checks if a `value` is `NaN`.
+ * Note: this is not the same as native `isNaN`, which will return true for
+ * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
+ * @example
+ *
+ * _.isNaN(NaN);
+ * // => true
+ *
+ * isNaN(undefined);
+ * // => true
+ *
+ * _.isNaN(undefined);
+ * // => false
+ */
+ function isNaN(value) {
+ // `NaN` is the only value for which `===` is not reflexive.
+ return value !== value;
+ }
+
+ /**
+ * Checks if a `value` is `null`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
+ * @example
+ *
+ * _.isNull(null);
+ * // => true
+ *
+ * _.isNull(undefined);
+ * // => false
+ */
+ function isNull(value) {
+ return value === null;
+ }
+
+ /**
+ * Checks if a `value` is a number.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
+ * @example
+ *
+ * _.isNumber(8.4 * 5;
+ * // => true
+ */
+ function isNumber(value) {
+ return toString.call(value) == '[object Number]';
+ }
+
+ /**
+ * Checks if a `value` is a regular expression.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
+ * @example
+ *
+ * _.isRegExp(/moe/);
+ * // => true
+ */
+ function isRegExp(value) {
+ return toString.call(value) == '[object RegExp]';
+ }
+
+ /**
+ * Checks if a `value` is a string.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
+ * @example
+ *
+ * _.isString('moe');
+ * // => true
+ */
+ function isString(value) {
+ return toString.call(value) == '[object String]';
+ }
+
+ /**
+ * Checks if a `value` is `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ */
+ function isUndefined(value) {
+ return value === void 0;
+ }
+
+ /**
+ * Produces an array of the `object`'s enumerable own property names.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property names.
+ * @example
+ *
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => ['one', 'two', 'three']
+ */
+ function keys(object) {
+ if (object !== Object(object)) {
+ throw TypeError();
+ }
+ var result = [];
+ for (var key in object) {
+ if (hasOwnProperty.call(object, key)) {
+ result[result.length] = key;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an object composed of the specified properties. Property names may
+ * be specified as individual arguments or as arrays of property names.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to pluck.
+ * @param {Object} [prop1, prop2, ..] The properties to pick.
+ * @returns {Object} Returns an object composed of the picked properties.
+ * @example
+ *
+ * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
+ * // => { 'name': 'moe', 'age': 40 }
+ */
+ function pick(object) {
+ var result = {};
+ forEach(flatten(slice.call(arguments, 1)), function(key) {
+ if (key in object) result[key] = object[key];
+ });
+ return result;
+ }
+
+ /**
+ * Invokes `interceptor` with the `value` as the first argument, and then returns
+ * `value`. The primary purpose of this method is to "tap into" a method chain,
+ * in order to performoperations on intermediate results within the chain.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to pass to `callback`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {Mixed} Returns `value`.
+ * @example
+ *
+ * _.chain([1,2,3,200])
+ * .filter(function(num) { return num % 2 == 0; })
+ * .tap(alert)
+ * .map(function(num) { return num * num })
+ * .value();
+ * // => // [2, 200] (alerted)
+ * // => [4, 40000]
+ */
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+
+ /**
+ * Produces an array of the `object`'s enumerable own property values.
+ *
+ * @static
+ * @memberOf _
+ * @alias methods
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property values.
+ * @example
+ *
+ * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => [1, 2, 3]
+ */
+ function values(object) {
+ return map(object, identity);
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Escapes a string for insertion into HTML, replacing `&`, `<`, `>`, `"`, `'`,
+ * and `/` characters.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} string The string to escape.
+ * @returns {String} Returns the escaped string.
+ * @example
+ *
+ * _.escape('Curly, Larry & Moe');
+ * // => "Curly, Larry & Moe"
+ */
+ function escape(string) {
+ return (string + '').replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"')
+ .replace(/'/g, ''').replace(/\//g,'/');
+ }
+
+ /**
+ * This function simply returns the first argument passed to it.
+ * Note: It is used throughout Lodash as a default callback.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Mixed} value Any value.
+ * @returns {Mixed} Returns `value`.
+ * @example
+ *
+ * var moe = { 'name': 'moe' };
+ * moe === _.identity(moe);
+ * // => true
+ */
+ function identity(value) {
+ return value;
+ }
+
+ /**
+ * Adds functions properties of `object` to the `lodash` function and chainable
+ * wrapper.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Object} object The object of function properties to add to `lodash`.
+ * @example
+ *
+ * _.mixin({
+ * 'capitalize': function(string) {
+ * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+ * }
+ * });
+ *
+ * _.capitalize('curly');
+ * // => 'Curly'
+ *
+ * _('larry').capitalize();
+ * // => 'Larry'
+ */
+ function mixin(object) {
+ forEach(functions(object), function(name){
+ addToWrapper(name, lodash[name] = object[name]);
+ });
+ }
+
+ /**
+ * Reverts the '_' variable to its previous value and returns a reference to
+ * the `lodash` function.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @returns {Function} Returns the `lodash` function.
+ * @example
+ *
+ * var lodash = _.noConflict();
+ */
+ function noConflict() {
+ window['_'] = oldDash;
+ return this;
+ }
+
+ /**
+ * Resolves the value of `property` on `object`. If the property is a function
+ * it will be invoked and its result returned, else the property value is returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Object} object The object to inspect.
+ * @param {String} property The property to get the result of.
+ * @returns {Mixed} Returns the resolved.
+ * @example
+ *
+ * var object = {
+ * 'cheese': 'crumpets',
+ * 'stuff': function() {
+ * return 'nonsense';
+ * }
+ * };
+ *
+ * _.result(object, 'cheese');
+ * // => 'crumpets'
+ *
+ * _.result(object, 'stuff');
+ * // => 'nonsense'
+ */
+ function result(object, property) {
+ if (object == null) return null;
+ var value = object[property];
+ return isFunction(value) ? object[property]() : value;
+ }
+
+ /**
+ * Executes the `callback` function `n` times.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Number} n The number of times to execute the callback.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding for the callback.
+ * @example
+ *
+ * _.times(3, function() { genie.grantWish(); });
+ */
+ function times(n, callback, thisArg) {
+ for (var index = 0; index < n; index++) {
+ callback.call(thisArg, index);
+ }
+ }
+
+ /**
+ * Generates a unique id. If `prefix` is passed, the id will be appended to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} [prefix] The value to prefix the id with.
+ * @returns {Number|String} Returns a numeric id if no prefix is passed, else
+ * a string id may be returned.
+ * @example
+ *
+ * _.uniqueId('contact_');
+ * // => 'contact_104'
+ */
+ function uniqueId(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * JavaScript micro-templating, similar to John Resig's implementation.
+ * Lo-Dash templating handles arbitrary delimiters, preserves whitespace,
+ * and correctly escapes quotes within interpolated code.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} text The
+ * @param {Obect} data The
+ * @param {Object} settings
+ * @returns {String} Returns....
+ * @example
+ *
+ * var compiled = _.template('hello: <%= name %>');
+ * compiled({ 'name': 'moe' });
+ * // => 'hello: moe'
+ *
+ * var list = '% _.forEach(people, function(name) { %>
-
-
+
+
-
+
diff --git a/underscore.js b/underscore.js
deleted file mode 100644
index f6f7e2f23..000000000
--- a/underscore.js
+++ /dev/null
@@ -1,1059 +0,0 @@
-// Underscore.js 1.3.3
-// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore is freely distributable under the MIT license.
-// Portions of Underscore are inspired or borrowed from Prototype,
-// Oliver Steele's Functional, and John Resig's Micro-Templating.
-// For all details and documentation:
-// http://documentcloud.github.com/underscore
-
-(function() {
-
- // Baseline setup
- // --------------
-
- // Establish the root object, `window` in the browser, or `global` on the server.
- var root = this;
-
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
-
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
-
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
- // Create quick reference variables for speed access to core prototypes.
- var slice = ArrayProto.slice,
- unshift = ArrayProto.unshift,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
-
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
-
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) { return new wrapper(obj); };
-
- // Export the Underscore object for **Node.js**, with
- // backwards-compatibility for the old `require()` API. If we're in
- // the browser, add `_` as a global object via a string identifier,
- // for Closure Compiler "advanced" mode.
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root['_'] = _;
- }
-
- // Current version.
- _.VERSION = '1.3.3';
-
- // Collection Functions
- // --------------------
-
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (_.has(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- };
-
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = _.collect = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- if (obj.length === +obj.length) results.length = obj.length;
- return results;
- };
-
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError('Reduce of empty array with no initial value');
- return memo;
- };
-
- // The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var reversed = _.toArray(obj).reverse();
- if (context && !initial) iterator = _.bind(iterator, context);
- return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
- };
-
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
-
- // Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
- // Aliased as `select`.
- _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- each(obj, function(value, index, list) {
- if (!iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
-
- // Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
- // Aliased as `all`.
- _.every = _.all = function(obj, iterator, context) {
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
-
- // Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
- // Aliased as `any`.
- var any = _.some = _.any = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
-
- // Determine if a given value is included in the array or object using `===`.
- // Aliased as `contains`.
- _.include = _.contains = function(obj, target) {
- var found = false;
- if (obj == null) return found;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- found = any(obj, function(value) {
- return value === target;
- });
- return found;
- };
-
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- return _.map(obj, function(value) {
- return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
- });
- };
-
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- };
-
- // Return the maximum element or (element-based computation).
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
- if (!iterator && _.isEmpty(obj)) return -Infinity;
- var result = {computed : -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
- if (!iterator && _.isEmpty(obj)) return Infinity;
- var result = {computed : Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
-
- // Shuffle an array.
- _.shuffle = function(obj) {
- var shuffled = [], rand;
- each(obj, function(value, index, list) {
- rand = Math.floor(Math.random() * (index + 1));
- shuffled[index] = shuffled[rand];
- shuffled[rand] = value;
- });
- return shuffled;
- };
-
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, val, context) {
- var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- if (a === void 0) return 1;
- if (b === void 0) return -1;
- return a < b ? -1 : a > b ? 1 : 0;
- }), 'value');
- };
-
- // Groups the object's values by a criterion. Pass either a string attribute
- // to group by, or a function that returns the criterion.
- _.groupBy = function(obj, val) {
- var result = {};
- var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
- each(obj, function(value, index) {
- var key = iterator(value, index);
- (result[key] || (result[key] = [])).push(value);
- });
- return result;
- };
-
- // Use a comparator function to figure out at what index an object should
- // be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator) {
- iterator || (iterator = _.identity);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >> 1;
- iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
- }
- return low;
- };
-
- // Safely convert anything iterable into a real, live array.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (_.isArguments(obj)) return slice.call(obj);
- if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
- return _.values(obj);
- };
-
- // Return the number of elements in an object.
- _.size = function(obj) {
- return _.isArray(obj) ? obj.length : _.keys(obj).length;
- };
-
- // Array Functions
- // ---------------
-
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head` and `take`. The **guard** check
- // allows it to work with `_.map`.
- _.first = _.head = _.take = function(array, n, guard) {
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- };
-
- // Returns everything but the last entry of the array. Especcialy useful on
- // the arguments object. Passing **n** will return all the values in
- // the array, excluding the last N. The **guard** check allows it to work with
- // `_.map`.
- _.initial = function(array, n, guard) {
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
- };
-
- // Get the last element of an array. Passing **n** will return the last N
- // values in the array. The **guard** check allows it to work with `_.map`.
- _.last = function(array, n, guard) {
- if ((n != null) && !guard) {
- return slice.call(array, Math.max(array.length - n, 0));
- } else {
- return array[array.length - 1];
- }
- };
-
- // Returns everything but the first entry of the array. Aliased as `tail`.
- // Especially useful on the arguments object. Passing an **index** will return
- // the rest of the values in the array from that index onward. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = function(array, index, guard) {
- return slice.call(array, (index == null) || guard ? 1 : index);
- };
-
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, function(value){ return !!value; });
- };
-
- // Return a completely flattened version of an array.
- _.flatten = function(array, shallow) {
- return _.reduce(array, function(memo, value) {
- if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
- memo[memo.length] = value;
- return memo;
- }, []);
- };
-
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
-
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iterator) {
- var initial = iterator ? _.map(array, iterator) : array;
- var results = [];
- // The `isSorted` flag is irrelevant if the array only contains two elements.
- if (array.length < 3) isSorted = true;
- _.reduce(initial, function (memo, value, index) {
- if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
- memo.push(value);
- results.push(array[index]);
- }
- return memo;
- }, []);
- return results;
- };
-
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(_.flatten(arguments, true));
- };
-
- // Produce an array that contains every item shared between all the
- // passed-in arrays. (Aliased as "intersect" for back-compat.)
- _.intersection = _.intersect = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- };
-
- // Take the difference between one array and a number of other arrays.
- // Only the elements present in just the first array will remain.
- _.difference = function(array) {
- var rest = _.flatten(slice.call(arguments, 1), true);
- return _.filter(array, function(value){ return !_.include(rest, value); });
- };
-
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
- return results;
- };
-
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i, l;
- if (isSorted) {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
- for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
- return -1;
- };
-
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item) {
- if (array == null) return -1;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
- var i = array.length;
- while (i--) if (i in array && array[i] === item) return i;
- return -1;
- };
-
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
-
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
-
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
-
- return range;
- };
-
- // Function (ahem) Functions
- // ------------------
-
- // Reusable constructor function for prototype setting.
- var ctor = function(){};
-
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Binding with arguments is also known as `curry`.
- // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
- // We check for `func.bind` first, to fail fast when `func` is undefined.
- _.bind = function bind(func, context) {
- var bound, args;
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- if (!_.isFunction(func)) throw new TypeError;
- args = slice.call(arguments, 2);
- return bound = function() {
- if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
- ctor.prototype = func.prototype;
- var self = new ctor;
- var result = func.apply(self, args.concat(slice.call(arguments)));
- if (Object(result) === result) return result;
- return self;
- };
- };
-
- // Bind all of an object's methods to that object. Useful for ensuring that
- // all callbacks defined on an object belong to it.
- _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length == 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- };
-
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- };
-
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
- };
-
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
-
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time.
- _.throttle = function(func, wait) {
- var context, args, timeout, throttling, more, result;
- var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
- return function() {
- context = this; args = arguments;
- var later = function() {
- timeout = null;
- if (more) func.apply(context, args);
- whenDone();
- };
- if (!timeout) timeout = setTimeout(later, wait);
- if (throttling) {
- more = true;
- } else {
- result = func.apply(context, args);
- }
- whenDone();
- throttling = true;
- return result;
- };
- };
-
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds. If `immediate` is passed, trigger the function on the
- // leading edge, instead of the trailing.
- _.debounce = function(func, wait, immediate) {
- var timeout;
- return function() {
- var context = this, args = arguments;
- var later = function() {
- timeout = null;
- if (!immediate) func.apply(context, args);
- };
- if (immediate && !timeout) func.apply(context, args);
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- };
- };
-
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- return memo = func.apply(this, arguments);
- };
- };
-
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return function() {
- var args = [func].concat(slice.call(arguments, 0));
- return wrapper.apply(this, args);
- };
- };
-
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var funcs = arguments;
- return function() {
- var args = arguments;
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- };
-
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- if (times <= 0) return func();
- return function() {
- if (--times < 1) { return func.apply(this, arguments); }
- };
- };
-
- // Object Functions
- // ----------------
-
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
- return keys;
- };
-
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- return _.map(obj, _.identity);
- };
-
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
-
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- obj[prop] = source[prop];
- }
- });
- return obj;
- };
-
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj) {
- var result = {};
- each(_.flatten(slice.call(arguments, 1)), function(key) {
- if (key in obj) result[key] = obj[key];
- });
- return result;
- };
-
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- });
- return obj;
- };
-
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- if (!_.isObject(obj)) return obj;
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
-
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
-
- // Internal recursive comparison function.
- function eq(a, b, stack) {
- // Identical objects are equal. `0 === -0`, but they aren't identical.
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
- if (a === b) return a !== 0 || 1 / a == 1 / b;
- // A strict comparison is necessary because `null == undefined`.
- if (a == null || b == null) return a === b;
- // Unwrap any wrapped objects.
- if (a._chain) a = a._wrapped;
- if (b._chain) b = b._wrapped;
- // Invoke a custom `isEqual` method if one is provided.
- if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
- if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
- // Compare `[[Class]]` names.
- var className = toString.call(a);
- if (className != toString.call(b)) return false;
- switch (className) {
- // Strings, numbers, dates, and booleans are compared by value.
- case '[object String]':
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
- // equivalent to `new String("5")`.
- return a == String(b);
- case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
- // other numeric values.
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
- case '[object Date]':
- case '[object Boolean]':
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
- // millisecond representations. Note that invalid dates with millisecond representations
- // of `NaN` are not equivalent.
- return +a == +b;
- // RegExps are compared by their source patterns and flags.
- case '[object RegExp]':
- return a.source == b.source &&
- a.global == b.global &&
- a.multiline == b.multiline &&
- a.ignoreCase == b.ignoreCase;
- }
- if (typeof a != 'object' || typeof b != 'object') return false;
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
- var length = stack.length;
- while (length--) {
- // Linear search. Performance is inversely proportional to the number of
- // unique nested structures.
- if (stack[length] == a) return true;
- }
- // Add the first object to the stack of traversed objects.
- stack.push(a);
- var size = 0, result = true;
- // Recursively compare objects and arrays.
- if (className == '[object Array]') {
- // Compare array lengths to determine if a deep comparison is necessary.
- size = a.length;
- result = size == b.length;
- if (result) {
- // Deep compare the contents, ignoring non-numeric properties.
- while (size--) {
- // Ensure commutative equality for sparse arrays.
- if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
- }
- }
- } else {
- // Objects with different constructors are not equivalent.
- if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
- // Deep compare objects.
- for (var key in a) {
- if (_.has(a, key)) {
- // Count the expected number of properties.
- size++;
- // Deep compare each member.
- if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
- }
- }
- // Ensure that both objects contain the same number of properties.
- if (result) {
- for (key in b) {
- if (_.has(b, key) && !(size--)) break;
- }
- result = !size;
- }
- }
- // Remove the first object from the stack of traversed objects.
- stack.pop();
- return result;
- }
-
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- return eq(a, b, []);
- };
-
- // Is a given array, string, or object empty?
- // An "empty" object has no enumerable own-properties.
- _.isEmpty = function(obj) {
- if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (_.has(obj, key)) return false;
- return true;
- };
-
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType == 1);
- };
-
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) == '[object Array]';
- };
-
- // Is a given variable an object?
- _.isObject = function(obj) {
- return obj === Object(obj);
- };
-
- // Is a given variable an arguments object?
- _.isArguments = function(obj) {
- return toString.call(obj) == '[object Arguments]';
- };
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return !!(obj && _.has(obj, 'callee'));
- };
- }
-
- // Is a given value a function?
- _.isFunction = function(obj) {
- return toString.call(obj) == '[object Function]';
- };
-
- // Is a given value a string?
- _.isString = function(obj) {
- return toString.call(obj) == '[object String]';
- };
-
- // Is a given value a number?
- _.isNumber = function(obj) {
- return toString.call(obj) == '[object Number]';
- };
-
- // Is a given object a finite number?
- _.isFinite = function(obj) {
- return _.isNumber(obj) && isFinite(obj);
- };
-
- // Is the given value `NaN`?
- _.isNaN = function(obj) {
- // `NaN` is the only value for which `===` is not reflexive.
- return obj !== obj;
- };
-
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
- };
-
- // Is a given value a date?
- _.isDate = function(obj) {
- return toString.call(obj) == '[object Date]';
- };
-
- // Is the given value a regular expression?
- _.isRegExp = function(obj) {
- return toString.call(obj) == '[object RegExp]';
- };
-
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
-
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Has own property?
- _.has = function(obj, key) {
- return hasOwnProperty.call(obj, key);
- };
-
- // Utility Functions
- // -----------------
-
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
-
- // Keep the identity function around for default iterators.
- _.identity = function(value) {
- return value;
- };
-
- // Run a function **n** times.
- _.times = function (n, iterator, context) {
- for (var i = 0; i < n; i++) iterator.call(context, i);
- };
-
- // Escape a string for HTML interpolation.
- _.escape = function(string) {
- return (''+string).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
- };
-
- // If the value of the named property is a function then invoke it;
- // otherwise, return it.
- _.result = function(object, property) {
- if (object == null) return null;
- var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- };
-
- // Add your own custom functions to the Underscore object, ensuring that
- // they're correctly added to the OOP wrapper as well.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- addToWrapper(name, _[name] = obj[name]);
- });
- };
-
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = idCounter++;
- return prefix ? prefix + id : id;
- };
-
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g,
- escape : /<%-([\s\S]+?)%>/g
- };
-
- // When customizing `templateSettings`, if you don't want to define an
- // interpolation, evaluation or escaping regex, we need one that is
- // guaranteed not to match.
- var noMatch = /.^/;
-
- // Certain characters need to be escaped so that they can be put into a
- // string literal.
- var escapes = {
- '\\': '\\',
- "'": "'",
- 'r': '\r',
- 'n': '\n',
- 't': '\t',
- 'u2028': '\u2028',
- 'u2029': '\u2029'
- };
-
- for (var p in escapes) escapes[escapes[p]] = p;
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
- var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
-
- // Within an interpolation, evaluation, or escaping, remove HTML escaping
- // that had been previously added.
- var unescape = function(code) {
- return code.replace(unescaper, function(match, escape) {
- return escapes[escape];
- });
- };
-
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- _.template = function(text, data, settings) {
- settings = _.defaults(settings || {}, _.templateSettings);
-
- // Compile the template source, taking care to escape characters that
- // cannot be included in a string literal and then unescape them in code
- // blocks.
- var source = "__p+='" + text
- .replace(escaper, function(match) {
- return '\\' + escapes[match];
- })
- .replace(settings.escape || noMatch, function(match, code) {
- return "'+\n_.escape(" + unescape(code) + ")+\n'";
- })
- .replace(settings.interpolate || noMatch, function(match, code) {
- return "'+\n(" + unescape(code) + ")+\n'";
- })
- .replace(settings.evaluate || noMatch, function(match, code) {
- return "';\n" + unescape(code) + "\n;__p+='";
- }) + "';\n";
-
- // If a variable is not specified, place data values in local scope.
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
- source = "var __p='';" +
- "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
- source + "return __p;\n";
-
- var render = new Function(settings.variable || 'obj', '_', source);
- if (data) return render(data, _);
- var template = function(data) {
- return render.call(this, data, _);
- };
-
- // Provide the compiled function source as a convenience for build time
- // precompilation.
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
- source + '}';
-
- return template;
- };
-
- // Add a "chain" function, which will delegate to the wrapper.
- _.chain = function(obj) {
- return _(obj).chain();
- };
-
- // The OOP Wrapper
- // ---------------
-
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
- var wrapper = function(obj) { this._wrapped = obj; };
-
- // Expose `wrapper.prototype` as `_.prototype`
- _.prototype = wrapper.prototype;
-
- // Helper function to continue chaining intermediate results.
- var result = function(obj, chain) {
- return chain ? _(obj).chain() : obj;
- };
-
- // A method to easily add functions to the OOP wrapper.
- var addToWrapper = function(name, func) {
- wrapper.prototype[name] = function() {
- var args = slice.call(arguments);
- unshift.call(args, this._wrapped);
- return result(func.apply(_, args), this._chain);
- };
- };
-
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
-
- // Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- var wrapped = this._wrapped;
- method.apply(wrapped, arguments);
- var length = wrapped.length;
- if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
- return result(wrapped, this._chain);
- };
- });
-
- // Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- return result(method.apply(this._wrapped, arguments), this._chain);
- };
- });
-
- // Start chaining a wrapped Underscore object.
- wrapper.prototype.chain = function() {
- this._chain = true;
- return this;
- };
-
- // Extracts the result from a wrapped and chained object.
- wrapper.prototype.value = function() {
- return this._wrapped;
- };
-
-}).call(this);