Compare commits

..

21 Commits
0.4.1 ... 0.4.2

Author SHA1 Message Date
John-David Dalton
5defe7d975 Bump to v0.4.2.
Former-commit-id: 48638d63970b9d4300661620b881ea34854d24d2
2012-07-16 14:34:48 -04:00
John-David Dalton
7e79903fe8 Update tests to work around QUnit 1.9.0 bug in Narwhal/older-Firefox and add platform.js to test/index.html.
Former-commit-id: eed8246c795735558ba9f499b86f08ed3970ccaf
2012-07-16 13:58:36 -04:00
John-David Dalton
a2fa52504c Ensure stringClass isn't stripped out when needed for certain builds and update dependencies for arrayClass, funcClass, objectTypes, and reNative.
Former-commit-id: 334973dcab4660733e1d081efe3602a167c452d9
2012-07-15 07:01:44 -04:00
John-David Dalton
2629f85e73 Update minified build and rebuild documentation.
Former-commit-id: 5b434ca8c22a44d1603dcc1e92bf4caea6fe00a1
2012-07-15 03:52:22 -04:00
John-David Dalton
8577816234 Add optimizations for large arrays to _.difference, _.intersection, and _.without.
Former-commit-id: 26d55a6a3340e77b5269b2003d20def3fe77bca9
2012-07-15 03:51:28 -04:00
John-David Dalton
e58d47a3b2 Add "strict" build.
Former-commit-id: fcdd8d36c9e0c6d698059541b97915ae1b28650e
2012-07-14 08:59:50 -04:00
John-David Dalton
c9c83ee7e6 Add _.invoke benchmark to perf.js and a link to the compatibility changes wiki entry in README.md.
Former-commit-id: 51296709ea8d9dd6e951530b9874b90af3c764a2
2012-07-14 06:21:59 -04:00
John-David Dalton
139693dce6 Optimize benchmark setups, cleanup perf/index.html, and add platform.js.
Former-commit-id: 228b7b6fd230638f9ec8c79eafa56506fc84b79a
2012-07-14 04:51:50 -04:00
John-David Dalton
f98193d822 Poll until Firebug-lite is loaded.
Former-commit-id: c568ed963fc5716c2c84d63aba45a8ef258c1e7b
2012-07-13 14:41:21 -04:00
John-David Dalton
8052f1ac9d Revert unstable Closure Compiler.
Former-commit-id: 81716f0c269ac8a5befbf584c0dc964777cc1e1a
2012-07-13 04:33:50 -04:00
John-David Dalton
4f78a06993 Add _.isEqual benchmarks.
Former-commit-id: 5b3ee06ea3f31f10e8fac96da8766cc1c4c2d3bb
2012-07-13 04:17:38 -04:00
John-David Dalton
6c4b4b392b Avoid expensive test setup in perf.js.
Former-commit-id: f1c1ed41cb86c83aba2c3f7da1dedf6a280221ad
2012-07-12 18:19:23 -04:00
John-David Dalton
268fe34238 Update Closure Compiler.
Former-commit-id: bfdbe43546f3861cbeaaa99644af68e95f2175d5
2012-07-12 16:54:17 -04:00
John-David Dalton
cc620205d6 Control "use strict" directive use in builds.
Former-commit-id: 66a9bdee5cc61710d7d42d685feba616ec855322
2012-07-12 16:25:30 -04:00
John-David Dalton
f0d7c97b7b Update test-ui.js to better integrate with QUnit 1.9.0.
Former-commit-id: 7e6083ebb54fde0ebaa9f4f4551bb190e602a370
2012-07-12 15:48:52 -04:00
John-David Dalton
660a6e9e4c Update minified build and rebuild documentation.
Former-commit-id: 6e747961d3d756d016a27b530bf961841a93bd00
2012-07-12 15:27:25 -04:00
John-David Dalton
3386c2a7a5 Avoid enforcing strict mode in _.defaults, _.extend, and _.bindAll and add benchmarks for _.bindAll and _.functions. [closes #45]
Former-commit-id: 1bb0b5155d3ae46052b4a06cb538dff307e8ec5e
2012-07-12 15:25:18 -04:00
John-David Dalton
9530efb4d4 Update vendor folder.
Former-commit-id: 363508c8d79afa1ec8c1aba48b5be58a8a572367
2012-07-12 13:32:48 -04:00
John-David Dalton
4293515b3d Add help and version options to build.js.
Former-commit-id: 95a9fdaa7a00550922e71ce01a3f742b845d082c
2012-07-12 13:31:42 -04:00
John-David Dalton
61105e0679 Cleanup inline documentation.
Former-commit-id: 1fa95d45c2c3d1fe50f5827f4743aad3c8b75f95
2012-07-12 03:27:15 -04:00
John-David Dalton
79a289c7e2 Update CDN copy link.
Former-commit-id: 4d0d26292eef227f343f6b482856482f8f554a43
2012-07-12 02:06:55 -04:00
23 changed files with 4390 additions and 629 deletions

View File

@@ -1,14 +1,14 @@
# Lo-Dash <sup>v0.4.1</sup>
# Lo-Dash <sup>v0.4.2</sup>
A drop-in replacement for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), that delivers [performance improvements](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#closed-underscorejs-issues), and [additional features](https://github.com/bestiejs/lodash#features).
A drop-in replacement<sup>[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer)</sup> for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), that delivers [performance improvements](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#closed-underscorejs-issues), and [additional features](https://github.com/bestiejs/lodash#features).
Lo-Dashs performance is gained by avoiding slower native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
## Download
* [Development source](https://raw.github.com/bestiejs/lodash/v0.4.1/lodash.js)
* [Production source](https://raw.github.com/bestiejs/lodash/v0.4.1/lodash.min.js)
* CDN copies of ≤ [v0.3.2](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.3.2/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
* [Development source](https://raw.github.com/bestiejs/lodash/v0.4.2/lodash.js)
* [Production source](https://raw.github.com/bestiejs/lodash/v0.4.2/lodash.min.js)
* CDN copies of ≤ [v0.4.1](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.4.1/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
* For optimal performance, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
## Dive in
@@ -64,6 +64,11 @@ lodash legacy
* Mobile builds, with IE < 9 bug fixes and method compilation removed, may be created using the `mobile` modifier argument.
~~~ bash
lodash mobile
~~~
* Strict builds, with `_.bindAll`, `_.extend`, and `_.defaults` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.
~~~ bash
lodash strict
~~~
Custom builds may be created in three ways:
@@ -75,23 +80,23 @@ lodash category=collections,functions
lodash category="collections, functions"
~~~
2. Use the `include` argument to pass the names of methods to include in the build.
~~~ bash
lodash include=each,filter,map
lodash include="each, filter, map"
~~~
3. Use the `exclude` argument to pass the names of methods to exclude from the build.
2. Use the `exclude` argument to pass the names of methods to exclude from the build.
~~~ bash
lodash exclude=union,uniq,zip
lodash exclude="union, uniq, zip"
~~~
All arguments, except `include` with `exclude` and `mobile` with `legacy`, may be combined.
3. Use the `include` argument to pass the names of methods to include in the build.
~~~ bash
lodash include=each,filter,map
lodash include="each, filter, map"
~~~
All arguments, except `exclude` with `include` and `legacy` with `mobile`, may be combined.
~~~ bash
lodash backbone mobile category=functions include=pick,uniq
lodash backbone legacy category=utilities exclude=first,last
lodash backbone mobile strict category=functions include=pick,uniq
~~~
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
@@ -146,29 +151,29 @@ require({
## Closed Underscore.js issues <sup>(20+)</sup>
* Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L306-312)]
* Ensure array-like objects with invalid `length` properties are treated like regular objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L257-263), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L607-621), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L863-866)]
* Ensure *"Arrays"* methods allow falsey `array` arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L931-970)]
* Ensure *"Collections"* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L265-283), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L623-640), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L868-871)]
* Ensure templates compiled with errors are inspectable [[#666](https://github.com/documentcloud/underscore/issues/666), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L737-744)]
* Fix cross-browser object iteration bugs [[#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L195-207), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L317-342), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L438-449), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L457-459), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L477-497), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L667-669)]
* Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L364-370)]
* Ensure array-like objects with invalid `length` properties are treated like regular objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L315-321), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L665-679), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L921-924)]
* Ensure *"Arrays"* methods allow falsey `array` arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L989-1027)]
* Ensure *"Collections"* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L148-157), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L323-341), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L681-698), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L926-929)]
* Ensure templates compiled with errors are inspectable [[#666](https://github.com/documentcloud/underscore/issues/666), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L795-802)]
* Fix cross-browser object iteration bugs [[#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L224-236), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L375-400), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L496-507), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L515-517), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L535-555), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L725-727)]
* Handle arrays with `undefined` values correctly in IE < 9 [[#601](https://github.com/documentcloud/underscore/issues/601)]
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L86-92)]
* Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L70-84)]
* `_(…)` should return passed wrapper instances [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L104-107)]
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L138-147)]
* `_.escape` should return an empty string when passed `null` or `undefined` [[#407](https://github.com/documentcloud/underscore/issues/427), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L176-179)]
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L252-255)]
* `_.groupBy` should add values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L357-364)]
* `_isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L467-469)]
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L591-605)]
* `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L650-652)]
* `_.size` shouldn't error on falsey values [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L654-661)]
* `_.size` should work with `arguments` objects cross-browser [[#653](https://github.com/documentcloud/underscore/issues/653), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L663-665)]
* `_.sortedIndex` should support arrays with high `length` values [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L707-716)]
* `_.template` should not augment the `options` object [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L731-735)]
* `_.throttle` should work when called in a tight loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L814-824)]
* `_.zipObject` should accept less than two arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.1/test/test.js#L893-895)]
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L96-102)]
* Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L80-94)]
* `_(…)` should return passed wrapper instances [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L114-117)]
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L148-157)]
* `_.escape` should return an empty string when passed `null` or `undefined` [[#407](https://github.com/documentcloud/underscore/issues/427), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L205-208)]
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L310-313)]
* `_.groupBy` should add values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L415-422)]
* `_isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L525-527)]
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L649-663)]
* `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L708-710)]
* `_.size` shouldn't error on falsey values [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L712-719)]
* `_.size` should work with `arguments` objects cross-browser [[#653](https://github.com/documentcloud/underscore/issues/653), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L721-723)]
* `_.sortedIndex` should support arrays with high `length` values [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L765-774)]
* `_.template` should not augment the `options` object [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L789-793)]
* `_.throttle` should work when called in a loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L872-882)]
* `_.zipObject` should accept less than two arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L951-953)]
## Optimized methods <sup>(50+)</sup>
@@ -233,6 +238,13 @@ require({
## Release Notes
### <sup>v0.4.2</sup>
* Added `strict` build
* Ensured `_.bindAll`, `_.extend`, and `_.defaults` avoid strict mode errors when attempting to augment read-only properties
* Optimized the iteration of large arrays in `_.difference`, `_.intersection`, and `_.without`
* Fixed build bugs related to removing variables
### <sup>v0.4.1</sup>
* Fixed `_.template` regression

155
build.js
View File

@@ -20,6 +20,15 @@
/** Flag used to specify a mobile build */
var isMobile = !isLegacy && process.argv.indexOf('mobile') > -1;
/**
* Flag used to specify `_.bindAll`, `_.extend`, and `_.defaults` are
* constructed using the "use strict" directive.
*/
var isStrict = process.argv.indexOf('strict') > -1;
/** Flag used to specify if the build should include the "use strict" directive */
var useStrict = isStrict || !(isLegacy || isMobile);
/** Shortcut used to convert array-like objects to arrays */
var slice = [].slice;
@@ -30,6 +39,14 @@
var lodash = (function() {
var sandbox = {};
if (isStrict) {
source = setUseStrictOption(source, true);
}
else if (!useStrict) {
source = removeUseStrictDirective(source);
source = setUseStrictOption(source, false);
}
if (isLegacy) {
['isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'].forEach(function(varName) {
source = replaceVar(source, varName, 'false');
@@ -224,13 +241,13 @@
'inLoop',
'init',
'isKeysFast',
'iteratee',
'object',
'objectBranch',
'noCharByIndex',
'shadowed',
'top',
'useHas'
'useHas',
'useStrict'
];
/** Collections of method names */
@@ -261,6 +278,34 @@
/*--------------------------------------------------------------------------*/
/**
* Logs the help message to the console.
*
* @private
*/
function displayHelp() {
console.log([
'',
' Commands:',
'',
' lodash backbone Build containing all methods required by Backbone',
' lodash legacy Build tailored for older browsers without ES5 support',
' lodash mobile Build with IE < 9 bug fixes and method compilation removed',
' lodash strict Build with `_.bindAll`, `_.extend`, and `_.defaults` in strict mode',
' lodash category=... Comma separated categories of methods to include in the build',
' lodash exclude=... Comma separated names of methods to exclude from the build',
' lodash include=... Comma separated names of methods to include in the build',
'',
' All arguments, except `exclude` with `include` and `legacy` with `mobile`, may be combined.',
'',
' Options:',
'',
' -h, --help Display help information',
' -V, --version Output current version of Lo-Dash',
''
].join('\n'));
}
/**
* Gets the aliases associated with a given function name.
*
@@ -469,14 +514,25 @@
*/
function removeKeysOptimization(source) {
return removeVar(source, 'isKeysFast')
// remove optimized branch in `iteratorTemplate`
.replace(/(?: *\/\/.*\n)*\s*'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, '$2')
// remove `isKeysFast` from `beforeLoop.object` of `mapIteratorOptions`
.replace(/=\s*'\s*\+\s*\(isKeysFast.+/, "= []'")
// remove `isKeysFast` from `inLoop.object` of `mapIteratorOptions`, `invoke`, `pluck`, and `sortBy`
.replace(/'\s*\+\s*\(isKeysFast[^)]+?\)\s*\+\s*'/g, '.push')
// remove data object property assignment in `createIterator`
.replace(/\s*.+?\.isKeysFast *=.+/, '')
// remove optimized branch in `iteratorTemplate`
.replace(/(?: *\/\/.*\n)*\s*'( *)<% *if *\(isKeysFast[\s\S]+?'\1<% *} *else *\{ *%>.+\n([\s\S]+?) *'\1<% *} *%>.+/, '$2');
.replace(/\s*.+?\.isKeysFast *=.+/, '');
}
/**
* Removes the "use strict" directive from `source`.
*
* @private
* @param {String} source The source to process.
* @returns {String} Returns the modified source.
*/
function removeUseStrictDirective(source) {
return source.replace(/(["'])use strict\1;( *\n)?/, '');
}
/**
@@ -535,6 +591,42 @@
return source;
}
/**
* Hard-codes the `useStrict` template option value for `iteratorTemplate`.
*
* @private
* @param {String} source The source to process.
* @param {Boolean} value The value to set.
* @returns {String} Returns the modified source.
*/
function setUseStrictOption(source, value) {
return source
// replace `useStrict` branch in `value` with hard-coded option
.replace(/(?: *\/\/.*\n)*(\s*)' *<% *if *\(useStrict\).+/, value ? "$1'\\'use strict\\';\\n' +" : '')
// remove `useStrict` from iterator options
.replace(/ *'useStrict': *false,\n/g, '')
// remove `useStrict` data object property assignment in `createIterator`
.replace(/\s*.+?\.useStrict *=.+/, '');
}
/*--------------------------------------------------------------------------*/
// display help message
if (lodash.find(process.argv, function(arg) {
return /^(?:-h|--help)$/.test(arg);
})) {
displayHelp();
process.exit();
}
// display `lodash.VERSION`
if (lodash.find(process.argv, function(arg) {
return /^(?:-V|--version)$/.test(arg);
})) {
console.log(lodash.VERSION);
process.exit();
}
/*--------------------------------------------------------------------------*/
// Backbone build
@@ -796,13 +888,7 @@
// prepend data object references to property names to avoid having to
// use a with-statement
iteratorOptions.forEach(function(property) {
if (property == 'iteratee') {
// use a more fine-grained regexp for the `iteratee` property because
// it's a compiled variable as well as a data property
snippet = snippet.replace(/(__t *= *\( *)(iteratee)/, '$1obj.$2');
} else {
snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
}
snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property);
});
// remove unnecessary code
@@ -833,6 +919,16 @@
/*--------------------------------------------------------------------------*/
// remove associated functions, variables, and code snippets that the minifier may miss
if (isRemoved(source, 'bind')) {
source = removeVar(source, 'nativeBind');
source = removeVar(source, 'isBindFast');
}
if (isRemoved(source, 'isArray')) {
source = removeVar(source, 'nativeIsArray');
}
if (isRemoved(source, 'keys')) {
source = removeFunction(source, 'shimKeys');
}
if (isRemoved(source, 'mixin')) {
// remove `LoDash` constructor
source = removeFunction(source, 'LoDash');
@@ -851,37 +947,27 @@
if (isRemoved(source, 'toArray')) {
source = removeVar(source, 'noArraySliceOnStrings');
}
if (isRemoved(source, 'isArray', 'isEmpty', 'isEqual', 'size')) {
if (isRemoved(source, 'isArray', 'isEmpty', 'isEqual')) {
source = removeVar(source, 'arrayClass');
}
if (isRemoved(source, 'bind', 'functions', 'groupBy', 'invoke', 'isEqual', 'isFunction', 'result', 'sortBy', 'toArray')) {
if (isRemoved(source, 'bind', 'bindAll', 'functions', 'isEqual', 'isFunction', 'result', 'toArray')) {
source = removeVar(source, 'funcClass');
}
if (isRemoved(source, 'bind')) {
source = removeVar(source, 'nativeBind');
source = removeVar(source, 'isBindFast');
}
if (isRemoved(source, 'isArray')) {
source = removeVar(source, 'nativeIsArray');
}
if (isRemoved(source, 'keys')) {
source = removeFunction(source, 'shimKeys');
}
if (isRemoved(source, 'clone', 'isObject', 'keys')) {
if (isRemoved(source, 'bind', 'clone', 'isObject', 'keys')) {
source = removeVar(source, 'objectTypes');
}
if (isRemoved(source, 'bind', 'isArray', 'keys')) {
source = removeVar(source, 'reNative');
}
if (isRemoved(source, 'isEmpty', 'isEqual', 'isString', 'size')) {
source = removeVar(source, 'stringClass');
}
if ((source.match(/\bcreateIterator\b/g) || []).length < 2) {
source = removeFunction(source, 'createIterator');
}
if (isRemoved(source, 'createIterator', 'bind', 'isArray', 'keys')) {
source = removeVar(source, 'reNative');
}
if (isRemoved(source, 'createIterator', 'extend', 'isEqual')) {
source = removeVar(source, 'hasDontEnumBug');
}
if (isRemoved(source, 'createIterator', 'contains', 'isEmpty', 'isEqual', 'isString')) {
source = removeVar(source, 'stringClass');
}
if (isRemoved(source, 'createIterator', 'keys')) {
source = removeVar(source, 'nativeKeys');
}
@@ -901,9 +987,14 @@
source = source.replace(/^ *;\n/gm, '');
// begin the minification process
if (filterType || isBackbone || isLegacy || isMobile) {
if (filterType || isBackbone || isLegacy || isMobile || isStrict) {
fs.writeFileSync(path.join(cwd, 'lodash.custom.js'), source);
minify(source, 'lodash.custom.min', function(result) {
// re-remove "use strict" added by the minifier
if (!useStrict) {
result = removeUseStrictDirective(result);
}
fs.writeFileSync(path.join(cwd, 'lodash.custom.min.js'), result);
});
}

View File

@@ -34,9 +34,6 @@
// move vars exposed by Closure Compiler into the IIFE
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
// use double quotes consistently
source = source.replace(/'use strict'/, '"use strict"');
// unescape properties (i.e. foo["bar"] => foo.bar)
source = source.replace(/(\w)\["([^."]+)"\]/g, '$1.$2');

View File

@@ -10,17 +10,20 @@
'accumulator',
'args',
'arrayClass',
'bind',
'callback',
'className',
'collection',
'compareAscending',
'ctor',
'funcClass',
'funcs',
'hasOwnProperty',
'identity',
'index',
'isFunc',
'iteratee',
'iterateeIndex',
'iteratorBind',
'length',
'methodName',
@@ -36,8 +39,6 @@
'result',
'skipProto',
'slice',
'source',
'sourceIndex',
'stringClass',
'target',
'thisArg',
@@ -58,13 +59,13 @@
'inLoop',
'init',
'isKeysFast',
'iteratee',
'object',
'objectBranch',
'noCharByIndex',
'shadowed',
'top',
'useHas'
'useHas',
'useStrict'
];
/** Used to minify variables and string values to a single character */

View File

@@ -1,4 +1,4 @@
# Lo-Dash <sup>v0.4.1</sup>
# Lo-Dash <sup>v0.4.2</sup>
<!-- div -->
@@ -148,7 +148,7 @@ The `lodash` function.
<!-- div -->
### <a id="_version"></a>`_.VERSION`
<a href="#_version">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3563 "View in source") [&#x24C9;][1]
<a href="#_version">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3608 "View in source") [&#x24C9;][1]
*(String)*: The semantic version number.
@@ -160,7 +160,7 @@ The `lodash` function.
<!-- div -->
### <a id="_aftern-func"></a>`_.after(n, func)`
<a href="#_aftern-func">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1946 "View in source") [&#x24C9;][1]
<a href="#_aftern-func">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1985 "View in source") [&#x24C9;][1]
Creates a new function that is restricted to executing only after it is called `n` times.
@@ -188,7 +188,7 @@ _.forEach(notes, function(note) {
<!-- div -->
### <a id="_bindfunc--thisarg-arg1-arg2-"></a>`_.bind(func [, thisArg, arg1, arg2, ...])`
<a href="#_bindfunc--thisarg-arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2000 "View in source") [&#x24C9;][1]
<a href="#_bindfunc--thisarg-arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2039 "View in source") [&#x24C9;][1]
Creates a new function that, when called, invokes `func` with the `this` binding of `thisArg` and prepends any additional `bind` arguments to those passed to the bound function. Lazy defined methods may be bound by passing the object they are bound to as `func` and the method name as `thisArg`.
@@ -239,7 +239,7 @@ func();
<!-- div -->
### <a id="_bindallobject--methodname1-methodname2-"></a>`_.bindAll(object [, methodName1, methodName2, ...])`
<a href="#_bindallobject--methodname1-methodname2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2070 "View in source") [&#x24C9;][1]
<a href="#_bindallobject--methodname1-methodname2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2109 "View in source") [&#x24C9;][1]
Binds methods on `object` to `object`, overwriting the existing method. If no method names are provided, all the function properties of `object` will be bound.
@@ -270,7 +270,7 @@ jQuery('#lodash_button').on('click', buttonView.onClick);
<!-- div -->
### <a id="_chainvalue"></a>`_.chain(value)`
<a href="#_chainvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3488 "View in source") [&#x24C9;][1]
<a href="#_chainvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3533 "View in source") [&#x24C9;][1]
Wraps the value in a `lodash` wrapper object.
@@ -304,7 +304,7 @@ var youngest = _.chain(stooges)
<!-- div -->
### <a id="_clonevalue"></a>`_.clone(value)`
<a href="#_clonevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2396 "View in source") [&#x24C9;][1]
<a href="#_clonevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2439 "View in source") [&#x24C9;][1]
Create a shallow clone of the `value`. Any nested objects or arrays will be assigned by reference and not cloned.
@@ -328,7 +328,7 @@ _.clone({ 'name': 'moe' });
<!-- div -->
### <a id="_compactarray"></a>`_.compact(array)`
<a href="#_compactarray">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1193 "View in source") [&#x24C9;][1]
<a href="#_compactarray">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1227 "View in source") [&#x24C9;][1]
Produces a new array with all falsey values of `array` removed. The values `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
@@ -352,7 +352,7 @@ _.compact([0, 1, false, 2, '', 3]);
<!-- div -->
### <a id="_composefunc1-func2-"></a>`_.compose([func1, func2, ...])`
<a href="#_composefunc1-func2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2102 "View in source") [&#x24C9;][1]
<a href="#_composefunc1-func2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2145 "View in source") [&#x24C9;][1]
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 the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
@@ -379,7 +379,7 @@ welcome('moe');
<!-- div -->
### <a id="_containscollection-target"></a>`_.contains(collection, target)`
<a href="#_containscollection-target">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L719 "View in source") [&#x24C9;][1]
<a href="#_containscollection-target">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L762 "View in source") [&#x24C9;][1]
Checks if a given `target` value is present in a `collection` using strict equality for comparisons, i.e. `===`.
@@ -410,7 +410,7 @@ _.contains('curly', 'ur');
<!-- div -->
### <a id="_debouncefunc-wait-immediate"></a>`_.debounce(func, wait, immediate)`
<a href="#_debouncefunc-wait-immediate">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2135 "View in source") [&#x24C9;][1]
<a href="#_debouncefunc-wait-immediate">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2178 "View in source") [&#x24C9;][1]
Creates a new function that will delay the execution of `func` until after `wait` milliseconds have elapsed since the last time it was invoked. Pass `true` for `immediate` to cause debounce to invoke `func` on the leading, instead of the trailing, edge of the `wait` timeout. Subsequent calls to the debounced function will return the result of the last `func` call.
@@ -436,7 +436,7 @@ jQuery(window).on('resize', lazyLayout);
<!-- div -->
### <a id="_defaultsobject--defaults1-defaults2-"></a>`_.defaults(object [, defaults1, defaults2, ...])`
<a href="#_defaultsobject--defaults1-defaults2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2419 "View in source") [&#x24C9;][1]
<a href="#_defaultsobject--defaults1-defaults2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2462 "View in source") [&#x24C9;][1]
Assigns missing properties on `object` with default values from the defaults objects. Once a property is set, additional defaults of the same property will be ignored.
@@ -462,7 +462,7 @@ _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
<!-- div -->
### <a id="_deferfunc--arg1-arg2-"></a>`_.defer(func [, arg1, arg2, ...])`
<a href="#_deferfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2200 "View in source") [&#x24C9;][1]
<a href="#_deferfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2243 "View in source") [&#x24C9;][1]
Defers executing the `func` function until the current call stack has cleared. Additional arguments are passed to `func` when it is invoked.
@@ -487,7 +487,7 @@ _.defer(function() { alert('deferred'); });
<!-- div -->
### <a id="_delayfunc-wait--arg1-arg2-"></a>`_.delay(func, wait [, arg1, arg2, ...])`
<a href="#_delayfunc-wait--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2180 "View in source") [&#x24C9;][1]
<a href="#_delayfunc-wait--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2223 "View in source") [&#x24C9;][1]
Executes the `func` function after `wait` milliseconds. Additional arguments are passed to `func` when it is invoked.
@@ -514,7 +514,7 @@ _.delay(log, 1000, 'logged later');
<!-- div -->
### <a id="_differencearray--array1-array2-"></a>`_.difference(array [, array1, array2, ...])`
<a href="#_differencearray--array1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1225 "View in source") [&#x24C9;][1]
<a href="#_differencearray--array1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1259 "View in source") [&#x24C9;][1]
Produces a new array of `array` values not present in the other arrays using strict equality for comparisons, i.e. `===`.
@@ -539,7 +539,7 @@ _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
<!-- div -->
### <a id="_escapestring"></a>`_.escape(string)`
<a href="#_escapestring">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3128 "View in source") [&#x24C9;][1]
<a href="#_escapestring">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3173 "View in source") [&#x24C9;][1]
Escapes a string for inclusion in HTML, replacing `&`, `<`, `"`, and `'` characters.
@@ -563,9 +563,9 @@ _.escape('Curly, Larry & Moe');
<!-- div -->
### <a id="_everycollection--callbackidentity-thisarg"></a>`_.every(collection [, callback=identity, thisArg])`
<a href="#_everycollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L748 "View in source") [&#x24C9;][1]
<a href="#_everycollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L790 "View in source") [&#x24C9;][1]
Checks if the `callback` returns a truthy value for **all** elements of a `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
Checks if the `callback` returns a truthy value for **all** elements of a `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -589,7 +589,7 @@ _.every([true, 1, null, 'yes'], Boolean);
<!-- div -->
### <a id="_extendobject--source1-source2-"></a>`_.extend(object [, source1, source2, ...])`
<a href="#_extendobject--source1-source2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2438 "View in source") [&#x24C9;][1]
<a href="#_extendobject--source1-source2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2481 "View in source") [&#x24C9;][1]
Copies enumerable properties from the source objects to the `destination` object. Subsequent sources will overwrite propery assignments of previous sources.
@@ -614,9 +614,9 @@ _.extend({ 'name': 'moe' }, { 'age': 40 });
<!-- div -->
### <a id="_filtercollection--callbackidentity-thisarg"></a>`_.filter(collection [, callback=identity, thisArg])`
<a href="#_filtercollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L769 "View in source") [&#x24C9;][1]
<a href="#_filtercollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L810 "View in source") [&#x24C9;][1]
Examines each value in a `collection`, returning an array of all values the `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
Examines each value in a `collection`, returning an array of all values the `callback` returns truthy for. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -640,9 +640,9 @@ var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; })
<!-- div -->
### <a id="_findcollection-callback--thisarg"></a>`_.find(collection, callback [, thisArg])`
<a href="#_findcollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L791 "View in source") [&#x24C9;][1]
<a href="#_findcollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L831 "View in source") [&#x24C9;][1]
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 bound to `thisArg` and invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
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 bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -666,7 +666,7 @@ var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
<!-- div -->
### <a id="_firstarray--n-guard"></a>`_.first(array [, n, guard])`
<a href="#_firstarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1261 "View in source") [&#x24C9;][1]
<a href="#_firstarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1296 "View in source") [&#x24C9;][1]
Gets the first value of the `array`. Pass `n` to return the first `n` values of the `array`.
@@ -692,7 +692,7 @@ _.first([5, 4, 3, 2, 1]);
<!-- div -->
### <a id="_flattenarray-shallow"></a>`_.flatten(array, shallow)`
<a href="#_flattenarray-shallow">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1285 "View in source") [&#x24C9;][1]
<a href="#_flattenarray-shallow">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1320 "View in source") [&#x24C9;][1]
Flattens a nested array *(the nesting can be to any depth)*. If `shallow` is truthy, `array` will only be flattened a single level.
@@ -720,9 +720,9 @@ _.flatten([1, [2], [3, [[4]]]], true);
<!-- div -->
### <a id="_foreachcollection-callback--thisarg"></a>`_.forEach(collection, callback [, thisArg])`
<a href="#_foreachcollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L818 "View in source") [&#x24C9;][1]
<a href="#_foreachcollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L857 "View in source") [&#x24C9;][1]
Iterates over a `collection`, executing the `callback` for each value in the `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
Iterates over a `collection`, executing the `callback` for each value in the `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -749,7 +749,7 @@ _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
<!-- div -->
### <a id="_forinobject-callback--thisarg"></a>`_.forIn(object, callback [, thisArg])`
<a href="#_forinobject-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2467 "View in source") [&#x24C9;][1]
<a href="#_forinobject-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2510 "View in source") [&#x24C9;][1]
Iterates over `object`'s own and inherited enumerable properties, executing the `callback` for each property. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*.
@@ -785,7 +785,7 @@ _.forIn(new Dog('Dagny'), function(value, key) {
<!-- div -->
### <a id="_forownobject-callback--thisarg"></a>`_.forOwn(object, callback [, thisArg])`
<a href="#_forownobject-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2490 "View in source") [&#x24C9;][1]
<a href="#_forownobject-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2533 "View in source") [&#x24C9;][1]
Iterates over `object`'s own enumerable properties, executing the `callback` for each property. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, key, object)*.
@@ -813,7 +813,7 @@ _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
<!-- div -->
### <a id="_functionsobject"></a>`_.functions(object)`
<a href="#_functionsobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2507 "View in source") [&#x24C9;][1]
<a href="#_functionsobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2550 "View in source") [&#x24C9;][1]
Produces a sorted array of the enumerable properties, own and inherited, of `object` that have function values.
@@ -837,9 +837,9 @@ _.functions(_);
<!-- div -->
### <a id="_groupbycollection-callback--thisarg"></a>`_.groupBy(collection, callback [, thisArg])`
<a href="#_groupbycollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L846 "View in source") [&#x24C9;][1]
<a href="#_groupbycollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L884 "View in source") [&#x24C9;][1]
Splits `collection` into sets, grouped by the result of running each value through `callback`. The `callback` is bound to `thisArg` and 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.
Splits `collection` into sets, grouped by the result of running each value through `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*. The `callback` argument may also be the name of a property to group by.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -869,7 +869,7 @@ _.groupBy(['one', 'two', 'three'], 'length');
<!-- div -->
### <a id="_hasobject-property"></a>`_.has(object, property)`
<a href="#_hasobject-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2530 "View in source") [&#x24C9;][1]
<a href="#_hasobject-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2573 "View in source") [&#x24C9;][1]
Checks if the specified object `property` exists and is a direct property, instead of an inherited property.
@@ -894,7 +894,7 @@ _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
<!-- div -->
### <a id="_identityvalue"></a>`_.identity(value)`
<a href="#_identityvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3147 "View in source") [&#x24C9;][1]
<a href="#_identityvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3192 "View in source") [&#x24C9;][1]
This function returns the first argument passed to it. Note: It is used throughout Lo-Dash as a default callback.
@@ -919,7 +919,7 @@ moe === _.identity(moe);
<!-- div -->
### <a id="_indexofarray-value--fromindex0"></a>`_.indexOf(array, value [, fromIndex=0])`
<a href="#_indexofarray-value--fromindex0">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1329 "View in source") [&#x24C9;][1]
<a href="#_indexofarray-value--fromindex0">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1364 "View in source") [&#x24C9;][1]
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.
@@ -951,7 +951,7 @@ _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
<!-- div -->
### <a id="_initialarray--n-guard"></a>`_.initial(array [, n, guard])`
<a href="#_initialarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1369 "View in source") [&#x24C9;][1]
<a href="#_initialarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1404 "View in source") [&#x24C9;][1]
Gets all but the last value of `array`. Pass `n` to exclude the last `n` values from the result.
@@ -977,7 +977,7 @@ _.initial([3, 2, 1]);
<!-- div -->
### <a id="_intersectionarray1-array2-"></a>`_.intersection([array1, array2, ...])`
<a href="#_intersectionarray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1390 "View in source") [&#x24C9;][1]
<a href="#_intersectionarray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1425 "View in source") [&#x24C9;][1]
Computes the intersection of all the passed-in arrays.
@@ -1001,7 +1001,7 @@ _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
<!-- div -->
### <a id="_invokecollection-methodname--arg1-arg2-"></a>`_.invoke(collection, methodName [, arg1, arg2, ...])`
<a href="#_invokecollection-methodname--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L880 "View in source") [&#x24C9;][1]
<a href="#_invokecollection-methodname--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L918 "View in source") [&#x24C9;][1]
Invokes the method named by `methodName` on each element in the `collection`. Additional arguments will be passed to each invoked method. If `methodName` is a function it will be invoked for, and `this` bound to, each element in the `collection`.
@@ -1030,7 +1030,7 @@ _.invoke([123, 456], String.prototype.split, '');
<!-- div -->
### <a id="_isargumentsvalue"></a>`_.isArguments(value)`
<a href="#_isargumentsvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2550 "View in source") [&#x24C9;][1]
<a href="#_isargumentsvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2593 "View in source") [&#x24C9;][1]
Checks if `value` is an `arguments` object.
@@ -1057,7 +1057,7 @@ _.isArguments([1, 2, 3]);
<!-- div -->
### <a id="_isarrayvalue"></a>`_.isArray(value)`
<a href="#_isarrayvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2576 "View in source") [&#x24C9;][1]
<a href="#_isarrayvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2620 "View in source") [&#x24C9;][1]
Checks if `value` is an array.
@@ -1084,7 +1084,7 @@ _.isArray([1, 2, 3]);
<!-- div -->
### <a id="_isbooleanvalue"></a>`_.isBoolean(value)`
<a href="#_isbooleanvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2593 "View in source") [&#x24C9;][1]
<a href="#_isbooleanvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2637 "View in source") [&#x24C9;][1]
Checks if `value` is a boolean *(`true` or `false`)* value.
@@ -1108,7 +1108,7 @@ _.isBoolean(null);
<!-- div -->
### <a id="_isdatevalue"></a>`_.isDate(value)`
<a href="#_isdatevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2610 "View in source") [&#x24C9;][1]
<a href="#_isdatevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2654 "View in source") [&#x24C9;][1]
Checks if `value` is a date.
@@ -1132,7 +1132,7 @@ _.isDate(new Date);
<!-- div -->
### <a id="_iselementvalue"></a>`_.isElement(value)`
<a href="#_iselementvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2627 "View in source") [&#x24C9;][1]
<a href="#_iselementvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2671 "View in source") [&#x24C9;][1]
Checks if `value` is a DOM element.
@@ -1156,7 +1156,7 @@ _.isElement(document.body);
<!-- div -->
### <a id="_isemptyvalue"></a>`_.isEmpty(value)`
<a href="#_isemptyvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2651 "View in source") [&#x24C9;][1]
<a href="#_isemptyvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2695 "View in source") [&#x24C9;][1]
Checks if `value` is empty. Arrays or strings with a length of `0` and objects with no own enumerable properties are considered "empty".
@@ -1186,7 +1186,7 @@ _.isEmpty('');
<!-- div -->
### <a id="_isequala-b--stack"></a>`_.isEqual(a, b [, stack])`
<a href="#_isequala-b--stack">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2685 "View in source") [&#x24C9;][1]
<a href="#_isequala-b--stack">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2729 "View in source") [&#x24C9;][1]
Performs a deep comparison between two values to determine if they are equivalent to each other.
@@ -1218,7 +1218,7 @@ _.isEqual(moe, clone);
<!-- div -->
### <a id="_isfinitevalue"></a>`_.isFinite(value)`
<a href="#_isfinitevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2846 "View in source") [&#x24C9;][1]
<a href="#_isfinitevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2891 "View in source") [&#x24C9;][1]
Checks if `value` is a finite number. Note: This is not the same as native `isFinite`, which will return true for booleans and other values. See http://es5.github.com/#x15.1.2.5.
@@ -1248,7 +1248,7 @@ _.isFinite(Infinity);
<!-- div -->
### <a id="_isfunctionvalue"></a>`_.isFunction(value)`
<a href="#_isfunctionvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2863 "View in source") [&#x24C9;][1]
<a href="#_isfunctionvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2908 "View in source") [&#x24C9;][1]
Checks if `value` is a function.
@@ -1272,7 +1272,7 @@ _.isFunction(''.concat);
<!-- div -->
### <a id="_isnanvalue"></a>`_.isNaN(value)`
<a href="#_isnanvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2915 "View in source") [&#x24C9;][1]
<a href="#_isnanvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2960 "View in source") [&#x24C9;][1]
Checks if `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.
@@ -1305,7 +1305,7 @@ _.isNaN(undefined);
<!-- div -->
### <a id="_isnullvalue"></a>`_.isNull(value)`
<a href="#_isnullvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2938 "View in source") [&#x24C9;][1]
<a href="#_isnullvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2983 "View in source") [&#x24C9;][1]
Checks if `value` is `null`.
@@ -1332,7 +1332,7 @@ _.isNull(undefined);
<!-- div -->
### <a id="_isnumbervalue"></a>`_.isNumber(value)`
<a href="#_isnumbervalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2955 "View in source") [&#x24C9;][1]
<a href="#_isnumbervalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3000 "View in source") [&#x24C9;][1]
Checks if `value` is a number.
@@ -1356,7 +1356,7 @@ _.isNumber(8.4 * 5;
<!-- div -->
### <a id="_isobjectvalue"></a>`_.isObject(value)`
<a href="#_isobjectvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2884 "View in source") [&#x24C9;][1]
<a href="#_isobjectvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2929 "View in source") [&#x24C9;][1]
Checks if `value` is the language type of Object. *(e.g. arrays, functions, objects, regexps, `new Number(0)`, and `new String('')`)*
@@ -1383,7 +1383,7 @@ _.isObject(1);
<!-- div -->
### <a id="_isregexpvalue"></a>`_.isRegExp(value)`
<a href="#_isregexpvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2972 "View in source") [&#x24C9;][1]
<a href="#_isregexpvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3017 "View in source") [&#x24C9;][1]
Checks if `value` is a regular expression.
@@ -1407,7 +1407,7 @@ _.isRegExp(/moe/);
<!-- div -->
### <a id="_isstringvalue"></a>`_.isString(value)`
<a href="#_isstringvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2989 "View in source") [&#x24C9;][1]
<a href="#_isstringvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3034 "View in source") [&#x24C9;][1]
Checks if `value` is a string.
@@ -1431,7 +1431,7 @@ _.isString('moe');
<!-- div -->
### <a id="_isundefinedvalue"></a>`_.isUndefined(value)`
<a href="#_isundefinedvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3007 "View in source") [&#x24C9;][1]
<a href="#_isundefinedvalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3052 "View in source") [&#x24C9;][1]
Checks if `value` is `undefined`.
@@ -1455,7 +1455,7 @@ _.isUndefined(void 0);
<!-- div -->
### <a id="_keysobject"></a>`_.keys(object)`
<a href="#_keysobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3024 "View in source") [&#x24C9;][1]
<a href="#_keysobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3069 "View in source") [&#x24C9;][1]
Produces an array of object`'s own enumerable property names.
@@ -1479,7 +1479,7 @@ _.keys({ 'one': 1, 'two': 2, 'three': 3 });
<!-- div -->
### <a id="_lastarray--n-guard"></a>`_.last(array [, n, guard])`
<a href="#_lastarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1428 "View in source") [&#x24C9;][1]
<a href="#_lastarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1466 "View in source") [&#x24C9;][1]
Gets the last value of the `array`. Pass `n` to return the lasy `n` values of the `array`.
@@ -1505,7 +1505,7 @@ _.last([3, 2, 1]);
<!-- div -->
### <a id="_lastindexofarray-value--fromindexarraylength-1"></a>`_.lastIndexOf(array, value [, fromIndex=array.length-1])`
<a href="#_lastindexofarray-value--fromindexarraylength-1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1454 "View in source") [&#x24C9;][1]
<a href="#_lastindexofarray-value--fromindexarraylength-1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1492 "View in source") [&#x24C9;][1]
Gets the index at which the last occurrence of `value` is found using strict equality for comparisons, i.e. `===`.
@@ -1534,9 +1534,9 @@ _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
<!-- div -->
### <a id="_mapcollection--callbackidentity-thisarg"></a>`_.map(collection [, callback=identity, thisArg])`
<a href="#_mapcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L917 "View in source") [&#x24C9;][1]
<a href="#_mapcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L954 "View in source") [&#x24C9;][1]
Produces a new array of values by mapping each element in the `collection` through a transformation `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
Produces a new array of values by mapping each element in the `collection` through a transformation `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -1563,7 +1563,7 @@ _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
<!-- div -->
### <a id="_maxarray--callback-thisarg"></a>`_.max(array [, callback, thisArg])`
<a href="#_maxarray--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1494 "View in source") [&#x24C9;][1]
<a href="#_maxarray--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1532 "View in source") [&#x24C9;][1]
Retrieves the maximum value of an `array`. If `callback` is passed, it will be executed for each value in the `array` to generate the criterion by which the value is ranked. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index, array)*.
@@ -1595,7 +1595,7 @@ _.max(stooges, function(stooge) { return stooge.age; });
<!-- div -->
### <a id="_memoizefunc--resolver"></a>`_.memoize(func [, resolver])`
<a href="#_memoizefunc--resolver">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2223 "View in source") [&#x24C9;][1]
<a href="#_memoizefunc--resolver">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2266 "View in source") [&#x24C9;][1]
Creates a new function that memoizes the result of `func`. If `resolver` is passed, it will be used to determine the cache key for storing the result based on the arguments passed to the memoized function. By default, the first argument passed to the memoized function is used as the cache key.
@@ -1621,7 +1621,7 @@ var fibonacci = _.memoize(function(n) {
<!-- div -->
### <a id="_minarray--callback-thisarg"></a>`_.min(array [, callback, thisArg])`
<a href="#_minarray--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1544 "View in source") [&#x24C9;][1]
<a href="#_minarray--callback-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1582 "View in source") [&#x24C9;][1]
Retrieves the minimum value of an `array`. If `callback` is passed, it will be executed for each value in the `array` to generate the criterion by which the value is ranked. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index, array)*.
@@ -1647,7 +1647,7 @@ _.min([10, 5, 100, 2, 1000]);
<!-- div -->
### <a id="_mixinobject"></a>`_.mixin(object)`
<a href="#_mixinobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3173 "View in source") [&#x24C9;][1]
<a href="#_mixinobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3218 "View in source") [&#x24C9;][1]
Adds functions properties of `object` to the `lodash` function and chainable wrapper.
@@ -1677,7 +1677,7 @@ _('larry').capitalize();
<!-- div -->
### <a id="_noconflict"></a>`_.noConflict()`
<a href="#_noconflict">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3204 "View in source") [&#x24C9;][1]
<a href="#_noconflict">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3249 "View in source") [&#x24C9;][1]
Reverts the '_' variable to its previous value and returns a reference to the `lodash` function.
@@ -1697,7 +1697,7 @@ var lodash = _.noConflict();
<!-- div -->
### <a id="_oncefunc"></a>`_.once(func)`
<a href="#_oncefunc">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2249 "View in source") [&#x24C9;][1]
<a href="#_oncefunc">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2292 "View in source") [&#x24C9;][1]
Creates a new function that is restricted to one execution. Repeat calls to the function will return the value of the first call.
@@ -1723,7 +1723,7 @@ initialize();
<!-- div -->
### <a id="_partialfunc--arg1-arg2-"></a>`_.partial(func [, arg1, arg2, ...])`
<a href="#_partialfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2282 "View in source") [&#x24C9;][1]
<a href="#_partialfunc--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2325 "View in source") [&#x24C9;][1]
Creates a new function that, when called, invokes `func` with any additional `partial` arguments prepended to those passed to the partially applied function. This method is similar `bind`, except it does **not** alter the `this` binding.
@@ -1750,7 +1750,7 @@ hi('moe');
<!-- div -->
### <a id="_pickobject--prop1-prop2-"></a>`_.pick(object [, prop1, prop2, ...])`
<a href="#_pickobject--prop1-prop2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3046 "View in source") [&#x24C9;][1]
<a href="#_pickobject--prop1-prop2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3091 "View in source") [&#x24C9;][1]
Creates an object composed of the specified properties. Property names may be specified as individual arguments or as arrays of property names.
@@ -1775,7 +1775,7 @@ _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
<!-- div -->
### <a id="_pluckcollection-property"></a>`_.pluck(collection, property)`
<a href="#_pluckcollection-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L940 "View in source") [&#x24C9;][1]
<a href="#_pluckcollection-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L977 "View in source") [&#x24C9;][1]
Retrieves the value of a specified property from all elements in the `collection`.
@@ -1806,7 +1806,7 @@ _.pluck(stooges, 'name');
<!-- div -->
### <a id="_rangestart0-end--step1"></a>`_.range([start=0], end [, step=1])`
<a href="#_rangestart0-end--step1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1605 "View in source") [&#x24C9;][1]
<a href="#_rangestart0-end--step1">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1643 "View in source") [&#x24C9;][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.
@@ -1844,9 +1844,9 @@ _.range(0);
<!-- div -->
### <a id="_reducecollection-callback--accumulator-thisarg"></a>`_.reduce(collection, callback [, accumulator, thisArg])`
<a href="#_reducecollection-callback--accumulator-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L969 "View in source") [&#x24C9;][1]
<a href="#_reducecollection-callback--accumulator-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1005 "View in source") [&#x24C9;][1]
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 `thisArg` and invoked with `4` arguments; for arrays they are *(accumulator, value, index, array)* and for objects they are *(accumulator, value, key, object)*.
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 `thisArg` and invoked with `4` arguments; for arrays they are *(accumulator, value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -1871,7 +1871,7 @@ var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
<!-- div -->
### <a id="_reducerightcollection-callback--accumulator-thisarg"></a>`_.reduceRight(collection, callback [, accumulator, thisArg])`
<a href="#_reducerightcollection-callback--accumulator-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1006 "View in source") [&#x24C9;][1]
<a href="#_reducerightcollection-callback--accumulator-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1042 "View in source") [&#x24C9;][1]
The right-associative version of `_.reduce`.
@@ -1899,7 +1899,7 @@ var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
<!-- div -->
### <a id="_rejectcollection--callbackidentity-thisarg"></a>`_.reject(collection [, callback=identity, thisArg])`
<a href="#_rejectcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1061 "View in source") [&#x24C9;][1]
<a href="#_rejectcollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1097 "View in source") [&#x24C9;][1]
The opposite of `_.filter`, this method returns the values of a `collection` that `callback` does **not** return truthy for.
@@ -1925,7 +1925,7 @@ var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
<!-- div -->
### <a id="_restarray--n-guard"></a>`_.rest(array [, n, guard])`
<a href="#_restarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1642 "View in source") [&#x24C9;][1]
<a href="#_restarray--n-guard">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1680 "View in source") [&#x24C9;][1]
The opposite of `_.initial`, this method gets all but the first value of `array`. Pass `n` to exclude the first `n` values from the result.
@@ -1951,7 +1951,7 @@ _.rest([3, 2, 1]);
<!-- div -->
### <a id="_resultobject-property"></a>`_.result(object, property)`
<a href="#_resultobject-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3236 "View in source") [&#x24C9;][1]
<a href="#_resultobject-property">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3281 "View in source") [&#x24C9;][1]
Resolves the value of `property` on `object`. If `property` is a function it will be invoked and its result returned, else the property value is returned. If `object` is falsey, then `null` is returned.
@@ -1986,7 +1986,7 @@ _.result(object, 'stuff');
<!-- div -->
### <a id="_shufflearray"></a>`_.shuffle(array)`
<a href="#_shufflearray">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1663 "View in source") [&#x24C9;][1]
<a href="#_shufflearray">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1701 "View in source") [&#x24C9;][1]
Produces a new array of shuffled `array` values, using a version of the Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
@@ -2010,7 +2010,7 @@ _.shuffle([1, 2, 3, 4, 5, 6]);
<!-- div -->
### <a id="_sizevalue"></a>`_.size(value)`
<a href="#_sizevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3085 "View in source") [&#x24C9;][1]
<a href="#_sizevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3130 "View in source") [&#x24C9;][1]
Gets the size of `value` by returning `value.length` if `value` is a string or array, or the number of own enumerable properties if `value` is an object.
@@ -2040,9 +2040,9 @@ _.size('curly');
<!-- div -->
### <a id="_somecollection--callbackidentity-thisarg"></a>`_.some(collection [, callback=identity, thisArg])`
<a href="#_somecollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1085 "View in source") [&#x24C9;][1]
<a href="#_somecollection--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1120 "View in source") [&#x24C9;][1]
Checks if the `callback` returns a truthy value for **any** element of a `collection`. The function returns as soon as it finds passing value, and does not iterate over the entire `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; for arrays they are *(value, index, array)* and for objects they are *(value, key, object)*.
Checks if the `callback` returns a truthy value for **any** element of a `collection`. The function returns as soon as it finds passing value, and does not iterate over the entire `collection`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -2066,9 +2066,9 @@ _.some([null, 0, 'yes', false]);
<!-- div -->
### <a id="_sortbycollection-callback--thisarg"></a>`_.sortBy(collection, callback [, thisArg])`
<a href="#_sortbycollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1118 "View in source") [&#x24C9;][1]
<a href="#_sortbycollection-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1152 "View in source") [&#x24C9;][1]
Produces a new sorted array, sorted in ascending order by the results of running each element of `collection` through a transformation `callback`. The `callback` is bound to `thisArg` and 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')*.
Produces a new sorted array, sorted in ascending order by the results of running each element of `collection` through a transformation `callback`. The `callback` is bound to `thisArg` and invoked with `3` arguments; *(value, index|key, collection)*. The `callback` argument may also be the name of a property to sort by *(e.g. 'length')*.
#### Arguments
1. `collection` *(Array|Object|String)*: The collection to iterate over.
@@ -2098,7 +2098,7 @@ _.sortBy(['larry', 'brendan', 'moe'], 'length');
<!-- div -->
### <a id="_sortedindexarray-value--callbackidentity-thisarg"></a>`_.sortedIndex(array, value [, callback=identity, thisArg])`
<a href="#_sortedindexarray-value--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1715 "View in source") [&#x24C9;][1]
<a href="#_sortedindexarray-value--callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1753 "View in source") [&#x24C9;][1]
Uses a binary search to determine the smallest index at which the `value` should be inserted into `array` in order to maintain the sort order of the sorted `array`. If `callback` is passed, it will be executed for `value` and each element in `array` to compute their sort ranking. The `callback` is bound to `thisArg` and invoked with `1` argument; *(value)*.
@@ -2139,7 +2139,7 @@ _.sortedIndex(['twenty', 'thirty', 'fourty'], 'thirty-five', function(word) {
<!-- div -->
### <a id="_tapvalue-interceptor"></a>`_.tap(value, interceptor)`
<a href="#_tapvalue-interceptor">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3515 "View in source") [&#x24C9;][1]
<a href="#_tapvalue-interceptor">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3560 "View in source") [&#x24C9;][1]
Invokes `interceptor` with the `value` as the first argument, and then returns `value`. The purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
@@ -2169,7 +2169,7 @@ _.chain([1,2,3,200])
<!-- div -->
### <a id="_templatetext-data-options"></a>`_.template(text, data, options)`
<a href="#_templatetext-data-options">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3296 "View in source") [&#x24C9;][1]
<a href="#_templatetext-data-options">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3341 "View in source") [&#x24C9;][1]
A micro-templating method that handles arbitrary delimiters, preserves whitespace, and correctly escapes quotes within interpolated code.
@@ -2228,7 +2228,7 @@ _.template('<%= data.hasWith %>', { 'hasWith': 'no' }, { 'variable': 'data' });
<!-- div -->
### <a id="_throttlefunc-wait"></a>`_.throttle(func, wait)`
<a href="#_throttlefunc-wait">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2318 "View in source") [&#x24C9;][1]
<a href="#_throttlefunc-wait">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2361 "View in source") [&#x24C9;][1]
Creates a new function that, when executed, will only call the `func` function at most once per every `wait` milliseconds. If the throttled function is invoked more than once during the `wait` timeout, `func` will also be called on the trailing edge of the timeout. Subsequent calls to the throttled function will return the result of the last `func` call.
@@ -2253,7 +2253,7 @@ jQuery(window).on('scroll', throttled);
<!-- div -->
### <a id="_timesn-callback--thisarg"></a>`_.times(n, callback [, thisArg])`
<a href="#_timesn-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3431 "View in source") [&#x24C9;][1]
<a href="#_timesn-callback--thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3476 "View in source") [&#x24C9;][1]
Executes the `callback` function `n` times. The `callback` is bound to `thisArg` and invoked with `1` argument; *(index)*.
@@ -2279,7 +2279,7 @@ _.times(3, function() { this.grantWish(); }, genie);
<!-- div -->
### <a id="_toarraycollection"></a>`_.toArray(collection)`
<a href="#_toarraycollection">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1161 "View in source") [&#x24C9;][1]
<a href="#_toarraycollection">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1195 "View in source") [&#x24C9;][1]
Converts the `collection`, into an array. Useful for converting the `arguments` object.
@@ -2303,7 +2303,7 @@ Converts the `collection`, into an array. Useful for converting the `arguments`
<!-- div -->
### <a id="_unionarray1-array2-"></a>`_.union([array1, array2, ...])`
<a href="#_unionarray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1755 "View in source") [&#x24C9;][1]
<a href="#_unionarray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1793 "View in source") [&#x24C9;][1]
Computes the union of the passed-in arrays.
@@ -2327,7 +2327,7 @@ _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
<!-- div -->
### <a id="_uniqarray--issortedfalse-callbackidentity-thisarg"></a>`_.uniq(array [, isSorted=false, callback=identity, thisArg])`
<a href="#_uniqarray--issortedfalse-callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1800 "View in source") [&#x24C9;][1]
<a href="#_uniqarray--issortedfalse-callbackidentity-thisarg">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1838 "View in source") [&#x24C9;][1]
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 bound to `thisArg` and invoked with `3` arguments; *(value, index, array)*.
@@ -2363,7 +2363,7 @@ _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
<!-- div -->
### <a id="_uniqueidprefix"></a>`_.uniqueId([prefix])`
<a href="#_uniqueidprefix">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3458 "View in source") [&#x24C9;][1]
<a href="#_uniqueidprefix">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3503 "View in source") [&#x24C9;][1]
Generates a unique id. If `prefix` is passed, the id will be appended to it.
@@ -2387,7 +2387,7 @@ _.uniqueId('contact_');
<!-- div -->
### <a id="_valuesobject"></a>`_.values(object)`
<a href="#_valuesobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3106 "View in source") [&#x24C9;][1]
<a href="#_valuesobject">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3151 "View in source") [&#x24C9;][1]
Produces an array of `object`'s own enumerable property values.
@@ -2411,7 +2411,7 @@ _.values({ 'one': 1, 'two': 2, 'three': 3 });
<!-- div -->
### <a id="_withoutarray--value1-value2-"></a>`_.without(array [, value1, value2, ...])`
<a href="#_withoutarray--value1-value2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1849 "View in source") [&#x24C9;][1]
<a href="#_withoutarray--value1-value2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1887 "View in source") [&#x24C9;][1]
Produces a new array with all occurrences of the passed values removed using strict equality for comparisons, i.e. `===`.
@@ -2436,7 +2436,7 @@ _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
<!-- div -->
### <a id="_wrapfunc-wrapper--arg1-arg2-"></a>`_.wrap(func, wrapper [, arg1, arg2, ...])`
<a href="#_wrapfunc-wrapper--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2370 "View in source") [&#x24C9;][1]
<a href="#_wrapfunc-wrapper--arg1-arg2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L2413 "View in source") [&#x24C9;][1]
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.
@@ -2466,7 +2466,7 @@ hello();
<!-- div -->
### <a id="_ziparray1-array2-"></a>`_.zip([array1, array2, ...])`
<a href="#_ziparray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1881 "View in source") [&#x24C9;][1]
<a href="#_ziparray1-array2-">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1920 "View in source") [&#x24C9;][1]
Merges the elements of each array at their corresponding indexes. 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.
@@ -2490,7 +2490,7 @@ _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
<!-- div -->
### <a id="_zipobjectkeys"></a>`_.zipObject(keys)`
<a href="#_zipobjectkeys">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1910 "View in source") [&#x24C9;][1]
<a href="#_zipobjectkeys">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L1949 "View in source") [&#x24C9;][1]
Merges an array of `keys` and an array of `values` into a single object.
@@ -2521,7 +2521,7 @@ _.zipObject(['moe', 'larry', 'curly'], [30, 40, 50]);
<!-- div -->
### <a id="_prototypechain"></a>`_.prototype.chain()`
<a href="#_prototypechain">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3533 "View in source") [&#x24C9;][1]
<a href="#_prototypechain">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3578 "View in source") [&#x24C9;][1]
Enables method chaining on the wrapper object.
@@ -2542,7 +2542,7 @@ _([1, 2, 3]).value();
<!-- div -->
### <a id="_prototypevalue"></a>`_.prototype.value()`
<a href="#_prototypevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3550 "View in source") [&#x24C9;][1]
<a href="#_prototypevalue">#</a> [&#x24C8;](https://github.com/bestiejs/lodash/blob/master/lodash.js#L3595 "View in source") [&#x24C9;][1]
Extracts the wrapped value.

View File

@@ -21,7 +21,7 @@
// generate Markdown
$markdown = docdown(array(
'path' => '../' . $file,
'title' => 'Lo-Dash <sup>v0.4.1</sup>',
'title' => 'Lo-Dash <sup>v0.4.2</sup>',
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
));

198
lodash.js
View File

@@ -1,5 +1,5 @@
/*!
* Lo-Dash v0.4.1 <http://lodash.com>
* Lo-Dash v0.4.2 <http://lodash.com>
* Copyright 2012 John-David Dalton <http://allyoucanleet.com/>
* Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
* <http://documentcloud.github.com/underscore>
@@ -123,7 +123,7 @@
*/
var hasDontEnumBug = !propertyIsEnumerable.call({ 'valueOf': 0 }, 'valueOf');
/** Detect if `Array#slice` cannot be used to convert strings to arrays (e.g. Opera < 10.52) */
/** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
var noArraySliceOnStrings = slice.call('x')[0] != 'x';
/**
@@ -133,10 +133,10 @@
*/
var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
/* Detect if `Function#bind` exists and is inferred to be fast (i.e. all but V8) */
/* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
/* Detect if `Object.keys` exists and is inferred to be fast (i.e. V8, Opera, IE) */
/* Detect if `Object.keys` exists and is inferred to be fast (V8, Opera, IE) */
var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
/** Detect if sourceURL syntax is usable without erroring */
@@ -266,13 +266,17 @@
* @returns {String} Returns the interpolated text.
*/
var iteratorTemplate = template(
// conditional strict mode
'<% if (useStrict) { %>\'use strict\';\n<% } %>' +
// the `iteratee` may be reassigned by the `top` snippet
'var index, iteratee = <%= firstArg %>, ' +
// assign the `result` variable an initial value
'var result<% if (init) { %> = <%= init %><% } %>;\n' +
'result<% if (init) { %> = <%= init %><% } %>;\n' +
// add code to exit early or do so if the first argument is falsey
'<%= exit %>;\n' +
// add code after the exit snippet but before the iteration branches
'<%= top %>;\n' +
'var index, iteratee = <%= iteratee %>;\n' +
// the following branch is for iterating arrays and array-like objects
'<% if (arrayBranch) { %>' +
@@ -389,14 +393,14 @@
/** Reusable iterator options for `defaults` and `extend` */
var extendIteratorOptions = {
'useHas': false,
'useStrict': false,
'args': 'object',
'init': 'object',
'top':
'for (var source, sourceIndex = 1, length = arguments.length; sourceIndex < length; sourceIndex++) {\n' +
' source = arguments[sourceIndex];\n' +
(hasDontEnumBug ? ' if (source) {' : ''),
'iteratee': 'source',
'useHas': false,
'for (var iterateeIndex = 1, length = arguments.length; iterateeIndex < length; iterateeIndex++) {\n' +
' iteratee = arguments[iterateeIndex];\n' +
(hasDontEnumBug ? ' if (iteratee) {' : ''),
'inLoop': 'result[index] = iteratee[index]',
'bottom': (hasDontEnumBug ? ' }\n' : '') + '}'
};
@@ -435,6 +439,45 @@
/*--------------------------------------------------------------------------*/
/**
* Creates a new function optimized for searching large arrays for a given `value`,
* starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
*
* @private
* @param {Array} array The array to search.
* @param {Mixed} value The value to search for.
* @param {Number} [fromIndex=0] The index to start searching from.
* @param {Number} [largeSize=30] The length at which an array is considered large.
* @returns {Boolean} Returns `true` if `value` is found, else `false`.
*/
function cachedContains(array, fromIndex, largeSize) {
fromIndex || (fromIndex = 0);
var length = array.length,
isLarge = (length - fromIndex) >= (largeSize || 30),
cache = isLarge ? {} : array;
if (isLarge) {
// init value cache
var key,
index = fromIndex - 1;
while (++index < length) {
// manually coerce `value` to string because `hasOwnProperty`, in some
// older versions of Firefox, coerces objects incorrectly
key = array[index] + '';
(hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
}
}
return function(value) {
if (isLarge) {
var key = value + '';
return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
}
return indexOf(cache, value, fromIndex) > -1;
}
}
/**
* Creates compiled iteration functions. The iteration function will be created
* to iterate over only objects if the first argument of `options.args` is
@@ -443,6 +486,12 @@
* @private
* @param {Object} [options1, options2, ...] The compile options objects.
*
* useHas - A boolean to specify whether or not to use `hasOwnProperty` checks
* in the object loop.
*
* useStrict - A boolean to specify whether or not to include the ES5
* "use strict" directive.
*
* args - A string of comma separated arguments the iteration function will
* accept.
*
@@ -457,12 +506,6 @@
* beforeLoop - A string or object containing an "array" or "object" property
* of code to execute before the array or object loops.
*
* iteratee - A string or object containing an "array" or "object" property
* of the variable to be iterated in the loop expression.
*
* useHas - A boolean to specify whether or not to use `hasOwnProperty` checks
* in the object loop.
*
* inLoop - A string or object containing an "array" or "object" property
* of code to execute in the array or object loops.
*
@@ -506,14 +549,14 @@
}
// set additional template `data` values
var args = data.args,
firstArg = /^[^,]+/.exec(args)[0],
iteratee = (data.iteratee = data.iteratee || firstArg);
firstArg = /^[^,]+/.exec(args)[0];
data.firstArg = firstArg;
data.hasDontEnumBug = hasDontEnumBug;
data.isKeysFast = isKeysFast;
data.shadowed = shadowed;
data.useHas = data.useHas !== false;
data.useStrict = data.useStrict !== false;
if (!('noCharByIndex' in data)) {
data.noCharByIndex = noCharByIndex;
@@ -526,14 +569,14 @@
}
// create the function factory
var factory = Function(
'arrayClass, compareAscending, funcClass, hasOwnProperty, identity, ' +
'iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, ' +
'slice, stringClass, toString',
'"use strict"; return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
'arrayClass, bind, compareAscending, funcClass, hasOwnProperty, identity, ' +
'iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice, ' +
'stringClass, toString',
'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
);
// return the compiled function
return factory(
arrayClass, compareAscending, funcClass, hasOwnProperty, identity,
arrayClass, bind, compareAscending, funcClass, hasOwnProperty, identity,
iteratorBind, objectTypes, nativeKeys, propertyIsEnumerable, slice,
stringClass, toString
);
@@ -729,8 +772,7 @@
/**
* Checks if the `callback` returns a truthy value for **all** elements of a
* `collection`. The `callback` is bound to `thisArg` and invoked with 3
* arguments; for arrays they are (value, index, array) and for objects they
* are (value, key, object).
* arguments; (value, index|key, collection).
*
* @static
* @memberOf _
@@ -750,8 +792,7 @@
/**
* Examines each value in a `collection`, returning an array of all values the
* `callback` returns truthy for. The `callback` is bound to `thisArg` and
* invoked with 3 arguments; for arrays they are (value, index, array) and for
* objects they are (value, key, object).
* invoked with 3 arguments; (value, index|key, collection).
*
* @static
* @memberOf _
@@ -772,8 +813,7 @@
* 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
* bound to `thisArg` and invoked with 3 arguments; for arrays they are
* (value, index, array) and for objects they are (value, key, object).
* bound to `thisArg` and invoked with 3 arguments; (value, index|key, collection).
*
* @static
* @memberOf _
@@ -796,8 +836,7 @@
/**
* Iterates over a `collection`, executing the `callback` for each value in the
* `collection`. The `callback` is bound to `thisArg` and invoked with 3
* arguments; for arrays they are (value, index, array) and for objects they
* are (value, key, object).
* arguments; (value, index|key, collection).
*
* @static
* @memberOf _
@@ -820,9 +859,8 @@
/**
* Splits `collection` into sets, grouped by the result of running each value
* through `callback`. The `callback` is bound to `thisArg` and 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.
* 3 arguments; (value, index|key, collection). The `callback` argument may
* also be the name of a property to group by.
*
* @static
* @memberOf _
@@ -895,8 +933,7 @@
/**
* Produces a new array of values by mapping each element in the `collection`
* through a transformation `callback`. The `callback` is bound to `thisArg`
* and invoked with 3 arguments; for arrays they are (value, index, array)
* and for objects they are (value, key, object).
* and invoked with 3 arguments; (value, index|key, collection).
*
* @static
* @memberOf _
@@ -949,8 +986,7 @@
* 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 `thisArg` and invoked with 4
* arguments; for arrays they are (accumulator, value, index, array) and for
* objects they are (accumulator, value, key, object).
* arguments; for arrays they are (accumulator, value, index|key, collection).
*
* @static
* @memberOf _
@@ -1043,8 +1079,8 @@
}
/**
* The opposite of `_.filter`, this method returns the values of a `collection`
* that `callback` does **not** return truthy for.
* The opposite of `_.filter`, this method returns the values of a
* `collection` that `callback` does **not** return truthy for.
*
* @static
* @memberOf _
@@ -1066,8 +1102,7 @@
* Checks if the `callback` returns a truthy value for **any** element of a
* `collection`. The function returns as soon as it finds passing value, and
* does not iterate over the entire `collection`. The `callback` is bound to
* `thisArg` and invoked with 3 arguments; for arrays they are
* (value, index, array) and for objects they are (value, key, object).
* `thisArg` and invoked with 3 arguments; (value, index|key, collection).
*
* @static
* @memberOf _
@@ -1092,9 +1127,8 @@
* Produces a new sorted array, sorted in ascending order by the results of
* running each element of `collection` through a transformation `callback`.
* The `callback` is bound to `thisArg` and 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').
* (value, index|key, collection). The `callback` argument may also be the
* name of a property to sort by (e.g. 'length').
*
* @static
* @memberOf _
@@ -1229,10 +1263,11 @@
}
var index = -1,
length = array.length,
flattened = concat.apply(result, arguments);
flattened = concat.apply(result, arguments),
contains = cachedContains(flattened, length);
while (++index < length) {
if (indexOf(flattened, array[index], length) < 0) {
if (!contains(array[index])) {
result.push(array[index]);
}
}
@@ -1395,12 +1430,15 @@
var value,
index = -1,
length = array.length,
others = slice.call(arguments, 1);
others = slice.call(arguments, 1),
cache = [];
while (++index < length) {
value = array[index];
if (indexOf(result, value) < 0 &&
every(others, function(other) { return indexOf(other, value) > -1; })) {
every(others, function(other, index) {
return (cache[index] || (cache[index] = cachedContains(other)))(value);
})) {
result.push(value);
}
}
@@ -1852,10 +1890,11 @@
return result;
}
var index = -1,
length = array.length;
length = array.length,
contains = cachedContains(arguments, 1, 20);
while (++index < length) {
if (indexOf(arguments, array[index], 1) < 0) {
if (!contains(array[index])) {
result.push(array[index]);
}
}
@@ -2067,19 +2106,23 @@
* jQuery('#lodash_button').on('click', buttonView.onClick);
* // => When the button is clicked, `this.label` will have the correct value
*/
function bindAll(object) {
var funcs = arguments,
index = 1;
if (funcs.length == 1) {
index = 0;
funcs = functions(object);
}
for (var length = funcs.length; index < length; index++) {
object[funcs[index]] = bind(object[funcs[index]], object);
}
return object;
}
var bindAll = createIterator({
'useHas': false,
'useStrict': false,
'args': 'object',
'init': 'object',
'top':
'var funcs = arguments,\n' +
' length = funcs.length;\n' +
'if (length > 1) {\n' +
' for (var index = 1; index < length; index++)\n' +
' result[funcs[index]] = bind(result[funcs[index]], result);\n' +
' return result\n' +
'}',
'inLoop':
'if (toString.call(result[index]) == funcClass)' +
' result[index] = bind(result[index], result)'
});
/**
* Creates a new function that is the composition of the passed functions,
@@ -2505,9 +2548,9 @@
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/
var functions = createIterator({
'useHas': false,
'args': 'object',
'init': '[]',
'useHas': false,
'inLoop': 'if (toString.call(iteratee[index]) == funcClass) result.push(index)',
'bottom': 'result.sort()'
});
@@ -2550,7 +2593,8 @@
var isArguments = function(value) {
return toString.call(value) == '[object Arguments]';
};
// fallback for browser like IE < 9 which detect `arguments` as `[object Object]`
// fallback for browser like Firefox < 4 and IE < 9 which detect
// `arguments` as `[object Object]`
if (!isArguments(arguments)) {
isArguments = function(value) {
return !!(value && hasOwnProperty.call(value, 'callee'));
@@ -2729,8 +2773,8 @@
case boolClass:
case dateClass:
// coerce dates and booleans to numeric values, dates to milliseconds and booleans to 1 or 0;
// treat invalid dates coerced to `NaN` as not equal
// coerce dates and booleans to numeric values, dates to milliseconds and
// booleans to 1 or 0; treat invalid dates coerced to `NaN` as not equal
return +a == +b;
// regexps are compared by their source and flags
@@ -2775,7 +2819,8 @@
}
}
}
} else {
}
else {
// objects with different constructors are not equivalent
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
return false;
@@ -3560,7 +3605,7 @@
* @memberOf _
* @type String
*/
lodash.VERSION = '0.4.1';
lodash.VERSION = '0.4.2';
// assign static methods
lodash.after = after;
@@ -3690,11 +3735,12 @@
var value = this._wrapped;
func.apply(value, arguments);
// IE compatibility mode and IE < 9 have buggy Array `shift()` and `splice()`
// functions that fail to remove the last element, `value[0]`, of
// array-like objects even though the `length` property is set to `0`.
// The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
// is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
// Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array
// `shift()` and `splice()` functions that fail to remove the last element,
// `value[0]`, of array-like objects even though the `length` property is
// set to `0`. The `shift()` method is buggy in IE 8 compatibility mode,
// while `splice()` is buggy regardless of mode in IE < 9 and buggy in
// compatibility mode in IE 9.
if (value.length === 0) {
delete value[0];
}

64
lodash.min.js vendored
View File

@@ -1,35 +1,35 @@
/*!
Lo-Dash 0.4.1 lodash.com/license
Lo-Dash 0.4.2 lodash.com/license
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
*/
;(function(e,t){"use strict";function s(e){return new o(e)}function o(e){if(e&&e._wrapped)return e;this._wrapped=e}function u(){for(var e,t,n,s=-1,o=arguments.length,u={e:"",f:"",j:"",q:"",c:{d:""},n:{d:""}};++s<o;)for(t in e=arguments[s],e)n=(n=e[t])==r?"":n,/d|i/.test(t)?("string"==typeof n&&(n={b:n,m:n}),u.c[t]=n.b,u.n[t]=n.m):u[t]=n;e=u.a,t=/^[^,]+/.exec(e)[0],u.l=u.l||t,u.g=t,u.h=vt,u.k=bt,u.p=$,u.r=u.r!==i,"o"in u||(u.o=gt),u.f||(u.f="if(!"+t+")return A");if("f"!=t||!u.c.i)u.c=r;t="var A",u.
j&&(t+="="+u.j),t+=";"+u.f+";"+u.q+";var l,n="+u.l+";",u.c&&(t+="var p=n.length;l=-1;",u.n&&(t+="if(p===p>>>0){"),u.o&&(t+="if(I.call(n)==F){n=n.split('')}"),t+=u.c.d+";while(++l<p){"+u.c.i+"}",u.n&&(t+="}"));if(u.n){u.c&&(t+="else{"),u.h||(t+="var B=typeof n=='function'&&z.call(n,'prototype');"),u.k&&u.r?t+="var x=r(n),w=-1,p=x.length;"+u.n.d+";while(++w<p){l=x[w];if(!(B&&l=='prototype')){"+u.n.i+"}}":(t+=u.n.d+";for(l in n){",u.h?(u.r&&(t+="if(j.call(n,l)){"),t+=u.n.i+";",u.r&&(t+="}")):(t+="if(!(B&&l=='prototype')"
,u.r&&(t+="&&j.call(n,l)"),t+="){"+u.n.i+"}"),t+="}");if(u.h){t+="var h=n.constructor;";for(n=0;7>n;n++)t+="l='"+u.p[n]+"';if(","constructor"==u.p[n]&&(t+="!(h&&h.prototype===n)&&"),t+="j.call(n,l)){"+u.n.i+"}"}u.c&&(t+="}")}return t+=u.e+";return A",Function("c,g,i,j,k,o,u,r,z,C,F,I",'"use strict";return function('+e+"){"+t+"}")(ot,a,ft,G,k,h,Et,st,Z,et,ht,tt)}function a(e,n){return e=e.a,n=n.a,e===t?1:n===t?-1:e<n?-1:e>n?1:0}function f(e,t){return K[t]}function l(e){return"\\"+St[e]}function c(
e){return wt[e]}function h(e,t){return function(n,r,i){return e.call(t,n,r,i)}}function p(){}function d(e,t){if(F.test(t))return"<e%-"+t+"%>";var n=K.length;return K[n]="'+__e("+t+")+'",J+n}function v(e,t,n,r){return e=K.length,t?K[e]="';"+t+";__p+='":n?K[e]="'+__e("+n+")+'":r&&(K[e]="'+((__t=("+r+"))==null?'':__t)+'"),J+e}function m(e,t){if(F.test(t))return"<e%="+t+"%>";var n=K.length;return K[n]="'+((__t=("+t+"))==null?'':__t)+'",J+n}function g(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments
.length;r&&(t=h(t,r));if(i===i>>>0){var o=gt&&tt.call(e)==ht?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=Gt(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function y(e,t,n){if(e)return t==r||n?e[0]:et.call(e,0,t)}function b(e,t){var n=[];if(!e)return n;for(var r,i=-1,s=e.length;++i<s;)r=e[i],Kt(r)?Y.apply(n,t?r:b(r)):n.push(r);return n}function w(e,t,n){if(!e)return-1;var r=-1,i=e.length;if(n){if("number"!=typeof n)return r=x(e,t),e[r]===t?r:-1;r=
(0>n?Math.max(0,i+n):n)-1}for(;++r<i;)if(e[r]===t)return r;return-1}function E(e,t,n){var r=-Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]>i&&(i=e[s]);return i}for(n&&(t=h(t,n));++s<o;)n=t(e[s],s,e),n>r&&(r=n,i=e[s]);return i}function S(e,t,n){return e?et.call(e,t==r||n?1:t):[]}function x(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(n=N(n,r));for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+s>>>1,e[r]<t?i=r+1:s=r;return i}function T(e,t,n,r){var s=
[];if(!e)return s;var o=-1,u=e.length,a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n?r&&(n=h(n,r)):n=k;++o<u;)if(r=n(e[o],o,e),t?!o||a[a.length-1]!==r:0>w(a,r))a.push(r),s.push(e[o]);return s}function N(e,t){function n(){var o=arguments,u=t;return i||(e=t[r]),s.length&&(o=o.length?Q.apply(s,o):s),this instanceof n?(p.prototype=e.prototype,u=new p,(o=e.apply(u,o))&&Et[typeof o]?o:u):e.apply(u,o)}var r,i=tt.call(e)==ft;if(i){if(yt||nt&&2<arguments.length)return nt.call.apply(nt,arguments)}else r=t,
t=e;var s=et.call(arguments,2);return n}function C(e,t,s){s||(s=[]);if(e===t)return 0!==e||1/e==1/t;if(e==r||t==r)return e===t;e._chain&&(e=e._wrapped),t._chain&&(t=t._wrapped);if(e.isEqual&&tt.call(e.isEqual)==ft)return e.isEqual(t);if(t.isEqual&&tt.call(t.isEqual)==ft)return t.isEqual(e);var o=tt.call(e);if(o!=tt.call(t))return i;switch(o){case ht:return e==""+t;case lt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case ut:case at:return+e==+t;case ct:return e.source==t.source&&e.global==t.global&&e.multiline==
t.multiline&&e.ignoreCase==t.ignoreCase}if("object"!=typeof e||"object"!=typeof t)return i;for(var u=s.length;u--;)if(s[u]==e)return n;var u=-1,a=n,f=0;s.push(e);if(o==ot){if(f=e.length,a=f==t.length)for(;f--&&(a=C(e[f],t[f],s)););}else{if("constructor"in e!="constructor"in t||e.constructor!=t.constructor)return i;for(var l in e)if(G.call(e,l)&&(f++,!(a=G.call(t,l)&&C(e[l],t[l],s))))break;if(a){for(l in t)if(G.call(t,l)&&!(f--))break;a=!f}if(a&&vt)for(;7>++u&&(l=$[u],!G.call(e,l)||!!(a=G.call(t,l
)&&C(e[l],t[l],s))););}return s.pop(),a}function k(e){return e}function L(e){Ht(Jt(e),function(t){var r=s[t]=e[t];o.prototype[t]=function(){var e=[this._wrapped];return arguments.length&&Y.apply(e,arguments),e=r.apply(s,e),this._chain&&(e=new o(e),e._chain=n),e}})}var n=!0,r=null,i=!1,A,O,M,_,D="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),P=Array.prototype,H=Object.prototype,B=0,j=e._,F=/[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/
,I=/\b__p\+='';/g,q=/\b(__p\+=)''\+/g,R=/(__e\(.*?\)|\b__t\))\+'';/g,U=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,z=RegExp("^"+(H.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),W=/__token__(\d+)/g,X=/[&<"']/g,V=/['\n\r\t\u2028\u2029\\]/g,$="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),J="__token__",K=[],Q=P.concat,G=H.hasOwnProperty,Y=P.push,Z=H.propertyIsEnumerable,et=P.slice,tt=H.toString
,nt=z.test(nt=et.bind)&&nt,rt=z.test(rt=Array.isArray)&&rt,it=e.isFinite,st=z.test(st=Object.keys)&&st,ot="[object Array]",ut="[object Boolean]",at="[object Date]",ft="[object Function]",lt="[object Number]",ct="[object RegExp]",ht="[object String]",pt=e.clearTimeout,dt=e.setTimeout,vt=!Z.call({valueOf:0},"valueOf"),mt="x"!=et.call("x")[0],gt="xx"!="x"[0]+Object("x")[0],yt=nt&&/\n|Opera/.test(nt+tt.call(e.opera)),bt=st&&/^.+$|true/.test(st+!!e.attachEvent),wt={"&":"&amp;","<":"&lt;",'"':"&quot;","'"
:"&#x27;"},Et={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i},St={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"obj"};var xt={a:"f,d,H",j:"f",q:"if(!d){d=k}else if(H)d=o(d,H)",i:"d(n[l],l,f)"},Tt={j:"true",i:"if(!d(n[l],l,f))return!A"},Nt={a:"t",j:"t",q:"for(var D,E=1,p=arguments.length;E<p;E++){D=arguments[E];"+(vt?"if(D){":""),l:"D"
,r:i,i:"A[l]=n[l]",e:(vt?"}":"")+"}"},Ct={j:"[]",i:"d(n[l],l,f)&&A.push(n[l])"},kt={q:"if(H)d=o(d,H)"},Lt={i:{m:xt.i}},At={j:"",f:"if(!f)return[]",d:{b:"A=Array(p)",m:"A="+(bt?"Array(p)":"[]")},i:{b:"A[l]=d(n[l],l,f)",m:"A"+(bt?"[w]=":".push")+"(d(n[l],l,f))"}},Ot=u({a:"t",f:"if(!(t&&u[typeof t]))throw TypeError()",j:"[]",i:"A.push(l)"}),Mt=u({a:"f,G",j:"false",o:i,d:{b:"if(I.call(n)==F)return f.indexOf(G)>-1"},i:"if(n[l]===G)return true"}),_t=u(xt,Tt),Dt=u(xt,Ct),Pt=u(xt,kt,{j:"",i:"if(d(n[l],l,f))return n[l]"
}),Ht=u(xt,kt),Bt=u(xt,{j:"{}",q:"var v,m=typeof d=='function';if(m&&H)d=o(d,H)",i:"v=m?d(n[l],l,f):n[l][d];(j.call(A,v)?A[v]:A[v]=[]).push(n[l])"}),jt=u(At,{a:"f,q",q:"var b=C.call(arguments,2),m=typeof q=='function'",i:{b:"A[l]=(m?q:n[l][q]).apply(n[l],b)",m:"A"+(bt?"[w]=":".push")+"((m?q:n[l][q]).apply(n[l],b))"}}),Ft=u(xt,At),It=u(At,{a:"f,y",i:{b:"A[l]=n[l][y]",m:"A"+(bt?"[w]=":".push")+"(n[l][y])"}}),qt=u({a:"f,d,a,H",j:"a",q:"var s=arguments.length<3;if(H)d=o(d,H)",d:{b:"if(s)A=f[++l]"},i:
{b:"A=d(A,n[l],l,f)",m:"A=s?(s=false,n[l]):d(A,n[l],l,f)"}}),Rt=u(xt,Ct,{i:"!"+Ct.i}),Ut=u(xt,Tt,{j:"false",i:Tt.i.replace("!","")}),zt=u(xt,At,{q:"if(typeof d=='string'){var v=d;d=function(f){return f[v]}}else if(H)d=o(d,H)",i:{b:"A[l]={a:d(n[l],l,f),b:n[l]}",m:"A"+(bt?"[w]=":".push")+"({a:d(n[l],l,f),b:n[l]})"},e:"A.sort(g);p=A.length;while(p--){A[p]=A[p].b}"}),Wt=u(Nt,{i:"if(A[l]==null)"+Nt.i}),Xt=u(Nt),Vt=u(xt,kt,Lt,{r:i}),$t=u(xt,kt,Lt),Jt=u({a:"t",j:"[]",r:i,i:"if(I.call(n[l])==i)A.push(l)"
,e:"A.sort()"});Ht({Arguments:"[object Arguments]",Date:at,Function:ft,Number:lt,RegExp:ct,String:ht},function(e,t){s["is"+t]=function(t){return tt.call(t)==e}}),s.isArguments(arguments)||(s.isArguments=function(e){return!!e&&!!G.call(e,"callee")});var Kt=rt||function(e){return tt.call(e)==ot},Qt=u({a:"J",j:"true",q:"var e=I.call(J);if(e==c||e==F)return!J.length",i:{m:"return false"}}),Gt=st?function(e){return"function"==typeof e&&Z.call(e,"prototype")?Ot(e):st(e)}:Ot,Yt=u({a:"t",j:"[]",i:"A.push(n[l])"
});s.VERSION="0.4.1",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=N,s.bindAll=function(e){var t=arguments,n=1;1==t.length&&(n=0,t=Jt(e));for(var r=t.length;n<r;n++)e[t[n]]=N(e[t[n]],e);return e},s.chain=function(e){return e=new o(e),e._chain=n,e},s.clone=function(e){return e&&Et[typeof e]?Kt(e)?e.slice():Xt({},e):e},s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++n<r;)e[n]&&t.push(e[n]);return t},s.compose=function(){var e=
arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=Mt,s.debounce=function(e,t,n){function i(){a=r,n||e.apply(u,s)}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,pt(a),a=dt(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=Wt,s.defer=function(e){var n=et.call(arguments,1);return dt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=et.call(arguments,2);return dt(function(){return e.apply(t,r)},n)},s.difference=function(
e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=Q.apply(t,arguments);++n<r;)0>w(i,e[n],r)&&t.push(e[n]);return t},s.escape=function(e){return e==r?"":(e+"").replace(X,c)},s.every=_t,s.extend=Xt,s.filter=Dt,s.find=Pt,s.first=y,s.flatten=b,s.forEach=Ht,s.forIn=Vt,s.forOwn=$t,s.functions=Jt,s.groupBy=Bt,s.has=function(e,t){return G.call(e,t)},s.identity=k,s.indexOf=w,s.initial=function(e,t,n){return e?et.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=[];if(!e)return t;for(var n,r=-1
,i=e.length,s=et.call(arguments,1);++r<i;)n=e[r],0>w(t,n)&&_t(s,function(e){return-1<w(e,n)})&&t.push(n);return t},s.invoke=jt,s.isArray=Kt,s.isBoolean=function(e){return e===n||e===i||tt.call(e)==ut},s.isElement=function(e){return!!e&&1==e.nodeType},s.isEmpty=Qt,s.isEqual=C,s.isFinite=function(e){return it(e)&&tt.call(e)==lt},s.isNaN=function(e){return tt.call(e)==lt&&e!=+e},s.isNull=function(e){return e===r},s.isObject=function(e){return e&&Et[typeof e]},s.isUndefined=function(e){return e===t},
s.keys=Gt,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:et.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){if(!e)return-1;var r=e.length;for(n&&"number"==typeof n&&(r=(0>n?Math.max(0,r+n):Math.min(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.map=Ft,s.max=E,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return G.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=e.length
;if(!t){for(;++s<o;)e[s]<i&&(i=e[s]);return i}for(n&&(t=h(t,n));++s<o;)n=t(e[s],s,e),n<r&&(r=n,i=e[s]);return i},s.mixin=L,s.noConflict=function(){return e._=j,this},s.once=function(e){var t,r=i;return function(){return r?t:(r=n,t=e.apply(this,arguments))}},s.partial=function(e){var t=et.call(arguments,1),n=t.length;return function(){var r;return r=arguments,r.length&&(t.length=n,Y.apply(t,r)),r=1==t.length?e.call(this,t[0]):e.apply(this,t),t.length=n,r}},s.pick=function(e){for(var t,n=0,r=Q.apply
(P,arguments),i=r.length,s={};++n<i;)t=r[n],t in e&&(s[t]=e[t]);return s},s.pluck=It,s.range=function(e,t,n){n||(n=1),t==r&&(t=e||0,e=0);for(var i=-1,t=Math.max(0,Math.ceil((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=qt,s.reduceRight=g,s.reject=Rt,s.rest=S,s.result=function(e,t){if(!e)return r;var n=e[t];return tt.call(n)==ft?e[t]():n},s.shuffle=function(e){if(!e)return[];for(var t,n=-1,r=e.length,i=Array(r);++n<r;)t=Math.floor(Math.random()*(n+1)),i[n]=i[t],i[t]=e[n];return i},s.size=
function(e){if(!e)return 0;var t=e.length;return t===t>>>0?e.length:Gt(e).length},s.some=Ut,s.sortBy=zt,s.sortedIndex=x,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var i,o;i=n.escape;var u=n.evaluate,a=n.interpolate,c=s.templateSettings,n=n.variable;i==r&&(i=c.escape),u==r&&(u=c.evaluate),a==r&&(a=c.interpolate),i&&(e=e.replace(i,d)),a&&(e=e.replace(a,m)),u!=A&&(A=u,_=RegExp((u?u.source:"($^)")+"|<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>","g")),i=K.length,e=e.replace(_,v),
i=i!=K.length,e="__p += '"+e.replace(V,l).replace(W,f)+"';",K.length=0,n||(n=c.variable||O||"obj",i?e="with("+n+"){"+e+"}":(n!=O&&(O=n,M=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(U,"$&"+n+".").replace(M,"$1__d"))),e=(i?e.replace(I,""):e).replace(q,"$1").replace(R,"$1;"),e="function("+n+"){"+n+"||("+n+"={});var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":",__d="+n+"."+n+"||"+n+";")+e+"return __p}";try{o=Function("_","return "+e)(
s)}catch(h){o=function(){throw h}}return t?o(t):(o.source=e,o)},s.throttle=function(e,t){function n(){a=new Date,u=r,e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e.apply(o,i)):u||(u=dt(n,f)),s}},s.times=function(e,t,n){var r=-1;if(n)for(;++r<e;)t.call(n,r);else for(;++r<e;)t(r)},s.toArray=function(e){if(!e)return[];if(e.toArray&&tt.call(e.toArray)==ft)return e.toArray();var t=e.length;return t===t>>>0?(mt?tt.call(e)==ht:"string"==typeof
e)?e.split(""):et.call(e):Yt(e)},s.union=function(){for(var e=-1,t=[],n=Q.apply(t,arguments),r=n.length;++e<r;)0>w(t,n[e])&&t.push(n[e]);return t},s.uniq=T,s.uniqueId=function(e){var t=B++;return e?e+t:t},s.values=Yt,s.without=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++n<r;)0>w(arguments,e[n],1)&&t.push(e[n]);return t},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&Y.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){if(!e)return[];for(var t=-1,n=
E(It(arguments,"length")),r=Array(n);++t<n;)r[t]=It(arguments,t);return r},s.zipObject=function(e,t){if(!e)return{};var n=-1,r=e.length,i={};for(t||(t=[]);++n<r;)i[e[n]]=t[n];return i},s.all=_t,s.any=Ut,s.collect=Ft,s.detect=Pt,s.each=Ht,s.foldl=qt,s.foldr=g,s.head=y,s.include=Mt,s.inject=qt,s.methods=Jt,s.select=Dt,s.tail=S,s.take=y,s.unique=T,o.prototype=s.prototype,L(s),o.prototype.chain=function(){return this._chain=n,this},o.prototype.value=function(){return this._wrapped},Ht("pop push reverse shift sort splice unshift"
.split(" "),function(e){var t=P[e];o.prototype[e]=function(){var e=this._wrapped;return t.apply(e,arguments),e.length===0&&delete e[0],this._chain&&(e=new o(e),e._chain=n),e}}),Ht(["concat","join","slice"],function(e){var t=P[e];o.prototype[e]=function(){var e=t.apply(this._wrapped,arguments);return this._chain&&(e=new o(e),e._chain=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):D?"object"==typeof module&&module&&module.s==D?(module
.s=s)._=s:D._=s:e._=s})(this);
;(function(e,t){"use strict";function s(e){return new o(e)}function o(e){if(e&&e._wrapped)return e;this._wrapped=e}function u(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||30),s=i?{}:e;if(i)for(var o=t-1;++o<r;)n=e[o]+"",(Y.call(s,n)?s[n]:s[n]=[]).push(e[o]);return function(e){if(i){var n=e+"";return Y.call(s,n)&&-1<E(s[n],e)}return-1<E(s,e,t)}}function a(){for(var e,t,n,s=-1,o=arguments.length,u={e:"",f:"",j:"",p:"",c:{d:""},m:{d:""}};++s<o;)for(t in e=arguments[s],e)n=(n=e[t])==r?"":n,/d|i/.test(t)?
("string"==typeof n&&(n={b:n,l:n}),u.c[t]=n.b,u.m[t]=n.l):u[t]=n;e=u.a,t=/^[^,]+/.exec(e)[0],u.g=t,u.h=mt,u.k=wt,u.o=J,u.q=u.q!==i,u.r=u.r!==i,"n"in u||(u.n=yt),u.f||(u.f="if(!"+t+")return D");if("g"!=t||!u.c.i)u.c=r;t="",u.r&&(t+="'use strict';"),t+="var n,p="+u.g+",D",u.j&&(t+="="+u.j),t+=";"+u.f+";"+u.p+";",u.c&&(t+="var s=p.length;n=-1;",u.m&&(t+="if(s===s>>>0){"),u.n&&(t+="if(J.call(p)==G){p=p.split('')}"),t+=u.c.d+";while(++n<s){"+u.c.i+"}",u.m&&(t+="}"));if(u.m){u.c&&(t+="else{"),u.h||(t+="var E=typeof p=='function'&&C.call(p,'prototype');"
),u.k&&u.q?t+="var A=u(p),z=-1,s=A.length;"+u.m.d+";while(++z<s){n=A[z];if(!(E&&n=='prototype')){"+u.m.i+"}}":(t+=u.m.d+";for(n in p){",u.h?(u.q&&(t+="if(l.call(p,n)){"),t+=u.m.i+";",u.q&&(t+="}")):(t+="if(!(E&&n=='prototype')",u.q&&(t+="&&l.call(p,n)"),t+="){"+u.m.i+"}"),t+="}");if(u.h){t+="var i=p.constructor;";for(n=0;7>n;n++)t+="n='"+u.o[n]+"';if(","constructor"==u.o[n]&&(t+="!(i&&i.prototype===p)&&"),t+="l.call(p,n)){"+u.m.i+"}"}u.c&&(t+="}")}return t+=u.e+";return D",Function("c,d,h,j,l,m,r,x,u,C,F,G,J"
,"return function("+e+"){"+t+"}")(ut,C,f,lt,Y,L,p,St,ot,et,tt,pt,nt)}function f(e,n){return e=e.a,n=n.a,e===t?1:n===t?-1:e<n?-1:e>n?1:0}function l(e,t){return Q[t]}function c(e){return"\\"+xt[e]}function h(e){return Et[e]}function p(e,t){return function(n,r,i){return e.call(t,n,r,i)}}function d(){}function v(e,t){if(I.test(t))return"<e%-"+t+"%>";var n=Q.length;return Q[n]="'+__e("+t+")+'",K+n}function m(e,t,n,r){return e=Q.length,t?Q[e]="';"+t+";__p+='":n?Q[e]="'+__e("+n+")+'":r&&(Q[e]="'+((__t=("+
r+"))==null?'':__t)+'"),K+e}function g(e,t){if(I.test(t))return"<e%="+t+"%>";var n=Q.length;return Q[n]="'+((__t=("+t+"))==null?'':__t)+'",K+n}function y(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments.length;r&&(t=p(t,r));if(i===i>>>0){var o=yt&&nt.call(e)==pt?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=Zt(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function b(e,t,n){if(e)return t==r||n?e[0]:tt.call(e,0,t)}function w(e,t){var n=[];if(!e)
return n;for(var r,i=-1,s=e.length;++i<s;)r=e[i],Gt(r)?Z.apply(n,t?r:w(r)):n.push(r);return n}function E(e,t,n){if(!e)return-1;var r=-1,i=e.length;if(n){if("number"!=typeof n)return r=T(e,t),e[r]===t?r:-1;r=(0>n?Math.max(0,i+n):n)-1}for(;++r<i;)if(e[r]===t)return r;return-1}function S(e,t,n){var r=-Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]>i&&(i=e[s]);return i}for(n&&(t=p(t,n));++s<o;)n=t(e[s],s,e),n>r&&(r=n,i=e[s]);return i}function x(e,t,n){return e?tt.call(e,t==r||
n?1:t):[]}function T(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(n=C(n,r));for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+s>>>1,e[r]<t?i=r+1:s=r;return i}function N(e,t,n,r){var s=[];if(!e)return s;var o=-1,u=e.length,a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n?r&&(n=p(n,r)):n=L;++o<u;)if(r=n(e[o],o,e),t?!o||a[a.length-1]!==r:0>E(a,r))a.push(r),s.push(e[o]);return s}function C(e,t){function n(){var o=arguments,u=t;return i||(e=t[r]),s.length&&(o=o.length?G.apply(s,o)
:s),this instanceof n?(d.prototype=e.prototype,u=new d,(o=e.apply(u,o))&&St[typeof o]?o:u):e.apply(u,o)}var r,i=nt.call(e)==lt;if(i){if(bt||rt&&2<arguments.length)return rt.call.apply(rt,arguments)}else r=t,t=e;var s=tt.call(arguments,2);return n}function k(e,t,s){s||(s=[]);if(e===t)return 0!==e||1/e==1/t;if(e==r||t==r)return e===t;e._chain&&(e=e._wrapped),t._chain&&(t=t._wrapped);if(e.isEqual&&nt.call(e.isEqual)==lt)return e.isEqual(t);if(t.isEqual&&nt.call(t.isEqual)==lt)return t.isEqual(e);var o=
nt.call(e);if(o!=nt.call(t))return i;switch(o){case pt:return e==""+t;case ct:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case at:case ft:return+e==+t;case ht:return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if("object"!=typeof e||"object"!=typeof t)return i;for(var u=s.length;u--;)if(s[u]==e)return n;var u=-1,a=n,f=0;s.push(e);if(o==ut){if(f=e.length,a=f==t.length)for(;f--&&(a=k(e[f],t[f],s)););}else{if("constructor"in e!="constructor"in t||e.constructor!=
t.constructor)return i;for(var l in e)if(Y.call(e,l)&&(f++,!(a=Y.call(t,l)&&k(e[l],t[l],s))))break;if(a){for(l in t)if(Y.call(t,l)&&!(f--))break;a=!f}if(a&&mt)for(;7>++u&&(l=J[u],!Y.call(e,l)||!!(a=Y.call(t,l)&&k(e[l],t[l],s))););}return s.pop(),a}function L(e){return e}function A(e){Bt(Qt(e),function(t){var r=s[t]=e[t];o.prototype[t]=function(){var e=[this._wrapped];return arguments.length&&Z.apply(e,arguments),e=r.apply(s,e),this._chain&&(e=new o(e),e._chain=n),e}})}var n=!0,r=null,i=!1,O,M,_,D
,P="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),H=Array.prototype,B=Object.prototype,j=0,F=e._,I=/[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,q=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,z=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,W=RegExp("^"+(B.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/__token__(\d+)/g,V=/[&<"']/g,$=/['\n\r\t\u2028\u2029\\]/g
,J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),K="__token__",Q=[],G=H.concat,Y=B.hasOwnProperty,Z=H.push,et=B.propertyIsEnumerable,tt=H.slice,nt=B.toString,rt=W.test(rt=tt.bind)&&rt,it=W.test(it=Array.isArray)&&it,st=e.isFinite,ot=W.test(ot=Object.keys)&&ot,ut="[object Array]",at="[object Boolean]",ft="[object Date]",lt="[object Function]",ct="[object Number]",ht="[object RegExp]",pt="[object String]",dt=e.clearTimeout,vt=e.setTimeout
,mt=!et.call({valueOf:0},"valueOf"),gt="x"!=tt.call("x")[0],yt="xx"!="x"[0]+Object("x")[0],bt=rt&&/\n|Opera/.test(rt+nt.call(e.opera)),wt=ot&&/^.+$|true/.test(ot+!!e.attachEvent),Et={"&":"&amp;","<":"&lt;",'"':"&quot;","'":"&#x27;"},St={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i},xt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"obj"
};var Tt={a:"g,e,I",j:"g",p:"if(!e){e=m}else if(I)e=r(e,I)",i:"e(p[n],n,g)"},Nt={j:"true",i:"if(!e(p[n],n,g))return!D"},Ct={q:i,r:i,a:"w",j:"w",p:"for(var q=1,s=arguments.length;q<s;q++){p=arguments[q];"+(mt?"if(p){":""),i:"D[n]=p[n]",e:(mt?"}":"")+"}"},kt={j:"[]",i:"e(p[n],n,g)&&D.push(p[n])"},Lt={p:"if(I)e=r(e,I)"},At={i:{l:Tt.i}},Ot={j:"",f:"if(!g)return[]",d:{b:"D=Array(s)",l:"D="+(wt?"Array(s)":"[]")},i:{b:"D[n]=e(p[n],n,g)",l:"D"+(wt?"[z]=":".push")+"(e(p[n],n,g))"}},Mt=a({a:"w",f:"if(!(w&&x[typeof w]))throw TypeError()"
,j:"[]",i:"D.push(n)"}),_t=a({a:"g,H",j:"false",n:i,d:{b:"if(J.call(p)==G)return g.indexOf(H)>-1"},i:"if(p[n]===H)return true"}),Dt=a(Tt,Nt),Pt=a(Tt,kt),Ht=a(Tt,Lt,{j:"",i:"if(e(p[n],n,g))return p[n]"}),Bt=a(Tt,Lt),jt=a(Tt,{j:"{}",p:"var y,o=typeof e=='function';if(o&&I)e=r(e,I)",i:"y=o?e(p[n],n,g):p[n][e];(l.call(D,y)?D[y]:D[y]=[]).push(p[n])"}),Ft=a(Ot,{a:"g,t",p:"var b=F.call(arguments,2),o=typeof t=='function'",i:{b:"D[n]=(o?t:p[n][t]).apply(p[n],b)",l:"D"+(wt?"[z]=":".push")+"((o?t:p[n][t]).apply(p[n],b))"
}}),It=a(Tt,Ot),qt=a(Ot,{a:"g,B",i:{b:"D[n]=p[n][B]",l:"D"+(wt?"[z]=":".push")+"(p[n][B])"}}),Rt=a({a:"g,e,a,I",j:"a",p:"var v=arguments.length<3;if(I)e=r(e,I)",d:{b:"if(v)D=g[++n]"},i:{b:"D=e(D,p[n],n,g)",l:"D=v?(v=false,p[n]):e(D,p[n],n,g)"}}),Ut=a(Tt,kt,{i:"!"+kt.i}),zt=a(Tt,Nt,{j:"false",i:Nt.i.replace("!","")}),Wt=a(Tt,Ot,{p:"if(typeof e=='string'){var y=e;e=function(g){return g[y]}}else if(I)e=r(e,I)",i:{b:"D[n]={a:e(p[n],n,g),b:p[n]}",l:"D"+(wt?"[z]=":".push")+"({a:e(p[n],n,g),b:p[n]})"},e
:"D.sort(h);s=D.length;while(s--){D[s]=D[s].b}"}),Xt=a({q:i,r:i,a:"w",j:"w",p:"var k=arguments,s=k.length;if(s>1){for(var n=1;n<s;n++)D[k[n]]=d(D[k[n]],D);return D}",i:"if(J.call(D[n])==j)D[n]=d(D[n],D)"}),Vt=a(Ct,{i:"if(D[n]==null)"+Ct.i}),$t=a(Ct),Jt=a(Tt,Lt,At,{q:i}),Kt=a(Tt,Lt,At),Qt=a({q:i,a:"w",j:"[]",i:"if(J.call(p[n])==j)D.push(n)",e:"D.sort()"});Bt({Arguments:"[object Arguments]",Date:ft,Function:lt,Number:ct,RegExp:ht,String:pt},function(e,t){s["is"+t]=function(t){return nt.call(t)==e}}
),s.isArguments(arguments)||(s.isArguments=function(e){return!!e&&!!Y.call(e,"callee")});var Gt=it||function(e){return nt.call(e)==ut},Yt=a({a:"K",j:"true",p:"var f=J.call(K);if(f==c||f==G)return!K.length",i:{l:"return false"}}),Zt=ot?function(e){return"function"==typeof e&&et.call(e,"prototype")?Mt(e):ot(e)}:Mt,en=a({a:"w",j:"[]",i:"D.push(p[n])"});s.VERSION="0.4.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=C,s.bindAll=Xt,s.chain=function(e)
{return e=new o(e),e._chain=n,e},s.clone=function(e){return e&&St[typeof e]?Gt(e)?e.slice():$t({},e):e},s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++n<r;)e[n]&&t.push(e[n]);return t},s.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=_t,s.debounce=function(e,t,n){function i(){a=r,n||e.apply(u,s)}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,dt(a),a=vt(i,t),r&&(o=
e.apply(u,s)),o}},s.defaults=Vt,s.defer=function(e){var n=tt.call(arguments,1);return vt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=tt.call(arguments,2);return vt(function(){return e.apply(t,r)},n)},s.difference=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=G.apply(t,arguments),i=u(i,r);++n<r;)i(e[n])||t.push(e[n]);return t},s.escape=function(e){return e==r?"":(e+"").replace(V,h)},s.every=Dt,s.extend=$t,s.filter=Pt,s.find=Ht,s.first=b,s.flatten=w,s.forEach=Bt,
s.forIn=Jt,s.forOwn=Kt,s.functions=Qt,s.groupBy=jt,s.has=function(e,t){return Y.call(e,t)},s.identity=L,s.indexOf=E,s.initial=function(e,t,n){return e?tt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=[];if(!e)return t;for(var n,r=-1,i=e.length,s=tt.call(arguments,1),o=[];++r<i;)n=e[r],0>E(t,n)&&Dt(s,function(e,t){return(o[t]||(o[t]=u(e)))(n)})&&t.push(n);return t},s.invoke=Ft,s.isArray=Gt,s.isBoolean=function(e){return e===n||e===i||nt.call(e)==at},s.isElement=function(e){return!!
e&&1==e.nodeType},s.isEmpty=Yt,s.isEqual=k,s.isFinite=function(e){return st(e)&&nt.call(e)==ct},s.isNaN=function(e){return nt.call(e)==ct&&e!=+e},s.isNull=function(e){return e===r},s.isObject=function(e){return e&&St[typeof e]},s.isUndefined=function(e){return e===t},s.keys=Zt,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:tt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){if(!e)return-1;var r=e.length;for(n&&"number"==typeof n&&(r=(0>n?Math.max(0,r+n):Math.min(n,r-1))+1);r--;)if(
e[r]===t)return r;return-1},s.map=It,s.max=S,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return Y.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]<i&&(i=e[s]);return i}for(n&&(t=p(t,n));++s<o;)n=t(e[s],s,e),n<r&&(r=n,i=e[s]);return i},s.mixin=A,s.noConflict=function(){return e._=F,this},s.once=function(e){var t,r=i;return function(){return r?t:(r=n,t=
e.apply(this,arguments))}},s.partial=function(e){var t=tt.call(arguments,1),n=t.length;return function(){var r;return r=arguments,r.length&&(t.length=n,Z.apply(t,r)),r=1==t.length?e.call(this,t[0]):e.apply(this,t),t.length=n,r}},s.pick=function(e){for(var t,n=0,r=G.apply(H,arguments),i=r.length,s={};++n<i;)t=r[n],t in e&&(s[t]=e[t]);return s},s.pluck=qt,s.range=function(e,t,n){n||(n=1),t==r&&(t=e||0,e=0);for(var i=-1,t=Math.max(0,Math.ceil((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=
Rt,s.reduceRight=y,s.reject=Ut,s.rest=x,s.result=function(e,t){if(!e)return r;var n=e[t];return nt.call(n)==lt?e[t]():n},s.shuffle=function(e){if(!e)return[];for(var t,n=-1,r=e.length,i=Array(r);++n<r;)t=Math.floor(Math.random()*(n+1)),i[n]=i[t],i[t]=e[n];return i},s.size=function(e){if(!e)return 0;var t=e.length;return t===t>>>0?e.length:Zt(e).length},s.some=zt,s.sortBy=Wt,s.sortedIndex=T,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var i,o;i=n.escape;var u=n.evaluate,
a=n.interpolate,f=s.templateSettings,n=n.variable;i==r&&(i=f.escape),u==r&&(u=f.evaluate),a==r&&(a=f.interpolate),i&&(e=e.replace(i,v)),a&&(e=e.replace(a,g)),u!=O&&(O=u,D=RegExp((u?u.source:"($^)")+"|<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>","g")),i=Q.length,e=e.replace(D,m),i=i!=Q.length,e="__p += '"+e.replace($,c).replace(X,l)+"';",Q.length=0,n||(n=f.variable||M||"obj",i?e="with("+n+"){"+e+"}":(n!=M&&(M=n,_=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(z,"$&"+n+".").replace(_,"$1__d"))),e=(
i?e.replace(q,""):e).replace(R,"$1").replace(U,"$1;"),e="function("+n+"){"+n+"||("+n+"={});var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":",__d="+n+"."+n+"||"+n+";")+e+"return __p}";try{o=Function("_","return "+e)(s)}catch(h){o=function(){throw h}}return t?o(t):(o.source=e,o)},s.throttle=function(e,t){function n(){a=new Date,u=r,e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e
.apply(o,i)):u||(u=vt(n,f)),s}},s.times=function(e,t,n){var r=-1;if(n)for(;++r<e;)t.call(n,r);else for(;++r<e;)t(r)},s.toArray=function(e){if(!e)return[];if(e.toArray&&nt.call(e.toArray)==lt)return e.toArray();var t=e.length;return t===t>>>0?(gt?nt.call(e)==pt:"string"==typeof e)?e.split(""):tt.call(e):en(e)},s.union=function(){for(var e=-1,t=[],n=G.apply(t,arguments),r=n.length;++e<r;)0>E(t,n[e])&&t.push(n[e]);return t},s.uniq=N,s.uniqueId=function(e){var t=j++;return e?e+t:t},s.values=en,s.without=
function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=u(arguments,1,20);++n<r;)i(e[n])||t.push(e[n]);return t},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&Z.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){if(!e)return[];for(var t=-1,n=S(qt(arguments,"length")),r=Array(n);++t<n;)r[t]=qt(arguments,t);return r},s.zipObject=function(e,t){if(!e)return{};var n=-1,r=e.length,i={};for(t||(t=[]);++n<r;)i[e[n]]=t[n];return i},s.all=Dt,s.any=zt,s.collect=It,s.detect=
Ht,s.each=Bt,s.foldl=Rt,s.foldr=y,s.head=b,s.include=_t,s.inject=Rt,s.methods=Qt,s.select=Pt,s.tail=x,s.take=b,s.unique=N,o.prototype=s.prototype,A(s),o.prototype.chain=function(){return this._chain=n,this},o.prototype.value=function(){return this._wrapped},Bt("pop push reverse shift sort splice unshift".split(" "),function(e){var t=H[e];o.prototype[e]=function(){var e=this._wrapped;return t.apply(e,arguments),e.length===0&&delete e[0],this._chain&&(e=new o(e),e._chain=n),e}}),Bt(["concat","join"
,"slice"],function(e){var t=H[e];o.prototype[e]=function(){var e=t.apply(this._wrapped,arguments);return this._chain&&(e=new o(e),e._chain=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):P?"object"==typeof module&&module&&module.s==P?(module.s=s)._=s:P._=s:e._=s})(this);

View File

@@ -1,6 +1,6 @@
{
"name": "lodash",
"version": "0.4.1",
"version": "0.4.2",
"description": "A drop-in replacement for Underscore.js that delivers performance improvements, bug fixes, and additional features.",
"homepage": "http://lodash.com",
"main": "lodash",

View File

@@ -21,28 +21,37 @@
var lodash = _.noConflict();
</script>
<script src="../vendor/underscore/underscore.js"></script>
<script src="../vendor/platform.js/platform.js"></script>
<script src="../vendor/benchmark.js/benchmark.js"></script>
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
<script src="perf.js"></script>
<script>
(function() {
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
var useApplet = !/[?&]nojava=true(?:&|$)/.test(location.search);
function init() {
var fbUI = document.getElementById('FirebugUI'),
fbDoc = fbUI && (fbDoc = fbUI.contentWindow || fbUI.contentDocument).document || fbDoc,
fbCommandLine = fbDoc && fbDoc.getElementById('fbCommandLine');
if (!fbCommandLine) {
return setTimeout(init, 15);
}
fbUI.style.height = fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
// give applet time to initialize
lodash.delay(run, useApplet ? 500 : 15);
}
if (useApplet) {
// using innerHTML avoids an alert in some versions of IE6
var div = document.createElement('div');
div.innerHTML = '<applet code=nano archive="../vendor/benchmark.js/nano.jar">';
document.body.insertBefore(div.lastChild, document.body.firstChild);
}
window.onload = init;
}());
window.onload = function() {
var fbUI = document.getElementById('FirebugUI'),
fbDoc = (fbDoc = fbUI.contentWindow || fbUI.contentDocument).document || fbDoc,
sibling = document.getElementsByTagName('script')[0],
script = document.createElement('script');
fbUI.style.height = fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
script.src = 'perf.js?t=' + (+new Date);
sibling.parentNode.insertBefore(script, sibling);
};
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,14 @@
</head>
<body>
<div id="qunit"></div>
<script src="../vendor/qunit/qunit/qunit.js"></script>
<script src="../vendor/platform.js/platform.js"></script>
<script>
// avoid syntax errors for `QUnit.throws` in older Firefoxes
document.write(platform.name == 'Firefox' && /^1\b/.test(platform.version)
? '<script src="../vendor/qunit/qunit/qunit-1.8.0.js"><\/script>'
: '<script src="../vendor/qunit/qunit/qunit.js"><\/script>'
);
</script>
<script src="test-ui.js"></script>
<script>
// set a bad shim
@@ -59,6 +66,17 @@
require(['test.js']);
});
// set a more readable browser name
window.onload = function() {
var timeoutId = setInterval(function() {
var ua = document.getElementById('qunit-userAgent');
if (ua) {
ua.innerHTML = platform;
clearInterval(timeoutId);
}
}, 15);
};
</script>
</body>
</html>

View File

@@ -45,10 +45,10 @@
}
function init() {
var header = document.getElementById('qunit-header');
if (header) {
header.appendChild(label1);
header.appendChild(label2);
var toolbar = document.getElementById('qunit-testrunner-toolbar');
if (toolbar) {
toolbar.appendChild(label1);
toolbar.appendChild(label2);
dropdown.selectedIndex = (function() {
switch (build) {
@@ -70,19 +70,19 @@
var label1 = document.createElement('label');
label1.innerHTML =
'<input name="norequire" type="checkbox">norequire</label>';
'<input name="norequire" type="checkbox">No RequireJS</label>';
var label2 = document.createElement('label');
label2.innerHTML =
label2.innerHTML = ' ' +
'<select name="build">' +
'<option value="dev">developement</option>' +
'<option value="prod">production</option>' +
'<option value="custom">custom</option>' +
'<option value="custom-debug">custom (debug)</option>' +
'</select>build';
'<option value="dev">Developement</option>' +
'<option value="prod">Production</option>' +
'<option value="custom">Custom</option>' +
'<option value="custom-debug">Custom (debug)</option>' +
'</select> Build';
var checkbox = label1.firstChild,
dropdown = label2.firstChild;
dropdown = label2.getElementsByTagName('select')[0];
init();
});

View File

@@ -4,11 +4,17 @@
/** Use a single load function */
var load = typeof require == 'function' ? require : window.load;
/** The `platform` object to check */
var platform =
window.platform ||
load('../vendor/platform.js/platform.js') ||
window.platform;
/** The unit testing framework */
var QUnit =
window.QUnit || (
window.setTimeout || (window.addEventListener = window.setTimeout = / /),
window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit,
window.QUnit = load('../vendor/qunit/qunit/qunit' + (platform.name == 'Narwhal' ? '-1.8.0' : '') + '.js') || window.QUnit,
load('../vendor/qunit-clib/qunit-clib.js'),
(window.addEventListener || 0).test && delete window.addEventListener,
window.QUnit
@@ -21,6 +27,9 @@
_._ || _
);
/** Shortcut used to make object properties immutable */
var freeze = Object.freeze;
/** Shortcut used to convert array-like objects to arrays */
var slice = [].slice;
@@ -52,9 +61,10 @@
* Skips a given number of tests with a passing result.
*
* @private
* @param {Number} count The number of tests to skip.
* @param {Number} [count=1] The number of tests to skip.
*/
function skipTest(count) {
count || (count = 1);
while (count--) {
ok(true, 'test skipped');
}
@@ -71,7 +81,7 @@
if (window.document && window.require) {
equal((lodashModule || {}).moduleName, 'lodash');
} else {
skipTest(1)
skipTest()
}
});
@@ -79,7 +89,7 @@
if (window.document && window.require) {
equal((underscoreModule || {}).moduleName, 'underscore');
} else {
skipTest(1)
skipTest()
}
});
@@ -87,7 +97,7 @@
if (window.document) {
notDeepEqual(lodashBadShim.keys({ 'a': 1 }), []);
} else {
skipTest(1);
skipTest();
}
});
}());
@@ -162,6 +172,25 @@
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.difference');
(function() {
test('should work correctly when using `cachedContains`', function() {
var array1 = _.range(27),
array2 = array1.slice(),
a = {},
b = {},
c = {};
array1.push(a, b, c);
array2.push(b, c, a);
deepEqual(_.difference(array1, array2), []);
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.escape');
(function() {
@@ -209,6 +238,35 @@
/*--------------------------------------------------------------------------*/
_.each(['bindAll', 'defaults', 'extend'], function(methodName) {
var func = _[methodName];
QUnit.module('lodash.' + methodName + ' strict mode checks');
test('should not throw strict mode errors', function() {
var object = { 'a': null, 'b': function(){} },
pass = true;
if (freeze) {
freeze(object);
try {
if (methodName == 'bindAll') {
func(object);
} else {
func(object, { 'a': 1 });
}
} catch(e) {
pass = false;
}
ok(pass);
}
else {
skipTest();
}
});
});
/*--------------------------------------------------------------------------*/
QUnit.module('lodash.find');
(function() {

View File

@@ -2698,20 +2698,18 @@
sample = bench.stats.sample;
/**
* Adds a number of clones to the queue.
* Adds a clone to the queue.
*/
function enqueue(count) {
while (count--) {
queue.push(bench.clone({
'_original': bench,
'events': {
'abort': [update],
'cycle': [update],
'error': [update],
'start': [update]
}
}));
}
function enqueue() {
queue.push(bench.clone({
'_original': bench,
'events': {
'abort': [update],
'cycle': [update],
'error': [update],
'start': [update]
}
}));
}
/**
@@ -2817,14 +2815,14 @@
}
// if time permits, increase sample size to reduce the margin of error
if (queue.length < 2 && !maxedOut) {
enqueue(1);
enqueue();
}
// abort the invoke cycle when done
event.aborted = done;
}
// init queue and begin
enqueue(minSamples);
enqueue();
invoke(queue, {
'name': 'run',
'args': { 'async': async },

20
vendor/platform.js/LICENSE.txt vendored Normal file
View File

@@ -0,0 +1,20 @@
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

99
vendor/platform.js/README.md vendored Normal file
View File

@@ -0,0 +1,99 @@
# Platform.js <sup>v1.0.0-pre</sup>
A platform detection library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>.
## Disclaimer
Platform.js is for informational purposes only and **not** intended as a substitution for [feature detection/inference](http://allyoucanleet.com/post/18087210413/feature-testing-costs#screencast2) checks.
## BestieJS
Platform.js 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 Platform.js can be viewed here: [/doc/README.md](https://github.com/bestiejs/platform.js/blob/master/doc/README.md#readme)
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/platform.js/wiki/Roadmap).
## Installation and usage
In a browser or Adobe AIR:
~~~ html
<script src="platform.js"></script>
~~~
Via [npm](http://npmjs.org/):
~~~ bash
npm install platform
~~~
In [Narwhal](http://narwhaljs.org/), [Node.js](http://nodejs.org/), and [RingoJS](http://ringojs.org/):
~~~ js
var platform = require('platform');
~~~
In [Rhino](http://www.mozilla.org/rhino/):
~~~ js
load('platform.js');
~~~
In an AMD loader like [RequireJS](http://requirejs.org/):
~~~ js
require({
'paths': {
'platform': 'path/to/platform'
}
},
['platform'], function(platform) {
console.log(platform.name);
});
~~~
Usage example:
~~~ js
// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition
platform.name; // 'IE'
platform.version; // '10.0'
platform.layout; // 'Trident'
platform.os; // 'Windows Server 2008 R2 / 7 x64'
platform.description; // 'IE 10.0 x86 (platform preview; running in IE 7 mode) on Windows Server 2008 R2 / 7 x64'
// or on an iPad
platform.name; // 'Safari'
platform.version; // '5.1'
platform.product; // 'iPad'
platform.manufacturer; // 'Apple'
platform.layout; // 'WebKit'
platform.os; // 'iOS 5.0'
platform.description; // 'Safari 5.1 on Apple iPad (iOS 5.0)'
// or parsing a given UA string
var info = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7.2; en; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 11.52');
info.name; // 'Opera'
info.version; // '11.52'
info.layout; // 'Presto'
info.os; // 'Mac OS X 10.7.2'
info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2'
~~~
## Footnotes
1. Platform.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, RingoJS 0.7-0.8, and Rhino 1.7RC3.
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">&#8617;</a>
## Author
* [John-David Dalton](http://allyoucanleet.com/)
[![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter")
## Contributors
* [Mathias Bynens](http://mathiasbynens.be/)
[![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter")

922
vendor/platform.js/platform.js vendored Normal file
View File

@@ -0,0 +1,922 @@
/*!
* Platform.js v1.0.0-pre <http://mths.be/platform>
* Copyright 2010-2012 John-David Dalton <http://allyoucanleet.com/>
* Available under MIT license <http://mths.be/mit>
*/
;(function(window) {
'use strict';
/** Backup possible window/global object */
var oldWin = window;
/** Detect free variable `exports` */
var freeExports = typeof exports == 'object' && exports;
/** Detect free variable `global` */
var freeGlobal = typeof global == 'object' && global &&
(global == global.global ? (window = global) : global);
/** Opera regexp */
var reOpera = /Opera/;
/** Used to resolve a value's internal [[Class]] */
var toString = {}.toString;
/** Detect Java environment */
var java = /Java/.test(getClassOf(window.java)) && window.java;
/** A character to represent alpha */
var alpha = java ? 'a' : '\u03b1';
/** A character to represent beta */
var beta = java ? 'b' : '\u03b2';
/** Browser document object */
var doc = window.document || {};
/** Used to check for own properties of an object */
var hasOwnProperty = {}.hasOwnProperty;
/** Browser navigator object */
var nav = window.navigator || {};
/**
* Detect Opera browser
* http://www.howtocreate.co.uk/operaStuff/operaObject.html
* http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
*/
var opera = window.operamini || window.opera;
/** Opera [[Class]] */
var operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null);
/** Possible global object */
var thisBinding = this;
/** Browser user agent string */
var userAgent = nav.userAgent || '';
/*--------------------------------------------------------------------------*/
/**
* Capitalizes a string value.
*
* @private
* @param {String} string The string to capitalize.
* @returns {String} The capitalized string.
*/
function capitalize(string) {
string = String(string);
return string.charAt(0).toUpperCase() + string.slice(1);
}
/**
* An iteration utility for arrays and objects.
*
* @private
* @param {Array|Object} object The object to iterate over.
* @param {Function} callback The function called per iteration.
*/
function each(object, callback) {
var index = -1,
length = object.length;
if (length == length >>> 0) {
while (++index < length) {
callback(object[index], index, object);
}
} else {
forOwn(object, callback);
}
}
/**
* Trim and conditionally capitalize string values.
*
* @private
* @param {String} string The string to format.
* @returns {String} The formatted string.
*/
function format(string) {
string = trim(string);
return /^(?:webOS|i(?:OS|P))/.test(string)
? string
: capitalize(string);
}
/**
* Iterates over an object's own properties, executing the `callback` for each.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} callback The function executed per own property.
*/
function forOwn(object, callback) {
for (var key in object) {
hasKey(object, key) && callback(object[key], key, object);
}
}
/**
* Gets the internal [[Class]] of a value.
*
* @private
* @param {Mixed} value The value.
* @returns {String} The [[Class]].
*/
function getClassOf(value) {
return value == null
? capitalize(value)
: toString.call(value).slice(8, -1);
}
/**
* Checks if an object has the specified key as a direct property.
*
* @private
* @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`.
*/
function hasKey() {
// lazy define for others (not as accurate)
hasKey = function(object, key) {
var parent = object != null && (object.constructor || Object).prototype;
return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);
};
// for modern browsers
if (getClassOf(hasOwnProperty) == 'Function') {
hasKey = function(object, key) {
return object != null && hasOwnProperty.call(object, key);
};
}
// for Safari 2
else if ({}.__proto__ == Object.prototype) {
hasKey = function(object, key) {
var result = false;
if (object != null) {
object = Object(object);
object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];
}
return result;
};
}
return hasKey.apply(this, arguments);
}
/**
* Host objects can return type values that are different from their actual
* data type. The objects we are concerned with usually return non-primitive
* types of object, function, or unknown.
*
* @private
* @param {Mixed} object The owner of the property.
* @param {String} property The property to check.
* @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
*/
function isHostType(object, property) {
var type = object != null ? typeof object[property] : 'number';
return !/^(?:boolean|number|string|undefined)$/.test(type) &&
(type == 'object' ? !!object[property] : true);
}
/**
* Prepares a string for use in a RegExp constructor by making hyphens and
* spaces optional.
*
* @private
* @param {String} string The string to qualify.
* @returns {String} The qualified string.
*/
function qualify(string) {
return String(string).replace(/([ -])(?!$)/g, '$1?');
}
/**
* A bare-bones` Array#reduce` like utility function.
*
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function called per iteration.
* @param {Mixed} accumulator Initial value of the accumulator.
* @returns {Mixed} The accumulator.
*/
function reduce(array, callback) {
var accumulator = null;
each(array, function(value, index) {
accumulator = callback(accumulator, value, index, array);
});
return accumulator;
}
/**
* Removes leading and trailing whitespace from a string.
*
* @private
* @param {String} string The string to trim.
* @returns {String} The trimmed string.
*/
function trim(string) {
return String(string).replace(/^ +| +$/g, '');
}
/*--------------------------------------------------------------------------*/
/**
* Creates a new platform object.
*
* @memberOf platform
* @param {String} [ua = navigator.userAgent] The user agent string.
* @returns {Object} A platform object.
*/
function parse(ua) {
ua || (ua = userAgent);
/** Temporary variable used over the script's lifetime */
var data;
/** The CPU architecture */
var arch = ua;
/** Platform description array */
var description = [];
/** Platform alpha/beta indicator */
var prerelease = null;
/** A flag to indicate that environment features should be used to resolve the platform */
var useFeatures = ua == userAgent;
/** The browser/environment version */
var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
/* Detectable layout engines (order is important) */
var layout = getLayout([
{ 'label': 'WebKit', 'pattern': 'AppleWebKit' },
'iCab',
'Presto',
'NetFront',
'Tasman',
'Trident',
'KHTML',
'Gecko'
]);
/* Detectable browser names (order is important) */
var name = getName([
'Adobe AIR',
'Arora',
'Avant Browser',
'Camino',
'Epiphany',
'Fennec',
'Flock',
'Galeon',
'GreenBrowser',
'iCab',
'Iceweasel',
'Iron',
'K-Meleon',
'Konqueror',
'Lunascape',
'Maxthon',
'Midori',
'Nook Browser',
'PhantomJS',
'Raven',
'Rekonq',
'RockMelt',
'SeaMonkey',
{ 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
'Sleipnir',
'SlimBrowser',
'Sunrise',
'Swiftfox',
'WebPositive',
'Opera Mini',
'Opera',
'Chrome',
{ 'label': 'Chrome Mobile', 'pattern': 'CrMo' },
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
{ 'label': 'IE', 'pattern': 'MSIE' },
'Safari'
]);
/* Detectable products (order is important) */
var product = getProduct([
'BlackBerry',
{ 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
{ 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
'Google TV',
'iPad',
'iPod',
'iPhone',
'Kindle',
{ 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
'Nook',
'PlayBook',
'PlayStation Vita',
'TouchPad',
'Transformer',
'Xoom'
]);
/* Detectable manufacturers */
var manufacturer = getManufacturer({
'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
'Asus': { 'Transformer': 1 },
'Barnes & Noble': { 'Nook': 1 },
'BlackBerry': { 'PlayBook': 1 },
'Google': { 'Google TV': 1 },
'HP': { 'TouchPad': 1 },
'LG': { },
'Motorola': { 'Xoom': 1 },
'Nokia': { },
'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1 },
'Sony': { 'PlayStation Vita': 1 }
});
/* Detectable OSes (order is important) */
var os = getOS([
'Android',
'CentOS',
'Debian',
'Fedora',
'FreeBSD',
'Gentoo',
'Haiku',
'Kubuntu',
'Linux Mint',
'Red Hat',
'SuSE',
'Ubuntu',
'Xubuntu',
'Cygwin',
'Symbian OS',
'hpwOS',
'webOS ',
'webOS',
'Tablet OS',
'Linux',
'Mac OS X',
'Macintosh',
'Mac',
'Windows 98;',
'Windows '
]);
/*------------------------------------------------------------------------*/
/**
* Picks the layout engine from an array of guesses.
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {String|Null} The detected layout engine.
*/
function getLayout(guesses) {
return reduce(guesses, function(result, guess) {
return result || RegExp('\\b' + (
guess.pattern || qualify(guess)
) + '\\b', 'i').exec(ua) && (guess.label || guess);
});
}
/**
* Picks the manufacturer from an array of guesses.
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {String|Null} The detected manufacturer.
*/
function getManufacturer(guesses) {
return reduce(guesses, function(result, value, key) {
// lookup the manufacturer by product or scan the UA for the manufacturer
return result || (
value[product] ||
value[0/*Opera 9.25 fix*/, /^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
RegExp('\\b' + (key.pattern || qualify(key)) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
) && (key.label || key);
});
}
/**
* Picks the browser name from an array of guesses.
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {String|Null} The detected browser name.
*/
function getName(guesses) {
return reduce(guesses, function(result, guess) {
return result || RegExp('\\b' + (
guess.pattern || qualify(guess)
) + '\\b', 'i').exec(ua) && (guess.label || guess);
});
}
/**
* Picks the OS name from an array of guesses.
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {String|Null} The detected OS name.
*/
function getOS(guesses) {
return reduce(guesses, function(result, guess) {
var pattern = guess.pattern || qualify(guess);
if (!result && (result =
RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua))) {
// platform tokens defined at
// http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
// http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
data = {
'6.2': '8',
'6.1': 'Server 2008 R2 / 7',
'6.0': 'Server 2008 / Vista',
'5.2': 'Server 2003 / XP 64-bit',
'5.1': 'XP',
'5.01': '2000 SP1',
'5.0': '2000',
'4.0': 'NT',
'4.90': 'ME'
};
// detect Windows version from platform tokens
if (/^Win/i.test(result) &&
(data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) {
result = 'Windows ' + data;
}
// correct character case and cleanup
result = format(String(result)
.replace(RegExp(pattern, 'i'), guess.label || guess)
.replace(/ ce$/i, ' CE')
.replace(/hpw/i, 'web')
.replace(/Macintosh/, 'Mac OS')
.replace(/_PowerPC/i, ' OS')
.replace(/(OS X) [^ \d]+/i, '$1')
.replace(/\/(\d)/, ' $1')
.replace(/_/g, '.')
.replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
.replace(/x86\.64/gi, 'x86_64')
.split(' on ')[0]);
}
return result;
});
}
/**
* Picks the product name from an array of guesses.
*
* @private
* @param {Array} guesses An array of guesses.
* @returns {String|Null} The detected product name.
*/
function getProduct(guesses) {
return reduce(guesses, function(result, guess) {
var pattern = guess.pattern || qualify(guess);
if (!result && (result =
RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
)) {
// split by forward slash and append product version if needed
if ((result = String(guess.label || result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
result[0] += ' ' + result[1];
}
// correct character case and cleanup
guess = guess.label || guess;
result = format(result[0]
.replace(RegExp(pattern, 'i'), guess)
.replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
.replace(RegExp('(' + guess + ')(\\w)', 'i'), '$1 $2'));
}
return result;
});
}
/**
* Resolves the version using an array of UA patterns.
*
* @private
* @param {Array} patterns An array of UA patterns.
* @returns {String|Null} The detected version.
*/
function getVersion(patterns) {
return reduce(patterns, function(result, pattern) {
return result || (RegExp(pattern +
'(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
});
}
/*------------------------------------------------------------------------*/
/**
* Return platform description when the platform object is coerced to a string.
*
* @name toString
* @memberOf platform
* @type Function
* @returns {String} The platform description.
*/
function toStringPlatform() {
return this.description || '';
}
/*------------------------------------------------------------------------*/
// convert layout to an array so we can add extra details
layout && (layout = [layout]);
// detect product names that contain their manufacturer's name
if (manufacturer && !product) {
product = getProduct([manufacturer]);
}
// clean up Google TV
if ((data = /Google TV/.exec(product))) {
product = data[0];
}
// detect simulators
if (/\bSimulator\b/i.test(ua)) {
product = (product ? product + ' ' : '') + 'Simulator';
}
// detect iOS
if (/^iP/.test(product)) {
name || (name = 'Safari');
os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
? ' ' + data[1].replace(/_/g, '.')
: '');
}
// detect Kubuntu
else if (name == 'Konqueror' && !/buntu/i.test(os)) {
os = 'Kubuntu';
}
// detect Android browsers
else if (manufacturer && manufacturer != 'Google' &&
/Chrome|Vita/.test(name + ';' + product)) {
name = 'Android Browser';
os = /Android/.test(os) ? os : 'Android';
}
// detect false positives for Firefox/Safari
else if (!name || (data = !/\bMinefield\b/i.test(ua) && /Firefox|Safari/.exec(name))) {
// escape the `/` for Firefox 1
if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
// clear name of false positives
name = null;
}
// reassign a generic name
if ((data = product || manufacturer || os) &&
(product || manufacturer || /Android|Symbian OS|Tablet OS|webOS/.test(os))) {
name = /[a-z]+(?: Hat)?/i.exec(/Android/.test(os) ? os : data) + ' Browser';
}
}
// detect non-Opera versions (order is important)
if (!version) {
version = getVersion([
'(?:Cloud9|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))',
'Version',
qualify(name),
'(?:Firefox|Minefield|NetFront)'
]);
}
// detect stubborn layout engines
if (layout == 'iCab' && parseFloat(version) > 3) {
layout = ['WebKit'];
} else if (data =
/Opera/.test(name) && 'Presto' ||
/\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' ||
!layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) {
layout = [data];
}
// leverage environment features
if (useFeatures) {
// detect server-side environments
// Rhino has a global function while others have a global object
if (isHostType(window, 'global')) {
if (java) {
data = java.lang.System;
arch = data.getProperty('os.arch');
os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
}
if (typeof exports == 'object' && exports) {
// if `thisBinding` is the [ModuleScope]
if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {
os || (os = data[0].os || null);
try {
data[1] = require('ringo/engine').version;
version = data[1].join('.');
name = 'RingoJS';
} catch(e) {
if (data[0].global == freeGlobal) {
name = 'Narwhal';
}
}
} else if (typeof process == 'object' && (data = process)) {
name = 'Node.js';
arch = data.arch;
os = data.platform;
version = /[\d.]+/.exec(data.version)[0];
}
} else if (getClassOf(window.environment) == 'Environment') {
name = 'Rhino';
}
}
// detect Adobe AIR
else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') {
name = 'Adobe AIR';
os = data.flash.system.Capabilities.os;
}
// detect PhantomJS
else if (getClassOf(data = window.phantom) == 'RuntimeObject') {
name = 'PhantomJS';
version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
}
// detect IE compatibility modes
else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
// we're in compatibility mode when the Trident version + 4 doesn't
// equal the document mode
version = [version, doc.documentMode];
if ((data = +data[1] + 4) != version[1]) {
description.push('IE ' + version[1] + ' mode');
layout[1] = '';
version[1] = data;
}
version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
}
os = os && format(os);
}
// detect prerelease phases
if (version && (data =
/(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
/(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
/\bMinefield\b/i.test(ua) && 'a')) {
prerelease = /b/i.test(data) ? 'beta' : 'alpha';
version = version.replace(RegExp(data + '\\+?$'), '') +
(prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
}
// rename code name "Fennec"
if (name == 'Fennec') {
name = 'Firefox Mobile';
}
// obscure Maxthon's unreliable version
else if (name == 'Maxthon' && version) {
version = version.replace(/\.[\d.]+/, '.x');
}
// detect Silk desktop/accelerated modes
else if (name == 'Silk') {
if (!/Mobi/i.test(ua)) {
os = 'Android';
description.unshift('desktop mode');
}
if (/Accelerated *= *true/i.test(ua)) {
description.unshift('accelerated');
}
}
// detect Windows Phone desktop mode
else if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
name += ' Mobile';
os = 'Windows Phone OS ' + data + '.x';
description.unshift('desktop mode');
}
// add mobile postfix
else if ((name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) &&
(os == 'Windows CE' || /Mobi/i.test(ua))) {
name += ' Mobile';
}
// detect IE platform preview
else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) {
description.unshift('platform preview');
}
// detect BlackBerry OS version
// http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
else if (/BlackBerry/.test(product) && (data =
(RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
version)) {
os = 'Device Software ' + data;
version = null;
}
// detect Opera identifying/masking itself as another browser
// http://www.opera.com/support/kb/view/843/
else if (this != forOwn && (
(useFeatures && opera) ||
(/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
(name == 'Firefox' && /OS X (?:\d+\.){2,}/.test(os)) ||
(name == 'IE' && (
(os && !/^Win/.test(os) && version > 5.5) ||
/Windows XP/.test(os) && version > 8 ||
version == 8 && !/Trident/.test(ua)
))
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {
// when "indentifying" the UA contains both Opera and the other browser's name
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
if (reOpera.test(name)) {
if (/IE/.test(data) && os == 'Mac OS') {
os = null;
}
data = 'identify' + data;
}
// when "masking" the UA contains only the other browser's name
else {
data = 'mask' + data;
if (operaClass) {
name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
} else {
name = 'Opera';
}
if (/IE/.test(data)) {
os = null;
}
if (!useFeatures) {
version = null;
}
}
layout = ['Presto'];
description.push(data);
}
// detect WebKit Nightly and approximate Chrome/Safari versions
if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
// correct build for numeric comparison
// (e.g. "532.5" becomes "532.05")
data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
// nightly builds are postfixed with a `+`
if (name == 'Safari' && data[1].slice(-1) == '+') {
name = 'WebKit Nightly';
prerelease = 'alpha';
version = data[1].slice(0, -1);
}
// clear incorrect browser versions
else if (version == data[1] ||
version == (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1]) {
version = null;
}
// use the full Chrome version when available
data = [data[0], (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]];
// detect JavaScriptCore
// http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
if (!useFeatures || (/internal|\n/i.test(toString.toString()) && !data[1])) {
layout[1] = 'like Safari';
data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');
} else {
layout[1] = 'like Chrome';
data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 535.21 ? 18 : '19');
}
// add the postfix of ".x" or "+" for approximate versions
layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');
// obscure version for some Safari 1-2 releases
if (name == 'Safari' && (!version || parseInt(version) > 45)) {
version = data;
}
}
// strip incorrect OS versions
if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 &&
ua.indexOf('/' + data + '-') > -1) {
os = trim(os.replace(data, ''));
}
// add layout engine
if (layout && !/Avant|Nook/.test(name) && (
/Browser|Lunascape|Maxthon/.test(name) ||
/^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) {
// don't add layout details to description if they are falsey
(data = layout[layout.length - 1]) && description.push(data);
}
// combine contextual information
if (description.length) {
description = ['(' + description.join('; ') + ')'];
}
// append manufacturer
if (manufacturer && product && product.indexOf(manufacturer) < 0) {
description.push('on ' + manufacturer);
}
// append product
if (product) {
description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);
}
// add browser/OS architecture
if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i).test(arch) && !/\bi686\b/i.test(arch)) {
os = os && os + (data.test(os) ? '' : ' 64-bit');
if (name && (/WOW64/i.test(ua) ||
(useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
description.unshift('32-bit');
}
}
ua || (ua = null);
/*------------------------------------------------------------------------*/
/**
* The platform object.
*
* @name platform
* @type Object
*/
return {
/**
* The browser/environment version.
*
* @memberOf platform
* @type String|Null
*/
'version': name && version && (description.unshift(version), version),
/**
* The name of the browser/environment.
*
* @memberOf platform
* @type String|Null
*/
'name': name && (description.unshift(name), name),
/**
* The name of the operating system.
*
* @memberOf platform
* @type String|Null
*/
'os': os && (name &&
!(os == os.split(' ')[0] && (os == name.split(' ')[0] || product)) &&
description.push(product ? '(' + os + ')' : 'on ' + os), os),
/**
* The platform description.
*
* @memberOf platform
* @type String|Null
*/
'description': description.length ? description.join(' ') : ua,
/**
* The name of the browser layout engine.
*
* @memberOf platform
* @type String|Null
*/
'layout': layout && layout[0],
/**
* The name of the product's manufacturer.
*
* @memberOf platform
* @type String|Null
*/
'manufacturer': manufacturer,
/**
* The alpha/beta release indicator.
*
* @memberOf platform
* @type String|Null
*/
'prerelease': prerelease,
/**
* The name of the product hosting the browser.
*
* @memberOf platform
* @type String|Null
*/
'product': product,
/**
* The browser's user agent string.
*
* @memberOf platform
* @type String|Null
*/
'ua': ua,
// parses a user agent string into a platform object
'parse': parse,
// returns the platform description
'toString': toStringPlatform
};
}
/*--------------------------------------------------------------------------*/
// expose platform
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// define as an anonymous module so, through path mapping, it can be aliased
define(function() {
return parse();
});
}
// check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports) {
// in Narwhal, Node.js, or RingoJS
forOwn(parse(), function(value, key) {
freeExports[key] = value;
});
}
// in a browser or Rhino
else {
// use square bracket notation so Closure Compiler won't munge `platform`
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
window['platform'] = parse();
}
}(this));

View File

@@ -5,6 +5,7 @@
* Available under MIT license <http://mths.be/mit>
*/
;(function(global) {
'use strict';
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
global.console || (global.console = { 'log': global.print });
@@ -24,7 +25,8 @@
var toString = {}.toString;
/** Used by timer methods */
var timer,
var doneCalled,
timer,
counter = 0,
ids = {};
@@ -149,26 +151,26 @@
* `runtime`, and `total`.
*/
function done(details) {
// stop `asyncTest()` from erroneously calling `done()` twice in environments w/o timeouts
if (!QUnit.doneCalled) {
console.log(hr);
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
console.log(' Finished in ' + details.runtime + ' milliseconds.');
console.log(hr);
// exit out of Rhino
try {
quit();
} catch(e) { }
// exit out of Node.js
try {
process.exit();
} catch(e) { }
// prevent multiple calls to `done()`
QUnit.doneCalled = true;
// stop `asyncTest()` from erroneously calling `done()` twice in
// environments w/o timeouts
if (doneCalled) {
return;
}
doneCalled = true;
console.log(hr);
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
console.log(' Finished in ' + details.runtime + ' milliseconds.');
console.log(hr);
// exit out of Rhino
try {
quit();
} catch(e) { }
// exit out of Node.js
try {
process.exit();
} catch(e) { }
}
/**
@@ -181,12 +183,13 @@
function log(details) {
var expected = details.expected,
result = details.result,
type = typeof expected != 'undefined' ? 'EQ' : 'OK',
assertion = [
result ? 'PASS' : 'FAIL',
type,
details.message || 'ok'
];
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
var assertion = [
result ? 'PASS' : 'FAIL',
type,
details.message || 'ok'
];
if (!result && type == 'EQ') {
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
@@ -215,7 +218,7 @@
* @returns {String} The result string.
*/
var parseObject = (function() {
var _parseObject = QUnit.jsDump.parsers.object;
var func = QUnit.jsDump.parsers.object;
return function(object) {
// fork to support Rhino's error objects
if (typeof object.rhinoException == 'object') {
@@ -224,7 +227,7 @@
'", fileName: "' + object.fileName +
'", lineNumber: ' + object.lineNumber + ' }';
}
return _parseObject(object);
return func(object);
};
}());
@@ -237,16 +240,16 @@
*/
function testDone(details) {
var assertions = QUnit.config.testStats.assertions,
name = details.name;
testName = details.name;
if (details.failed > 0) {
console.log(' FAIL - '+ name);
console.log(' FAIL - '+ testName);
each(assertions, function(value) {
console.log(' ' + value);
});
}
else {
console.log(' PASS - ' + name);
console.log(' PASS - ' + testName);
}
assertions.length = 0;
}
@@ -274,8 +277,11 @@
// exclude `module` because some environments have it as a built-in object
each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
'strictEqual', 'test'], function(name) {
global[name] = QUnit[name];
'strictEqual', 'test', 'throws'], function(funcName) {
var func = QUnit[funcName];
if (func) {
global[funcName] = func;
}
});
// expose timer methods to global
@@ -301,11 +307,11 @@
QUnit.moduleStart(moduleStart);
QUnit.testDone(testDone);
// wrap `parseObject`
// add wrapped function
QUnit.jsDump.parsers.object = parseObject;
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with Node.js
// or any version of QUnit with Narwhal, Rhino, or RingoJS
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
// Node.js or any version of QUnit with Narwhal, Rhino, or RingoJS
QUnit.init();
}(typeof global == 'object' && global || this));

View File

@@ -41,8 +41,9 @@ Releases
--------
Install git-extras and run `git changelog` to update History.md.
Update qunit/qunit.js|css to the release version, commit and tag, update them
again to the next version, commit and push commits and tags.
Update qunit/qunit.js|css and package.json to the release version, commit and
tag, update them again to the next version, commit and push commits and tags
(`git push --tags origin master`).
Put the 'v' in front of the tag (unlike the 1.1.0 release). Clean up the changelog,
removing merge commits or whitespace cleanups.
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
or whitespace cleanups.

1863
vendor/qunit/qunit/qunit-1.8.0.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/**
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
@@ -38,10 +38,10 @@
line-height: 1em;
font-weight: normal;
border-radius: 15px 15px 0 0;
-moz-border-radius: 15px 15px 0 0;
-webkit-border-top-right-radius: 15px;
-webkit-border-top-left-radius: 15px;
border-radius: 5px 5px 0 0;
-moz-border-radius: 5px 5px 0 0;
-webkit-border-top-right-radius: 5px;
-webkit-border-top-left-radius: 5px;
}
#qunit-header a {
@@ -54,9 +54,9 @@
color: #fff;
}
#qunit-header label {
#qunit-testrunner-toolbar label {
display: inline-block;
padding-left: 0.5em;
padding: 0 .5em 0 .1em;
}
#qunit-banner {
@@ -113,13 +113,9 @@
background-color: #fff;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
#qunit-tests table {
@@ -162,8 +158,7 @@
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
margin: 0.5em;
padding: 0.4em 0.5em 0.4em 0.5em;
padding: 5px;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
@@ -172,9 +167,9 @@
/*** Passing Styles */
#qunit-tests li li.pass {
color: #5E740B;
color: #3c510c;
background-color: #fff;
border-left: 26px solid #C6E746;
border-left: 10px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
@@ -190,15 +185,15 @@
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 26px solid #EE5757;
border-left: 10px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 15px 15px;
-moz-border-radius: 0 0 15px 15px;
-webkit-border-bottom-right-radius: 15px;
-webkit-border-bottom-left-radius: 15px;
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }

View File

@@ -1,5 +1,5 @@
/**
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
@@ -403,6 +403,8 @@ QUnit = {
QUnit.assert = {
/**
* Asserts rough true-ish result.
* @name ok
* @function
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
*/
ok: function( result, msg ) {
@@ -437,36 +439,59 @@ QUnit.assert = {
/**
* Assert that the first two arguments are equal, with an optional message.
* Prints out both actual and expected values.
* @name equal
* @function
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
*/
equal: function( actual, expected, message ) {
QUnit.push( expected == actual, actual, expected, message );
},
/**
* @name notEqual
* @function
*/
notEqual: function( actual, expected, message ) {
QUnit.push( expected != actual, actual, expected, message );
},
/**
* @name deepEqual
* @function
*/
deepEqual: function( actual, expected, message ) {
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
},
/**
* @name notDeepEqual
* @function
*/
notDeepEqual: function( actual, expected, message ) {
QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
},
/**
* @name strictEqual
* @function
*/
strictEqual: function( actual, expected, message ) {
QUnit.push( expected === actual, actual, expected, message );
},
/**
* @name notStrictEqual
* @function
*/
notStrictEqual: function( actual, expected, message ) {
QUnit.push( expected !== actual, actual, expected, message );
},
raises: function( block, expected, message ) {
throws: function( block, expected, message ) {
var actual,
ok = false;
// 'expected' is optional
if ( typeof expected === "string" ) {
message = expected;
expected = null;
@@ -494,18 +519,29 @@ QUnit.assert = {
} else if ( expected.call( {}, actual ) === true ) {
ok = true;
}
}
QUnit.push( ok, actual, null, message );
QUnit.push( ok, actual, null, message );
} else {
QUnit.pushFailure( message, null, 'No exception was thrown.' );
}
}
};
// @deprecated: Kept assertion helpers in root for backwards compatibility
/**
* @deprecate since 1.8.0
* Kept assertion helpers in root for backwards compatibility
*/
extend( QUnit, QUnit.assert );
/**
* @deprecated: Kept for backwards compatibility
* next step: remove entirely
* @deprecated since 1.9.0
* Kept global "raises()" for backwards compatibility
*/
QUnit.raises = QUnit.assert.throws;
/**
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0
* Kept to avoid TypeErrors for undefined methods.
*/
QUnit.equals = function() {
QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
@@ -549,7 +585,20 @@ config = {
// when enabled, all tests must call expect()
requireExpects: false,
urlConfig: [ "noglobals", "notrycatch" ],
// add checkboxes that are persisted in the query-string
// when enabled, the id is set to `true` as a `QUnit.config` property
urlConfig: [
{
id: "noglobals",
label: "Check for Globals",
tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
},
{
id: "notrycatch",
label: "No try-catch",
tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
}
],
// logging callback queues
begin: [],
@@ -770,7 +819,7 @@ extend( QUnit, {
});
},
pushFailure: function( message, source ) {
pushFailure: function( message, source, actual ) {
if ( !config.current ) {
throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
}
@@ -781,15 +830,23 @@ extend( QUnit, {
message: message
};
message = escapeInnerText(message ) || "error";
message = escapeInnerText( message ) || "error";
message = "<span class='test-message'>" + message + "</span>";
output = message;
output += "<table>";
if ( actual ) {
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeInnerText( actual ) + "</pre></td></tr>";
}
if ( source ) {
details.source = source;
output += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr></table>";
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>";
}
output += "</table>";
runLoggingCallbacks( "log", QUnit, details );
config.current.assertions.push({
@@ -859,7 +916,7 @@ QUnit.load = function() {
runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,
urlConfigHtml = "",
oldconfig = extend( {}, config );
@@ -872,8 +929,15 @@ QUnit.load = function() {
for ( i = 0; i < len; i++ ) {
val = config.urlConfig[i];
config[val] = QUnit.urlParams[val];
urlConfigHtml += "<label><input name='" + val + "' type='checkbox'" + ( config[val] ? " checked='checked'" : "" ) + ">" + val + "</label>";
if ( typeof val === "string" ) {
val = {
id: val,
label: val,
tooltip: "[no tooltip available]"
};
}
config[ val.id ] = QUnit.urlParams[ val.id ];
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>";
}
// `userAgent` initialized at top of scope
@@ -885,12 +949,7 @@ QUnit.load = function() {
// `banner` initialized at top of scope
banner = id( "qunit-header" );
if ( banner ) {
banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined }) + "'>" + banner.innerHTML + "</a> " + urlConfigHtml;
addEvent( banner, "change", function( event ) {
var params = {};
params[ event.target.name ] = event.target.checked ? true : undefined;
window.location = QUnit.url( params );
});
banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
}
// `toolbar` initialized at top of scope
@@ -931,8 +990,18 @@ QUnit.load = function() {
// `label` initialized at top of scope
label = document.createElement( "label" );
label.setAttribute( "for", "qunit-filter-pass" );
label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." );
label.innerHTML = "Hide passed tests";
toolbar.appendChild( label );
urlConfigCheckboxes = document.createElement( 'span' );
urlConfigCheckboxes.innerHTML = urlConfigHtml;
addEvent( urlConfigCheckboxes, "change", function( event ) {
var params = {};
params[ event.target.name ] = event.target.checked ? true : undefined;
window.location = QUnit.url( params );
});
toolbar.appendChild( urlConfigCheckboxes );
}
// `main` initialized at top of scope
@@ -1051,14 +1120,14 @@ function done() {
function validTest( test ) {
var include,
filter = config.filter && config.filter.toLowerCase(),
module = config.module,
module = config.module && config.module.toLowerCase(),
fullName = (test.module + ": " + test.testName).toLowerCase();
if ( config.testNumber ) {
return test.testNumber === config.testNumber;
}
if ( module && test.module !== module ) {
if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
return false;
}