mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-30 15:07:50 +00:00
Compare commits
121 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
219138ade6 | ||
|
|
9086d189b9 | ||
|
|
d1178defe0 | ||
|
|
691a561a95 | ||
|
|
aaaac93bd0 | ||
|
|
fd790566b2 | ||
|
|
db3b429784 | ||
|
|
40ed3278d4 | ||
|
|
d174b13111 | ||
|
|
1708663b32 | ||
|
|
6fdce4ad0d | ||
|
|
fff8d5f07d | ||
|
|
9c8e1f4706 | ||
|
|
0a1036c78f | ||
|
|
0e881a7972 | ||
|
|
839e52ba30 | ||
|
|
8f7d5dcb4d | ||
|
|
1104b28bc1 | ||
|
|
48521cb1e4 | ||
|
|
17e113dafb | ||
|
|
c33825a904 | ||
|
|
b07ef98c8f | ||
|
|
b3d68893df | ||
|
|
1329599987 | ||
|
|
2adf3f364c | ||
|
|
436ee34a02 | ||
|
|
4a6e17b214 | ||
|
|
6e9cbccde6 | ||
|
|
a0cb8ec124 | ||
|
|
21217dfda3 | ||
|
|
25ba18e570 | ||
|
|
a210377f35 | ||
|
|
07b9ca457f | ||
|
|
5f1372d39c | ||
|
|
01b84c79f0 | ||
|
|
4017443b1e | ||
|
|
fd2a17d244 | ||
|
|
126804f7c3 | ||
|
|
5167bbf59e | ||
|
|
8bcdfa2793 | ||
|
|
2f9cb6a91e | ||
|
|
662be14535 | ||
|
|
d6d065cd61 | ||
|
|
ac7f045708 | ||
|
|
ffe02ad7bf | ||
|
|
db1a87d10c | ||
|
|
4bae41ffd8 | ||
|
|
be36fb979f | ||
|
|
0f66d763e0 | ||
|
|
06f4743f51 | ||
|
|
9cc11b8774 | ||
|
|
de821e55ae | ||
|
|
463b5c6e49 | ||
|
|
65ab5fdb34 | ||
|
|
d2f7a035b3 | ||
|
|
bc0b924283 | ||
|
|
56ad6af5b2 | ||
|
|
c50bb3a5a9 | ||
|
|
d993a62263 | ||
|
|
82bc52b909 | ||
|
|
f31598f916 | ||
|
|
6a9efd8ac6 | ||
|
|
a9dddb6066 | ||
|
|
40cf5c99ef | ||
|
|
42f58cbbb3 | ||
|
|
fd9c780015 | ||
|
|
383b92b207 | ||
|
|
7036ed5e2f | ||
|
|
30666aa111 | ||
|
|
9614d68baa | ||
|
|
c25fb4c743 | ||
|
|
09d5222b1f | ||
|
|
426ca78bf7 | ||
|
|
a77a0945fe | ||
|
|
5311a0f903 | ||
|
|
d421656be8 | ||
|
|
04459eaa50 | ||
|
|
3beda8eea0 | ||
|
|
5e894be06b | ||
|
|
bc8f93b596 | ||
|
|
2fb93bac99 | ||
|
|
d0c94c1aef | ||
|
|
77242bfb95 | ||
|
|
5d2d86bffc | ||
|
|
8492c13e72 | ||
|
|
e4eb5dadda | ||
|
|
8532dc4b75 | ||
|
|
1ca26ce676 | ||
|
|
d8e3e823a7 | ||
|
|
473dd7660b | ||
|
|
5afeed56ef | ||
|
|
b91b04f652 | ||
|
|
25de44a23d | ||
|
|
00cfb95971 | ||
|
|
f4ba0e1191 | ||
|
|
6499643769 | ||
|
|
f85287a444 | ||
|
|
483bc9ad87 | ||
|
|
93b89a93c1 | ||
|
|
10064c046c | ||
|
|
a5aecb9d0e | ||
|
|
de1e889f1d | ||
|
|
16f89b40c3 | ||
|
|
0e387d2cda | ||
|
|
837c15e4f9 | ||
|
|
ae7e353169 | ||
|
|
6c1bbd2344 | ||
|
|
27247e8e56 | ||
|
|
08249d78ea | ||
|
|
827091e522 | ||
|
|
13d901bf8d | ||
|
|
e69bdabc99 | ||
|
|
e8d19265e4 | ||
|
|
49e3a49dc5 | ||
|
|
82a7c01898 | ||
|
|
c0d7dbf639 | ||
|
|
569caa0bf2 | ||
|
|
f88ea1ee7d | ||
|
|
d5a8fa0b97 | ||
|
|
3f8f96edea | ||
|
|
04fb4aff28 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
*.custom.*
|
||||
.DS_Store
|
||||
dist/
|
||||
node_modules/
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
*.custom.*
|
||||
.*
|
||||
dist/
|
||||
build.js
|
||||
index.js
|
||||
build/
|
||||
doc/*.php
|
||||
node_modules/
|
||||
perf/*.sh
|
||||
test/*.sh
|
||||
test/test-build.js
|
||||
test/template/
|
||||
vendor/closure-compiler
|
||||
vendor/docdown
|
||||
vendor/uglifyjs
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
*.custom.*
|
||||
.*
|
||||
dist/
|
||||
doc/*.php
|
||||
node_modules/
|
||||
perf/*.html
|
||||
|
||||
4
.travis.yml
Normal file
4
.travis.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
- 0.8
|
||||
165
README.md
165
README.md
@@ -1,15 +1,17 @@
|
||||
# Lo-Dash <sup>v0.7.0</sup>
|
||||
# Lo-Dash <sup>v0.8.2</sup>
|
||||
[](http://travis-ci.org/bestiejs/lodash)
|
||||
|
||||
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), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues-20), 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), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues), and [additional features](http://lodash.com/#features).
|
||||
|
||||
Lo-Dash’s 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.7.0/lodash.js)
|
||||
* [Production source](https://raw.github.com/bestiejs/lodash/v0.7.0/lodash.min.js)
|
||||
* CDN copies of ≤ [v0.7.0](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.7.0/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
|
||||
* [Development build](https://raw.github.com/bestiejs/lodash/v0.8.2/lodash.js)
|
||||
* [Production build](https://raw.github.com/bestiejs/lodash/v0.8.2/lodash.min.js)
|
||||
* [Underscore build](https://raw.github.com/bestiejs/lodash/v0.8.2/lodash.underscore.min.js) tailored for projects already using Underscore
|
||||
* CDN copies of ≤ [v0.8.2](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.8.2/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
|
||||
* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
|
||||
|
||||
## Dive in
|
||||
|
||||
@@ -32,32 +34,22 @@ For more information check out these screencasts over Lo-Dash:
|
||||
## Features
|
||||
|
||||
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
|
||||
* [_.bind](http://lodash.com/docs#bind) supports *“lazy”* binding
|
||||
* [_.clone](http://lodash.com/docs#clone) supports *“deep”* cloning
|
||||
* [_.countBy](http://lodash.com/docs#countBy) as a companion function for [_.groupBy](http://lodash.com/docs#groupBy) and [_.sortBy](http://lodash.com/docs#sortBy)
|
||||
* [_.debounce](http://lodash.com/docs#debounce)’ed functions match [_.throttle](http://lodash.com/docs#throttle)’ed functions’ return value behavior
|
||||
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
|
||||
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties
|
||||
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties
|
||||
* [_.indexOf](http://lodash.com/docs#indexOf) and [_.lastIndexOf](http://lodash.com/docs#lastIndexOf) accept a `fromIndex` argument
|
||||
* [_.invert](http://lodash.com/docs#invert) to create inverted objects
|
||||
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
|
||||
* [_.lateBind](http://lodash.com/docs#lateBind) for late binding
|
||||
* [_.merge](http://lodash.com/docs#merge) for a *“deep”* [_.extend](http://lodash.com/docs#extend)
|
||||
* [_.object](http://lodash.com/docs#object) and [_.pairs](http://lodash.com/docs#pairs) for composing objects
|
||||
* [_.omit](http://lodash.com/docs#omit) for the inverse functionality of [_.pick](http://lodash.com/docs#pick)
|
||||
* [_.partial](http://lodash.com/docs#partial) for partial application without `this` binding
|
||||
* [_.pick](http://lodash.com/docs#pick) and [_.omit](http://lodash.com/docs#omit) accept `callback` and `thisArg` arguments
|
||||
* [_.random](http://lodash.com/docs#random) for generating random numbers within a given range
|
||||
* [_.sortBy](http://lodash.com/docs#sortBy) performs a [stable](http://en.wikipedia.org/wiki/Sorting_algorithm#Stability) sort
|
||||
* [_.template](http://lodash.com/docs#template) utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging
|
||||
* [_.unescape](http://lodash.com/docs#unescape) to unescape strings escaped by [_.escape](http://lodash.com/docs#escape)
|
||||
* [_.where](http://lodash.com/docs#where) for filtering collections by contained properties
|
||||
* [_.countBy](http://lodash.com/docs#countBy), [_.groupBy](http://lodash.com/docs#groupBy), [_.sortedIndex](http://lodash.com/docs#sortedIndex), and [_.uniq](http://lodash.com/docs#uniq) accept a `thisArg` argument
|
||||
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
|
||||
[and more…](http://lodash.com/docs "_.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _.sortBy, _.where") accept strings
|
||||
|
||||
## Support
|
||||
|
||||
Lo-Dash has been tested in at least Chrome 5-21, Firefox 1-15, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.8, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||
Lo-Dash has been tested in at least Chrome 5~22, Firefox 1~16, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.11, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||
|
||||
## Custom builds
|
||||
|
||||
@@ -89,7 +81,7 @@ lodash mobile
|
||||
lodash strict
|
||||
```
|
||||
|
||||
* Underscore builds, with iteration fixes removed and only Underscore’s API, may be created using the `underscore` modifier argument.
|
||||
* Underscore builds, tailored for projects already using Underscore, may be created using the `underscore` modifier argument.
|
||||
```bash
|
||||
lodash underscore
|
||||
```
|
||||
@@ -97,23 +89,17 @@ lodash underscore
|
||||
Custom builds may be created using the following commands:
|
||||
|
||||
* Use the `category` argument to pass comma separated categories of methods to include in the build.<br>
|
||||
Valid categories are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
|
||||
Valid categories (case-insensitive) are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
|
||||
```bash
|
||||
lodash category=collections,functions
|
||||
lodash category="collections, functions"
|
||||
```
|
||||
|
||||
* Use the `exclude` argument to pass comma separated names of methods to exclude from the build.
|
||||
```bash
|
||||
lodash exclude=union,uniq,zip
|
||||
lodash exclude="union, uniq, zip"
|
||||
```
|
||||
|
||||
* Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.<br>
|
||||
Valid exports are *“amd”*, *“commonjs”*, *“global”*, *“node”*, and *“none”*.
|
||||
Valid exports are *“amd”*, *“commonjs”*, *“global”*, *“node”*, and *“none”*.
|
||||
```bash
|
||||
lodash exports=amd,commonjs,node
|
||||
lodash include="amd, commonjs, node"
|
||||
lodash exports="amd, commonjs, node"
|
||||
```
|
||||
|
||||
* Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.
|
||||
@@ -121,31 +107,49 @@ lodash include="amd, commonjs, node"
|
||||
lodash iife="!function(window,undefined){%output%}(this)"
|
||||
```
|
||||
|
||||
* Use the `include` argument to pass comma separated names of methods to include in the build.
|
||||
* Use the `include` argument to pass comma separated method/category names 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 `csp`/`mobile`, may be combined.
|
||||
|
||||
* Use the `minus` argument to pass comma separated method/category names to remove from those included in the build.
|
||||
```bash
|
||||
lodash backbone legacy exports=global category=utilities exclude=first,last
|
||||
lodash -s underscore mobile strict exports=amd category=functions include=pick,uniq
|
||||
lodash underscore minus=result,shuffle
|
||||
lodash underscore minus="result, shuffle"
|
||||
```
|
||||
|
||||
* Use the `plus` argument to pass comma separated method/category names to add to those included in the build.
|
||||
```bash
|
||||
lodash backbone plus=random,template
|
||||
lodash backbone plus="random, template"
|
||||
```
|
||||
|
||||
* Use the `template` argument to pass the file path pattern used to match template files to precompile
|
||||
```bash
|
||||
lodash template="./*.jst"
|
||||
```
|
||||
|
||||
* Use the `settings` argument to pass the template settings used when precompiling templates
|
||||
```bash
|
||||
lodash settings="{interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/g}"
|
||||
```
|
||||
|
||||
All arguments, except `legacy` with `csp` or `mobile`, may be combined.<br>
|
||||
Unless specified by `-o` or `--output`, all files created are saved to the current working directory.
|
||||
|
||||
The following options are also supported:
|
||||
|
||||
* `-c`, `--stdout` Write output to standard output
|
||||
* `-h`, `--help` Display help information
|
||||
* `-o`, `--output` Write output to a given path/filename
|
||||
* `-s`, `--silent` Skip status updates normally logged to the console
|
||||
* `-V`, `--version` Output current version of Lo-Dash
|
||||
* `-c`, `--stdout` Write output to standard output
|
||||
* `-d`, `--debug` Write only the debug output
|
||||
* `-h`, `--help` Display help information
|
||||
* `-m`, `--minify` Write only the minified output
|
||||
* `-o`, `--output` Write output to a given path/filename
|
||||
* `-s`, `--silent` Skip status updates normally logged to the console
|
||||
* `-V`, `--version` Output current version of Lo-Dash
|
||||
|
||||
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
||||
|
||||
Custom builds are saved to `lodash.custom.js` and `lodash.custom.min.js`.
|
||||
|
||||
## Installation and usage
|
||||
|
||||
In browsers:
|
||||
@@ -158,7 +162,9 @@ Using [npm](http://npmjs.org/):
|
||||
|
||||
```bash
|
||||
npm install lodash
|
||||
|
||||
npm install -g lodash
|
||||
npm link lodash
|
||||
```
|
||||
|
||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||
@@ -167,6 +173,8 @@ In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||
var _ = require('lodash');
|
||||
```
|
||||
|
||||
**Note:** If Lo-Dash is installed globally, [run `npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before attempting to `require` it.
|
||||
|
||||
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||
|
||||
```js
|
||||
@@ -192,43 +200,30 @@ require({
|
||||
});
|
||||
```
|
||||
|
||||
## Resolved Underscore.js issues <sup>(20+)</sup>
|
||||
## Resolved Underscore.js issues
|
||||
|
||||
* 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.7.0/test/test.js#L543-549)]
|
||||
* Ensure array-like objects with invalid `length` properties are treated like regular objects [[#741](https://github.com/documentcloud/underscore/issues/741), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L491-501)]
|
||||
* Ensure *“Arrays”*, *“Collections”*, and *“Objects”* methods don’t error when passed falsey arguments [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1719-1754)]
|
||||
* 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.7.0/test/test.js#L503-520)]
|
||||
* Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L554-579)]
|
||||
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L134-140)]
|
||||
* 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.7.0/test/test.js#L118-132)]
|
||||
* `_.clone` should allow `deep` cloning [[#595](https://github.com/documentcloud/underscore/pull/595), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L223-234)]
|
||||
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L289-298)]
|
||||
* `_.countBy` and `_.groupBy` should only add values to own, not inherited, properties [[#736](https://github.com/documentcloud/underscore/issues/736), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L306-313)]
|
||||
* `_.extend` should recursively extend objects [[#379](https://github.com/documentcloud/underscore/pull/379), [#718](https://github.com/documentcloud/underscore/issues/718), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L946-968)]
|
||||
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L486-489)]
|
||||
* `_.forEach` should allow exiting iteration early [[#211](https://github.com/documentcloud/underscore/issues/211), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L581-600)]
|
||||
* `_.isElement` should use strict equality for its duck type check [[#734](https://github.com/documentcloud/underscore/issues/734), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L696-705)]
|
||||
* `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L732-737)]
|
||||
* `_.isEqual` should return `true` for like-objects from different documents [[#733](https://github.com/documentcloud/underscore/issues/733), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L784-795)]
|
||||
* `_.isEqual` should use custom `isEqual` methods before checking strict equality [[#748](https://github.com/documentcloud/underscore/issues/748), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L758-761)]
|
||||
* `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L803-815)]
|
||||
* `_.isNaN(new Number(NaN))` should return `true` [[#749](https://github.com/documentcloud/underscore/issues/749), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L823-825)]
|
||||
* `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L879-881)]
|
||||
* `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1222-1225)]
|
||||
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1257-1271)]
|
||||
* `_.sortedIndex` should support arrays with high `length` values [[#735](https://github.com/documentcloud/underscore/issues/735), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1404-1413)]
|
||||
* `_.throttle` should work when called in a loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1534-1544)]
|
||||
* `_.toArray` uses custom `toArray` methods of arrays and strings [[#747](https://github.com/documentcloud/underscore/issues/747), [test](https://github.com/bestiejs/lodash/blob/v0.7.0/test/test.js#L1571-1579)]
|
||||
* Add AMD loader support [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L118-140)]
|
||||
* Allow iteration of objects with a `length` property [[#799](https://github.com/documentcloud/underscore/pull/799), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L510-516)]
|
||||
* 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.8.2/test/test.js#L470-487)]
|
||||
* Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L523-547)]
|
||||
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L142-148)]
|
||||
* `_.clone` should allow `deep` cloning [[#595](https://github.com/documentcloud/underscore/pull/595), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L214-225)]
|
||||
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L267-276)]
|
||||
* `_.extend` should recursively extend objects [[#379](https://github.com/documentcloud/underscore/pull/379), [#718](https://github.com/documentcloud/underscore/issues/718), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L968-990)]
|
||||
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L465-468)]
|
||||
* `_.forEach` should allow exiting iteration early [[#211](https://github.com/documentcloud/underscore/issues/211), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L553-571)]
|
||||
* `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L712-717)]
|
||||
* `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L772-784)]
|
||||
* `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L865-867)]
|
||||
* `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L1243-1246)]
|
||||
|
||||
## Optimized methods <sup>(50+)</sup>
|
||||
|
||||
* `_.bind`
|
||||
* `_.bindAll`
|
||||
* `_.clone`
|
||||
* `_.compact`
|
||||
* `_.contains`, `_.include`
|
||||
* `_.defaults`
|
||||
* `_.defer`
|
||||
* `_.difference`
|
||||
* `_.each`
|
||||
* `_.every`, `_.all`
|
||||
@@ -245,7 +240,6 @@ require({
|
||||
* `_.invoke`
|
||||
* `_.isArguments`
|
||||
* `_.isDate`
|
||||
* `_.isEmpty`
|
||||
* `_.isFinite`
|
||||
* `_.isFunction`
|
||||
* `_.isObject`
|
||||
@@ -272,11 +266,11 @@ require({
|
||||
* `_.sortedIndex`
|
||||
* `_.template`
|
||||
* `_.throttle`
|
||||
* `_.times`
|
||||
* `_.toArray`
|
||||
* `_.union`
|
||||
* `_.uniq`, `_.unique`
|
||||
* `_.values`
|
||||
* `_.where`
|
||||
* `_.without`
|
||||
* `_.wrap`
|
||||
* `_.zip`
|
||||
@@ -284,30 +278,13 @@ require({
|
||||
|
||||
## Release Notes
|
||||
|
||||
### <sup>v0.7.0</sup>
|
||||
### <sup>v0.8.2</sup>
|
||||
|
||||
#### Compatibility Warnings ####
|
||||
|
||||
* Renamed `_.zipObject` to `_.object`
|
||||
* Replaced `_.drop` with `_.omit`
|
||||
* Made `_.drop` alias `_.rest`
|
||||
|
||||
#### Changes ####
|
||||
|
||||
* Added [_.invert](http://lodash.com/docs#invert), [_.pairs](http://lodash.com/docs#pairs), and [_.random](http://lodash.com/docs#random)
|
||||
* Added `_.result` to the `backbone` build
|
||||
* Added `exports`, `iife`, `-c`/`--stdout`, `-o`/`--output`, and `-s`/`--silent` build options
|
||||
* Ensured `isPlainObject` works with objects from other documements
|
||||
* Ensured `_.isEqual` compares values with circular references correctly
|
||||
* Ensured `_.merge` work with four or more arguments
|
||||
* Ensured `_.sortBy` performs a stable sort for `undefined` values
|
||||
* Ensured `_.template` works with "interpolate" delimiters containing ternary operators
|
||||
* Ensured the production build works in Node.js
|
||||
* Ensured template delimiters are tokenized correctly
|
||||
* Made pseudo private properties `_chain` and `_wrapped` double-underscored to avoid conflicts
|
||||
* Made `minify.js` support `underscore.js`
|
||||
* Reduced the size of `mobile` and `underscore` builds
|
||||
* Simplified `_.isEqual` and `_.size`
|
||||
* Ensured `_.map` returns an array when passed a falsey collection
|
||||
* Ensured `_.throttle` clears its timeout when `func` is called
|
||||
* Made `_.max`, `_.min`, `_.shuffle` support iterating objects
|
||||
* Reduced `createIterator`, `_.clone`, and `_.compact`
|
||||
* Re-optimized `_.max`, `_.min`, and `_.sortedIndex`
|
||||
|
||||
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
|
||||
|
||||
|
||||
112
build/minify.js
112
build/minify.js
@@ -9,18 +9,15 @@
|
||||
spawn = require('child_process').spawn;
|
||||
|
||||
/** The directory that is the base of the repository */
|
||||
var basePath = path.join(__dirname, '../');
|
||||
var basePath = fs.realpathSync(path.join(__dirname, '..'));
|
||||
|
||||
/** The directory where the Closure Compiler is located */
|
||||
var closurePath = path.join(basePath, 'vendor', 'closure-compiler', 'compiler.jar');
|
||||
|
||||
/** The distribution directory */
|
||||
var distPath = path.join(basePath, 'dist');
|
||||
|
||||
/** Load other modules */
|
||||
var preprocess = require(path.join(__dirname, 'pre-compile')),
|
||||
postprocess = require(path.join(__dirname, 'post-compile')),
|
||||
uglifyJS = require(path.join(basePath, 'vendor', 'uglifyjs', 'uglify-js'));
|
||||
var preprocess = require('./pre-compile'),
|
||||
postprocess = require('./post-compile'),
|
||||
uglifyJS = require('../vendor/uglifyjs/uglify-js');
|
||||
|
||||
/** Closure Compiler command-line options */
|
||||
var closureOptions = [
|
||||
@@ -37,31 +34,38 @@
|
||||
* The exposed `minify` function minifies a given Lo-Dash `source` and invokes
|
||||
* the `onComplete` callback when finished.
|
||||
*
|
||||
* @param {Array|String} source The array of command-line arguments or the
|
||||
* source to minify.
|
||||
* @param {Object} options The options object containing `onComplete`,
|
||||
* `silent`, and `workingName`.
|
||||
* @param {Array|String} [source=''] The source to minify or array of commands.
|
||||
* @param {Object} [options={}] The options object.
|
||||
*/
|
||||
function minify(source, options) {
|
||||
source || (source = '');
|
||||
options || (options = {});
|
||||
|
||||
// juggle arguments
|
||||
if (Array.isArray(source)) {
|
||||
// convert the command-line arguments to an options object
|
||||
// convert commands to an options object
|
||||
options = source;
|
||||
|
||||
var filePath = options[options.length - 1],
|
||||
dirPath = path.dirname(filePath),
|
||||
workingName = path.basename(filePath, '.js') + '.min',
|
||||
outputPath = path.join(dirPath, workingName + '.js'),
|
||||
isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1;
|
||||
isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1,
|
||||
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
|
||||
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
|
||||
|
||||
outputPath = options.reduce(function(result, value, index) {
|
||||
if (/-o|--output/.test(value)) {
|
||||
result = options[index + 1];
|
||||
result = path.join(fs.realpathSync(path.dirname(result)), path.basename(result));
|
||||
}
|
||||
return result;
|
||||
}, outputPath);
|
||||
|
||||
options = {
|
||||
'isSilent': isSilent,
|
||||
'isTemplate': isTemplate,
|
||||
'outputPath': outputPath
|
||||
};
|
||||
|
||||
source = fs.readFileSync(filePath, 'utf8');
|
||||
options = {
|
||||
'silent': isSilent,
|
||||
'workingName': workingName,
|
||||
'onComplete': function(source) {
|
||||
fs.writeFileSync(outputPath, source, 'utf8');
|
||||
}
|
||||
};
|
||||
}
|
||||
new Minify(source, options);
|
||||
}
|
||||
@@ -72,35 +76,28 @@
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {String} source The source to minify.
|
||||
* @param {Object} options The options object containing `onComplete`,
|
||||
* `silent`, and `workingName`.
|
||||
* @param {Object} options The options object.
|
||||
*/
|
||||
function Minify(source, options) {
|
||||
source || (source = '');
|
||||
options || (options = {});
|
||||
|
||||
if (typeof source != 'string') {
|
||||
// juggle arguments
|
||||
if (typeof source == 'object' && source) {
|
||||
options = source || options;
|
||||
source = options.source || '';
|
||||
}
|
||||
// create the destination directory if it doesn't exist
|
||||
if (!fs.existsSync(distPath)) {
|
||||
// avoid errors when called as a npm executable
|
||||
try {
|
||||
fs.mkdirSync(distPath);
|
||||
} catch(e) { }
|
||||
}
|
||||
|
||||
this.compiled = {};
|
||||
this.hybrid = {};
|
||||
this.uglified = {};
|
||||
this.isSilent = !!options.silent;
|
||||
this.onComplete = options.onComplete || function() {};
|
||||
this.workingName = options.workingName || 'temp';
|
||||
this.isSilent = !!options.isSilent;
|
||||
this.isTemplate = !!options.isTemplate;
|
||||
this.outputPath = options.outputPath;
|
||||
|
||||
source = preprocess(source);
|
||||
source = preprocess(source, options);
|
||||
this.source = source;
|
||||
|
||||
this.onComplete = options.onComplete || function(source) {
|
||||
fs.writeFileSync(this.outputPath, source, 'utf8');
|
||||
};
|
||||
|
||||
// begin the minification process
|
||||
closureCompile.call(this, source, onClosureCompile.bind(this));
|
||||
}
|
||||
@@ -117,10 +114,19 @@
|
||||
* @param {Function} callback The function to call once the process completes.
|
||||
*/
|
||||
function closureCompile(source, message, callback) {
|
||||
var options = closureOptions.slice();
|
||||
|
||||
// use simple optimizations when minifying template files
|
||||
if (this.isTemplate) {
|
||||
options = options.map(function(value) {
|
||||
return value.replace(/^(compilation_level)=.+$/, '$1=SIMPLE_OPTIMIZATIONS');
|
||||
});
|
||||
}
|
||||
|
||||
// the standard error stream, standard output stream, and Closure Compiler process
|
||||
var error = '',
|
||||
output = '',
|
||||
compiler = spawn('java', ['-jar', closurePath].concat(closureOptions));
|
||||
compiler = spawn('java', ['-jar', closurePath].concat(options));
|
||||
|
||||
// juggle arguments
|
||||
if (typeof message == 'function') {
|
||||
@@ -130,7 +136,7 @@
|
||||
|
||||
if (!this.isSilent) {
|
||||
console.log(message == null
|
||||
? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
|
||||
? 'Compressing ' + path.basename(this.outputPath, '.js') + ' using the Closure Compiler...'
|
||||
: message
|
||||
);
|
||||
}
|
||||
@@ -183,7 +189,7 @@
|
||||
|
||||
if (!this.isSilent) {
|
||||
console.log(message == null
|
||||
? 'Compressing ' + this.workingName + ' using UglifyJS...'
|
||||
? 'Compressing ' + path.basename(this.outputPath, '.js') + ' using UglifyJS...'
|
||||
: message
|
||||
);
|
||||
}
|
||||
@@ -278,7 +284,7 @@
|
||||
if (!this.isSilent) {
|
||||
console.log('Done. Size: %d bytes.', result.length);
|
||||
}
|
||||
var message = 'Compressing ' + this.workingName + ' using hybrid minification...';
|
||||
var message = 'Compressing ' + path.basename(this.outputPath, '.js') + ' using hybrid minification...';
|
||||
|
||||
// store the gzipped result and report the size
|
||||
this.uglified.gzip = result;
|
||||
@@ -332,24 +338,8 @@
|
||||
function onComplete() {
|
||||
var compiled = this.compiled,
|
||||
hybrid = this.hybrid,
|
||||
name = this.workingName,
|
||||
uglified = this.uglified;
|
||||
|
||||
// avoid errors when called as a npm executable
|
||||
try {
|
||||
// save the Closure Compiled version to disk
|
||||
fs.writeFileSync(path.join(distPath, name + '.compiler.js'), compiled.source);
|
||||
fs.writeFileSync(path.join(distPath, name + '.compiler.js.gz'), compiled.gzip);
|
||||
|
||||
// save the Uglified version to disk
|
||||
fs.writeFileSync(path.join(distPath, name + '.uglify.js'), uglified.source);
|
||||
fs.writeFileSync(path.join(distPath, name + '.uglify.js.gz'), uglified.gzip);
|
||||
|
||||
// save the hybrid minified version to disk
|
||||
fs.writeFileSync(path.join(distPath, name + '.hybrid.js'), hybrid.source);
|
||||
fs.writeFileSync(path.join(distPath, name + '.hybrid.js.gz'), hybrid.gzip);
|
||||
} catch(e) { }
|
||||
|
||||
// select the smallest gzipped file and use its minified counterpart as the
|
||||
// official minified release (ties go to Closure Compiler)
|
||||
var min = Math.min(compiled.gzip.length, hybrid.gzip.length, uglified.gzip.length);
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
'lodash':
|
||||
'/*!\n' +
|
||||
' Lo-Dash @VERSION lodash.com/license\n' +
|
||||
' Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE\n' +
|
||||
' Underscore.js 1.4.2 underscorejs.org/LICENSE\n' +
|
||||
'*/',
|
||||
'underscore':
|
||||
'/*! Underscore.js @VERSION github.com/documentcloud/underscore/blob/master/LICENSE */'
|
||||
'/*! Underscore.js @VERSION underscorejs.org/LICENSE */'
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -27,7 +27,7 @@
|
||||
*/
|
||||
function postprocess(source) {
|
||||
// move vars exposed by Closure Compiler into the IIFE
|
||||
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
|
||||
source = source.replace(/^((?:(['"])use strict\2;)?(?:var (?:[a-z]+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^)]+\){)/, '$3$1');
|
||||
|
||||
// unescape properties (i.e. foo["bar"] => foo.bar)
|
||||
source = source.replace(/(\w)\["([^."]+)"\]/g, function(match, left, right) {
|
||||
@@ -56,13 +56,20 @@
|
||||
// expose `postprocess`
|
||||
if (module != require.main) {
|
||||
module.exports = postprocess;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// read the Lo-Dash source file from the first argument if the script
|
||||
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
|
||||
// the same file
|
||||
(function() {
|
||||
var source = fs.readFileSync(process.argv[2], 'utf8');
|
||||
fs.writeFileSync(process.argv[2], postprocess(source), 'utf8');
|
||||
var options = process.argv;
|
||||
if (options.length < 3) {
|
||||
return;
|
||||
}
|
||||
var filePath = options[options.length - 1],
|
||||
source = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
fs.writeFileSync(filePath, postprocess(source), 'utf8');
|
||||
}());
|
||||
}
|
||||
}());
|
||||
|
||||
@@ -12,12 +12,11 @@
|
||||
'callback',
|
||||
'collection',
|
||||
'concat',
|
||||
'createCallback',
|
||||
'ctor',
|
||||
'hasOwnProperty',
|
||||
'identity',
|
||||
'index',
|
||||
'iteratee',
|
||||
'iteratorBind',
|
||||
'length',
|
||||
'nativeKeys',
|
||||
'object',
|
||||
@@ -33,6 +32,7 @@
|
||||
'stringClass',
|
||||
'thisArg',
|
||||
'toString',
|
||||
'undefined',
|
||||
'value',
|
||||
|
||||
// lesser used variables
|
||||
@@ -44,7 +44,6 @@
|
||||
'callee',
|
||||
'className',
|
||||
'compareAscending',
|
||||
'data',
|
||||
'forIn',
|
||||
'found',
|
||||
'funcs',
|
||||
@@ -58,19 +57,18 @@
|
||||
'isPlainObject',
|
||||
'methodName',
|
||||
'noaccum',
|
||||
'noop',
|
||||
'objectClass',
|
||||
'objectTypes',
|
||||
'pass',
|
||||
'properties',
|
||||
'property',
|
||||
'propsLength',
|
||||
'recursive',
|
||||
'source',
|
||||
'sources',
|
||||
'stackA',
|
||||
'stackB',
|
||||
'stackLength',
|
||||
'target',
|
||||
'valueProp',
|
||||
'values'
|
||||
'target'
|
||||
];
|
||||
|
||||
/** Used to minify `compileIterator` option properties */
|
||||
@@ -80,7 +78,6 @@
|
||||
'arrayBranch',
|
||||
'beforeLoop',
|
||||
'bottom',
|
||||
'exit',
|
||||
'firstArg',
|
||||
'hasDontEnumBug',
|
||||
'inLoop',
|
||||
@@ -106,7 +103,6 @@
|
||||
var propWhitelist = [
|
||||
'_',
|
||||
'__chain__',
|
||||
'__proto__',
|
||||
'__wrapped__',
|
||||
'after',
|
||||
'all',
|
||||
@@ -118,7 +114,6 @@
|
||||
'chain',
|
||||
'clearTimeout',
|
||||
'clone',
|
||||
'clones',
|
||||
'collect',
|
||||
'compact',
|
||||
'compose',
|
||||
@@ -177,12 +172,14 @@
|
||||
'isNull',
|
||||
'isNumber',
|
||||
'isObject',
|
||||
'isPlainObject',
|
||||
'isRegExp',
|
||||
'isString',
|
||||
'isUndefined',
|
||||
'keys',
|
||||
'last',
|
||||
'lastIndexOf',
|
||||
'lateBind',
|
||||
'map',
|
||||
'max',
|
||||
'memoize',
|
||||
@@ -214,13 +211,11 @@
|
||||
'sortBy',
|
||||
'sortedIndex',
|
||||
'source',
|
||||
'sources',
|
||||
'stackA',
|
||||
'stackB',
|
||||
'tail',
|
||||
'take',
|
||||
'tap',
|
||||
'template',
|
||||
'templates',
|
||||
'templateSettings',
|
||||
'throttle',
|
||||
'times',
|
||||
@@ -249,16 +244,24 @@
|
||||
/**
|
||||
* Pre-process a given Lo-Dash `source`, preparing it for minification.
|
||||
*
|
||||
* @param {String} source The source to process.
|
||||
* @param {String} [source=''] The source to process.
|
||||
* @param {Object} [options={}] The options object.
|
||||
* @returns {String} Returns the processed source.
|
||||
*/
|
||||
function preprocess(source) {
|
||||
// remove copyright to add later in post-compile.js
|
||||
source = source.replace(/\/\*![\s\S]+?\*\//, '');
|
||||
function preprocess(source, options) {
|
||||
source || (source = '');
|
||||
options || (options = {});
|
||||
|
||||
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
||||
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
||||
|
||||
if (options.isTemplate) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// remove copyright to add later in post-compile.js
|
||||
source = source.replace(/\/\*![\s\S]+?\*\//, '');
|
||||
|
||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
||||
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
||||
@@ -278,7 +281,7 @@
|
||||
// remove whitespace from string literals
|
||||
source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
|
||||
// avoids removing the '\n' of the `stringEscapes` object
|
||||
return string.replace(/\[object |delete |else if|function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) {
|
||||
return string.replace(/\[object |delete |else |function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) {
|
||||
return match == false || match == '\\n' ? '' : match;
|
||||
});
|
||||
});
|
||||
@@ -287,7 +290,7 @@
|
||||
source = source.replace(/\+"__p\+='"/g, '+"\\n__p+=\'"');
|
||||
|
||||
// remove whitespace from `_.template` related regexes
|
||||
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
||||
source = source.replace(/(?:reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
||||
return match.replace(/ |\\n/g, '');
|
||||
});
|
||||
|
||||
@@ -303,12 +306,12 @@
|
||||
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');
|
||||
|
||||
// remove debug sourceURL use in `_.template`
|
||||
source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');
|
||||
source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
|
||||
|
||||
// minify internal properties used by 'compareAscending', `_.clone`, `_.isEqual`, `_.merge`, and `_.sortBy`
|
||||
// minify internal properties used by 'compareAscending', `_.merge`, and `_.sortBy`
|
||||
(function() {
|
||||
var properties = ['clones', 'criteria', 'index', 'sources', 'thorough', 'value', 'values'],
|
||||
snippets = source.match(/( +)(?:function (?:clone|compareAscending|isEqual)|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
|
||||
var properties = ['criteria', 'index', 'value'],
|
||||
snippets = source.match(/( +)(?:function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
|
||||
|
||||
if (!snippets) {
|
||||
return;
|
||||
@@ -443,8 +446,17 @@
|
||||
// was invoked directly (e.g. `node pre-compile.js source.js`) and write to
|
||||
// the same file
|
||||
(function() {
|
||||
var source = fs.readFileSync(process.argv[2], 'utf8');
|
||||
fs.writeFileSync(process.argv[2], preprocess(source), 'utf8');
|
||||
var options = process.argv;
|
||||
if (options.length < 3) {
|
||||
return;
|
||||
}
|
||||
var filePath = options[options.length - 1],
|
||||
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
|
||||
source = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
fs.writeFileSync(filePath, preprocess(source, {
|
||||
'isTemplate': isTemplate
|
||||
}), 'utf8');
|
||||
}());
|
||||
}
|
||||
}());
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "lodash",
|
||||
"version": "0.7.0",
|
||||
"description": "A drop-in replacement for Underscore.js delivering performance, bug fixes, and additional features.",
|
||||
"homepage": "http://lodash.com",
|
||||
"main": [
|
||||
"./lodash.js",
|
||||
"./lodash.min.js"
|
||||
],
|
||||
"keywords": [
|
||||
"browser",
|
||||
"client",
|
||||
"functional",
|
||||
"performance",
|
||||
"server",
|
||||
"speed",
|
||||
"util"
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://lodash.com/license"
|
||||
}
|
||||
],
|
||||
"author": {
|
||||
"name": "John-David Dalton",
|
||||
"email": "john.david.dalton@gmail.com",
|
||||
"web": "http://allyoucanleet.com/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bestiejs/lodash.git"
|
||||
}
|
||||
}
|
||||
4534
doc/README.md
4534
doc/README.md
File diff suppressed because it is too large
Load Diff
@@ -20,9 +20,10 @@
|
||||
|
||||
// generate Markdown
|
||||
$markdown = docdown(array(
|
||||
'path' => '../' . $file,
|
||||
'title' => 'Lo-Dash <sup>v0.7.0</sup>',
|
||||
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
||||
'path' => '../' . $file,
|
||||
'title' => 'Lo-Dash <sup>v0.8.2</sup>',
|
||||
'toc' => 'categories',
|
||||
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
||||
));
|
||||
|
||||
// save to a .md file
|
||||
|
||||
77
lodash.min.js
vendored
77
lodash.min.js
vendored
@@ -1,42 +1,39 @@
|
||||
/*!
|
||||
Lo-Dash 0.7.0 lodash.com/license
|
||||
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
|
||||
Lo-Dash 0.8.2 lodash.com/license
|
||||
Underscore.js 1.4.2 underscorejs.org/LICENSE
|
||||
*/
|
||||
;(function(e,t){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||V),s=i?{}:e;if(i)for(var o=t-1;++o<r;)n=e[o]+"",(lt.call(s,n)?s[n]:s[n]=[]).push(e[o]);return function(e){if(i){var n=e+"";return lt.call(s,n)&&-1<k(s[n],e)}return-1<k(s,e,t)}}function a(){for(var e,t,n,s=-1,o=arguments.length,u={e:"",f:"",j:"",q:"",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],n=u.s,u.g=t,u.h=Dt,u.k=zt,u.n=Bt,u.p=st,u.r=u.r!==i,u.s=n==r?Wt:n,u.o==r&&(u.o=It),u.f||(u.f="if(!"+t+")return u");if("d"!=t||!u.c.i)u.c=r;t="",u.s&&(t+="'use strict';"),t+="var i,A,j="+u.g+",u",u.j&&(t+="="+u.j),t+=";"+u.f+";"+u.q+";",u.c&&(t+="var l=j.length;i=-1;",u.m&&(t+="if(l>-1&&l===l>>>0){"),u.o&&(t+="if(z.call(j)==x){j=j.split('')}"),t+=u.c.d+";while(++i<l){A=j[i];"+u.c.i+"}",u.m&&(t+="}"));if(u.m){u.c?t+="else{"
|
||||
:u.n&&(t+="var l=j.length;i=-1;if(l&&P(j)){while(++i<l){A=j[i+=''];"+u.m.i+"}}else{"),u.h||(t+="var v=typeof j=='function'&&r.call(j,'prototype');");if(u.k&&u.r)t+="var o=-1,p=Y[typeof j]?m(j):[],l=p.length;"+u.m.d+";while(++o<l){i=p[o];",u.h||(t+="if(!(v&&i=='prototype')){"),t+="A=j[i];"+u.m.i+"",u.h||(t+="}");else{t+=u.m.d+";for(i in j){";if(!u.h||u.r)t+="if(",u.h||(t+="!(v&&i=='prototype')"),!u.h&&u.r&&(t+="&&"),u.r&&(t+="g.call(j,i)"),t+="){";t+="A=j[i];"+u.m.i+";";if(!u.h||u.r)t+="}"}t+="}";
|
||||
if(u.h){t+="var f=j.constructor;";for(n=0;7>n;n++)t+="i='"+u.p[n]+"';if(","constructor"==u.p[n]&&(t+="!(f&&f.prototype===j)&&"),t+="g.call(j,i)){A=j[i];"+u.m.i+"}"}if(u.c||u.n)t+="}"}return t+=u.e+";return u",Function("D,E,F,I,e,K,g,h,N,P,R,T,U,k,X,Y,m,r,w,x,z","var G=function("+e+"){"+t+"};return G")(Xt,q,_,f,ft,hn,lt,D,k,b,un,w,an,p,Lt,Kt,bt,ht,pt,Ot,dt)}function f(e,n){var r=e.c,i=n.c,e=e.b,n=n.b;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function l(e,t){return at[
|
||||
t]}function c(e){return"\\"+Qt[e]}function h(e){return $t[e]}function p(e,t){return function(n,r,i){return e.call(t,n,r,i)}}function d(){}function v(e,t){if(e&&J.test(t))return"<e%-"+t+"%>";var n=at.length;return at[n]="'+__e("+t+")+'",ot+n+ut}function m(e,t,n,i){return i?(e=at.length,at[e]="';"+i+";__p+='",ot+e+ut):t?v(r,t):g(r,n)}function g(e,t){if(e&&J.test(t))return"<e%="+t+"%>";var n=at.length;return at[n]="'+((__t=("+t+"))==null?'':__t)+'",ot+n+ut}function y(e){return Jt[e]}function b(e){return dt
|
||||
.call(e)==xt}function w(e){return"function"==typeof e}function E(e,t){var n=i;if(!e||"object"!=typeof e||!t&&b(e))return n;var r=e.constructor;return(!qt||"function"==typeof e.toString||"string"!=typeof (e+""))&&(!w(r)||r instanceof r)?Ht?(hn(e,function(e,t,r){return n=!lt.call(r,t),i}),n===i):(hn(e,function(e,t){n=t}),n===i||lt.call(e,n)):n}function S(e,t,s,o){if(e==r)return e;s&&(t=i),o||(o={e:r}),o.t==r&&(o.t=!(!R.clone&&!z.clone&&!W.clone));if(((s=Kt[typeof e])||o.t)&&e.clone&&w(e.clone))return o
|
||||
.t=r,e.clone(t);if(s){var u=dt.call(e);if(!Vt[u]||jt&&b(e))return e;var a=u==Tt,s=a||(u==Lt?an(e,n):s)}if(!s||!t)return s?a?pt.call(e):cn({},e):e;s=e.constructor;switch(u){case Nt:return new s(e==n);case Ct:return new s(+e);case kt:case Ot:return new s(e);case At:return s(e.source,Z.exec(e))}for(var f=o.a||(o.a=[]),l=o.d||(o.d=[]),u=f.length;u--;)if(l[u]==e)return f[u];var c=a?s(u=e.length):{};f.push(c),l.push(e);if(a)for(a=-1;++a<u;)c[a]=S(e[a],t,r,o);else pn(e,function(e,n){c[n]=S(e,t,r,o)});return c
|
||||
}function x(e,t,s){if(e==r||t==r)return e===t;s||(s={e:r}),s.t==r&&(s.t=!(!R.isEqual&&!z.isEqual&&!W.isEqual));if(Kt[typeof e]||Kt[typeof t]||s.t){e=e.__wrapped__||e,t=t.__wrapped__||t;if(e.isEqual&&w(e.isEqual))return s.t=r,e.isEqual(t);if(t.isEqual&&w(t.isEqual))return s.t=r,t.isEqual(e)}if(e===t)return 0!==e||1/e==1/t;var o=dt.call(e);if(o!=dt.call(t))return i;switch(o){case Nt:case Ct:return+e==+t;case kt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case At:case Ot:return e==t+""}var u=Xt[o];if(jt&&!
|
||||
u&&(u=b(e))&&!b(t)||!u&&(o!=Lt||qt&&("function"!=typeof e.toString&&"string"==typeof (e+"")||"function"!=typeof t.toString&&"string"==typeof (t+""))))return i;for(var a=s.stackA||(s.stackA=[]),f=s.stackB||(s.stackB=[]),o=a.length;o--;)if(a[o]==e)return f[o]==t;var o=-1,l=n,c=0;a.push(e),f.push(t);if(u){c=e.length;if(l=c==t.length)for(;c--&&(l=x(e[c],t[c],s)););return l}u=e.constructor,a=t.constructor;if(u!=a&&(!w(u)||!(u instanceof u&&w(a)&&a instanceof a)))return i;for(var h in e)if(lt.call(e,h)&&
|
||||
(c++,!lt.call(t,h)||!x(e[h],t[h],s)))return i;for(h in t)if(lt.call(t,h)&&!(c--))return i;if(Dt)for(;7>++o;)if(h=st[o],lt.call(e,h)&&(!lt.call(t,h)||!x(e[h],t[h],s)))return i;return n}function T(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments.length;r&&(t=p(t,r));if(-1<i&&i===i>>>0){var o=It&&dt.call(e)==Ot?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=gn(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function N(e,t,n){if(e)return t==r||n?e[0]
|
||||
:pt.call(e,0,t)}function C(e,t){var n=[];if(!e)return n;for(var r,i=-1,s=e.length;++i<s;)r=e[i],un(r)?ct.apply(n,t?r:C(r)):n.push(r);return n}function k(e,t,n){if(!e)return-1;var r=-1,i=e.length;if(n){if("number"!=typeof n)return r=O(e,t),e[r]===t?r:-1;r=(0>n?wt(0,i+n):n)-1}for(;++r<i;)if(e[r]===t)return r;return-1}function L(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 A(e,t,n){return e?pt.call(e,t==r||n?1:t):[]}function O(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(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 M(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=D;++o<u;)if(r=n(e[o],o,e),t?!o||a[a.length-1]!==r:0>k(a,r))a.push(r),s.push(e[o]);return s}function _(e,t){function n(){var o=arguments,u=t;return i||
|
||||
(e=t[r]),s.length&&(o=o.length?s.concat(pt.call(o)):s),this instanceof n?(d.prototype=e.prototype,u=new d,(o=e.apply(u,o))&&Kt[typeof o]?o:u):e.apply(u,o)}var r,i=w(e);if(i){if(Ut||vt&&2<arguments.length)return vt.call.apply(vt,arguments)}else r=t,t=e;var s=pt.call(arguments,2);return n}function D(e){return e}function P(e){Ln(dn(e),function(t){var r=s[t]=e[t];o.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&ct.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,H,B,j,F,I="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),q=Array.prototype,R=Boolean.prototype,U=Object.prototype,z=Number.prototype,W=String.prototype,X=0,V=30,$=e._,J=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,K=/&(?:amp|lt|gt|quot|#x27);/g,Q=/\b__p\+='';/g,G=/\b(__p\+=)''\+/g,Y=/(__e\(.*?\)|\b__t\))\+'';/g,Z=/\w*$/,et=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,tt=
|
||||
RegExp("^"+(U.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),nt=/__token(\d+)__/g,rt=/[&<>"']/g,it=/['\n\r\t\u2028\u2029\\]/g,st="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),ot="__token",ut="__",at=[],ft=q.concat,lt=U.hasOwnProperty,ct=q.push,ht=U.propertyIsEnumerable,pt=q.slice,dt=U.toString,vt=tt.test(vt=pt.bind)&&vt,mt=Math.floor,gt=tt.test(gt=Array.isArray)&>,yt=e.isFinite,bt=tt.test
|
||||
(bt=Object.keys)&&bt,wt=Math.max,Et=Math.min,St=Math.random,xt="[object Arguments]",Tt="[object Array]",Nt="[object Boolean]",Ct="[object Date]",kt="[object Number]",Lt="[object Object]",At="[object RegExp]",Ot="[object String]",Mt=e.clearTimeout,_t=e.setTimeout,Dt,Pt,Ht,Bt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments)Bt=!r;Dt=4>(n+"").length,Ht="x"!=n[0],Pt=(n.splice.call(t,0,1),t[0])})(1);var jt=!b(arguments
|
||||
),Ft="x"!=pt.call("x")[0],It="xx"!="x"[0]+Object("x")[0];try{var qt=("[object Object]",dt.call(e.document||0)==Lt)}catch(Rt){}var Ut=vt&&/\n|Opera/.test(vt+dt.call(e.opera)),zt=bt&&/^.+$|true/.test(bt+!!e.attachEvent),Wt=!Ut,Xt={};Xt[Nt]=Xt[Ct]=Xt["[object Function]"]=Xt[kt]=Xt[Lt]=Xt[At]=i,Xt[xt]=Xt[Tt]=Xt[Ot]=n;var Vt={};Vt[xt]=Vt["[object Function]"]=i,Vt[Tt]=Vt[Nt]=Vt[Ct]=Vt[kt]=Vt[Lt]=Vt[At]=Vt[Ot]=n;var $t={"&":"&","<":"<",">":">",'"':""","'":"'"},Jt={"&":"&","<":"<"
|
||||
,">":">",""":'"',"'":"'"},Kt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Qt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var Gt={a:"d,c,y",j:"d",q:"if(!c)c=h;else if(y)c=k(c,y)",i:"if(c(A,i,d)===false)return u"},Yt={j:"{}",q:"var q;if(typeof c!='function'){var ii=c;c=function(A){return A[ii]}}else if(y)c=k(c,y)"
|
||||
,i:"q=c(A,i,d);(g.call(u,q)?u[q]++:u[q]=1)"},Zt={j:"true",i:"if(!c(A,i,d))return!u"},en={r:i,s:i,a:"n",j:"n",q:"for(var a=1,b=arguments.length;a<b;a++){if(j=arguments[a]){",i:"u[i]=A",e:"}}"},tn={j:"[]",i:"c(A,i,d)&&u.push(A)"},nn={q:"if(y)c=k(c,y)"},rn={i:{l:Gt.i}},sn={j:"",f:"if(!d)return[]",d:{b:"u=Array(l)",l:"u="+(zt?"Array(l)":"[]")},i:{b:"u[i]=c(A,i,d)",l:"u"+(zt?"[o]=":".push")+"(c(A,i,d))"}},on={r:i,a:"n,c,y",j:"{}",q:"var S=typeof c=='function';if(!S){var t=e.apply(E,arguments)}else if(y)c=k(c,y)"
|
||||
,i:"if(S?!c(A,i,n):N(t,i)<0)u[i]=A"};jt&&(b=function(e){return!!e&&!!lt.call(e,"callee")});var un=gt||function(e){return dt.call(e)==Tt};w(/x/)&&(w=function(e){return"[object Function]"==dt.call(e)});var an=Kt.__proto__!=U?E:function(e,t){if(!e)return i;var n=e.valueOf,r="function"==typeof n&&(r=n.__proto__)&&r.__proto__;return r?e==r||e.__proto__==r&&(t||!b(e)):E(e)},fn=a({a:"n",j:"[]",i:"u.push(i)"}),ln=a(en,{i:"if(u[i]==null)"+en.i}),cn=a(en),hn=a(Gt,nn,rn,{r:i}),pn=a(Gt,nn,rn),dn=a({r:i,a:"n"
|
||||
,j:"[]",i:"if(T(A))u.push(i)",e:"u.sort()"}),vn=a({a:"n",j:"{}",i:"u[A]=i"}),mn=a({a:"A",j:"true",q:"var H=z.call(A),l=A.length;if(D[H]"+(jt?"||P(A)":"")+"||(H==X&&l>-1&&l===l>>>0&&T(A.splice)))return!l",i:{l:"return false"}}),gn=bt?function(e){var t=typeof e;return"function"==t&&ht.call(e,"prototype")?fn(e):e&&Kt[t]?bt(e):[]}:fn,yn=a(en,{a:"n,ee,O",q:"var Q,dd=O==U,J=dd?arguments[3]:{g:[],d:[]};for(var a=1,b=dd?2:arguments.length;a<b;a++){if(j=arguments[a]){",i:"if((ee=A)&&((Q=R(ee))||U(ee))){var L=false,jj=J.g,ff=J.d,gg=ff.length;while(gg--)if(L=ff[gg]==ee)break;if(L){u[i]=jj[gg]}else{jj.push(A=(A=u[i])&&Q?(R(A)?A:[]):(U(A)?A:{}));ff.push(ee);u[i]=G(A,ee,U,J)}}else if(ee!=null)u[i]=ee"
|
||||
}),bn=a(on),wn=a({a:"n",j:"[]",i:"u"+(zt?"[o]=":".push")+"([i,A])"}),En=a(on,{q:"if(typeof c!='function'){var q,t=e.apply(E,arguments),l=t.length;for(i=1;i<l;i++){q=t[i];if(q in n)u[q]=n[q]}}else{if(y)c=k(c,y)",i:"if(c(A,i,n))u[i]=A",e:"}"}),Sn=a({a:"n",j:"[]",i:"u.push(A)"}),xn=a({a:"d,hh",j:"false",o:i,d:{b:"if(z.call(d)==x)return d.indexOf(hh)>-1"},i:"if(A===hh)return true"}),Tn=a(Gt,Yt),Nn=a(Gt,Zt),Cn=a(Gt,tn),kn=a(Gt,nn,{j:"",i:"if(c(A,i,d))return A"}),Ln=a(Gt,nn),An=a(Gt,Yt,{i:"q=c(A,i,d);(g.call(u,q)?u[q]:u[q]=[]).push(A)"
|
||||
}),On=a(sn,{a:"d,V",q:"var C=w.call(arguments,2),S=typeof V=='function'",i:{b:"u[i]=(S?V:A[V]).apply(A,C)",l:"u"+(zt?"[o]=":".push")+"((S?V:A[V]).apply(A,C))"}}),Mn=a(Gt,sn),_n=a(sn,{a:"d,bb",i:{b:"u[i]=A[bb]",l:"u"+(zt?"[o]=":".push")+"(A[bb])"}}),Dn=a({a:"d,c,B,y",j:"B",q:"var W=arguments.length<3;if(y)c=k(c,y)",d:{b:"if(W)u=j[++i]"},i:{b:"u=c(u,A,i,d)",l:"u=W?(W=false,A):c(u,A,i,d)"}}),Pn=a(Gt,tn,{i:"!"+tn.i}),Hn=a(Gt,Zt,{j:"false",i:Zt.i.replace("!","")}),Bn=a(Gt,Yt,sn,{i:{b:"u[i]={b:c(A,i,d),c:i,f:A}"
|
||||
,l:"u"+(zt?"[o]=":".push")+"({b:c(A,i,d),c:i,f:A})"},e:"u.sort(I);l=u.length;while(l--)u[l]=u[l].f"}),jn=a(tn,{a:"d,aa",q:"var t=[];K(aa,function(A,q){t.push(q)});var cc=t.length",i:"for(var q,Z=true,s=0;s<cc;s++){q=t[s];if(!(Z=A[q]===aa[q]))break}Z&&u.push(A)"}),Fn=a({r:i,s:i,a:"n",j:"n",q:"var M=arguments,l=M.length;if(l>1){for(var i=1;i<l;i++)u[M[i]]=F(u[M[i]],u);return u}",i:"if(T(u[i]))u[i]=F(u[i],u)"});s.VERSION="0.7.0",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply
|
||||
(this,arguments)}},s.bind=_,s.bindAll=Fn,s.chain=function(e){return e=new o(e),e.__chain__=n,e},s.clone=S,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=xn,s.countBy=Tn,s.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,Mt
|
||||
(a),a=_t(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=ln,s.defer=function(e){var n=pt.call(arguments,1);return _t(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=pt.call(arguments,2);return _t(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=ft.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(rt,h)},s.every=Nn,s.extend=cn,s.filter=Cn,s.find=kn,s.first=N,s.flatten=
|
||||
C,s.forEach=Ln,s.forIn=hn,s.forOwn=pn,s.functions=dn,s.groupBy=An,s.has=function(e,t){return e?lt.call(e,t):i},s.identity=D,s.indexOf=k,s.initial=function(e,t,n){return e?pt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=[];if(!e)return t;var n,r=arguments.length,i=[],s=-1,o=e.length;e:for(;++s<o;)if(n=e[s],0>k(t,n)){for(var a=1;a<r;a++)if(!(i[a]||(i[a]=u(arguments[a])))(n))continue e;t.push(n)}return t},s.invert=vn,s.invoke=On,s.isArguments=b,s.isArray=un,s.isBoolean=function(e){return e===
|
||||
n||e===i||dt.call(e)==Nt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=mn,s.isEqual=x,s.isFinite=function(e){return yt(e)&&dt.call(e)==kt},s.isFunction=w,s.isNaN=function(e){return dt.call(e)==kt&&e!=+e},s.isNull=function(e){return e===r},s.isObject=function(e){return e?Kt[typeof e]:i},s.isUndefined=function(e){return e===t},s.keys=gn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:pt.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?wt(0,r+n):Et(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.map=Mn,s.max=L,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return lt.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=yn,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=P,s.noConflict=function(){return e
|
||||
._=$,this},s.object=function(e,t){if(!e)return{};for(var n=-1,r=e.length,i={};++n<r;)t?i[e[n]]=t[n]:i[e[n][0]]=e[n][1];return i},s.omit=bn,s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},s.pairs=wn,s.partial=function(e){var t=pt.call(arguments,1),n=t.length;return function(){var r;return r=arguments,r.length&&(t.length=n,ct.apply(t,r)),r=1==t.length?e.call(this,t[0]):e.apply(this,t),t.length=n,r}},s.pick=En,s.pluck=_n,s.random=function(e,t){return e==
|
||||
r&&t==r?St():(e=+e||0,t==r&&(t=e,e=0),e+mt(St()*((+t||0)-e+1)))},s.range=function(e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=wt(0,Math.ceil((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=Dn,s.reduceRight=T,s.reject=Pn,s.rest=A,s.result=function(e,t){if(!e)return r;var n=e[t];return w(n)?e[t]():n},s.shuffle=function(e){if(!e)return[];for(var t,n=-1,r=e.length,i=Array(r);++n<r;)t=mt(St()*(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-1<
|
||||
t&&t===t>>>0?t:gn(e).length},s.some=Hn,s.sortBy=Bn,s.sortedIndex=O,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var e=e+"",o,u;o=n.escape;var a=n.evaluate,f=n.interpolate,h=s.templateSettings,p=n=n.variable||h.variable;o==r&&(o=h.escape),a==r&&(a=h.evaluate||i),f==r&&(f=h.interpolate),o&&(e=e.replace(o,v)),f&&(e=e.replace(f,g)),a!=H&&(H=a,F=RegExp("<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>"+(a?"|"+a.source:""),"g")),o=at.length,e=e.replace(F,m),o=o!=at.length,e="__p += '"+e
|
||||
.replace(it,c).replace(nt,l)+"';",at.length=0,p||(n=B||"obj",o?e="with("+n+"){"+e+"}":(n!=B&&(B=n,j=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(et,"$&"+n+".").replace(j,"$1__d"))),e=(o?e.replace(Q,""):e).replace(G,"$1").replace(Y,"$1;"),e="function("+n+"){"+(p?"":n+"||("+n+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(p?"":",__d="+n+"."+n+"||"+n)+";")+e+"return __p}";try{u=Function("_","return "+e)(s)}catch(d){throw d
|
||||
.source=e,d}return t?u(t):(u.source=e,u)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=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=_t(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&&w(e.toArray))return e.toArray();var t=e.length;return-1<t&&t===t>>>0?(Ft?dt.call(e)==Ot:"string"==typeof e)?e.split(""):pt.call
|
||||
(e):Sn(e)},s.unescape=function(e){return e==r?"":(e+"").replace(K,y)},s.union=function(){for(var e=-1,t=[],n=ft.apply(t,arguments),r=n.length;++e<r;)0>k(t,n[e])&&t.push(n[e]);return t},s.uniq=M,s.uniqueId=function(e){var t=X++;return e?e+t:t},s.values=Sn,s.where=jn,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&&ct.apply(n,arguments),t.apply(this
|
||||
,n)}},s.zip=function(e){if(!e)return[];for(var t=-1,n=L(_n(arguments,"length")),r=Array(n);++t<n;)r[t]=_n(arguments,t);return r},s.all=Nn,s.any=Hn,s.collect=Mn,s.detect=kn,s.drop=A,s.each=Ln,s.foldl=Dn,s.foldr=T,s.head=N,s.include=xn,s.inject=Dn,s.methods=dn,s.select=Cn,s.tail=A,s.take=N,s.unique=M,Ln({Date:Ct,Number:kt,RegExp:At,String:Ot},function(e,t){s["is"+t]=function(t){return dt.call(t)==e}}),o.prototype=s.prototype,P(s),o.prototype.chain=function(){return this.__chain__=n,this},o.prototype
|
||||
.value=function(){return this.__wrapped__},Ln("pop push reverse shift sort splice unshift".split(" "),function(e){var t=q[e];o.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),Pt&&e.length===0&&delete e[0],this.__chain__&&(e=new o(e),e.__chain__=n),e}}),Ln(["concat","join","slice"],function(e){var t=q[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})):I?"object"==typeof module&&module&&module.exports==I?(module.exports=s)._=s:I._=s:e._=s})(this);
|
||||
;(function(e,t){function s(e){if(e&&e.__wrapped__)return e;if(!(this instanceof s))return new s(e);this.__wrapped__=e}function o(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||H),s=i?{}:e;if(i)for(n=t-1;++n<r;){var o=e[n]+"";(Z.call(s,o)?s[o]:s[o]=[]).push(e[n])}return function(e){if(i){var n=e+"";return Z.call(s,n)&&-1<T(s[n],e)}return-1<T(s,e,t)}}function u(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function a(e,t,n){function r(){var u=arguments
|
||||
,a=s?this:t;return i||(e=t[o]),n.length&&(u=u.length?n.concat(nt.call(u)):n),this instanceof r?(p.prototype=e.prototype,a=new p,(u=e.apply(a,u))&&Ht[typeof u]?u:a):e.apply(a,u)}var i=m(e),s=!n,o=e;return s&&(n=t),r}function f(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:A}function l(){for(var e={e:"",g:Et,i:"",j:Mt,m:Tt,n:kt,o:J,p:"",q:n,r:_t,c:{d:""},l:{d:""}},t,i=-1;t=arguments[++i];)for(var s in t){var o=t[s];/d|h/.test(s)?("string"==typeof
|
||||
o&&(o={b:o,k:o}),e.c[s]=o.b,e.l[s]=o.k):e[s]=o}t=e.a;if("d"!=(e.f=/^[^,]+/.exec(t)[0])||!e.c.h)e.c=r;i="",e.r&&(i+="'use strict';"),i+="var i,A,j="+e.f+",t="+(e.i||e.f)+";if(!"+e.f+")return t;"+e.p+";",e.c&&(i+="var k=j.length;i=-1;",e.l&&(i+="if(k===+k){"),e.n&&(i+="if(y.call(j)==w){j=j.split('')}"),i+=e.c.d+";while(++i<k){A=j[i];"+e.c.h+"}",e.l&&(i+="}"));if(e.l){e.c?i+="else {":e.m&&(i+="var k=j.length;i=-1;if(k&&O(j)){while(++i<k){A=j[i+=''];"+e.l.h+"}}else {"),e.g||(i+="var u=typeof j=='function'&&q.call(j,'prototype');"
|
||||
);if(e.j&&e.q)i+="var n=-1,o=Y[typeof j]?l(j):[],k=o.length;"+e.l.d+";while(++n<k){i=o[n];",e.g||(i+="if(!(u&&i=='prototype')){"),i+="A=j[i];"+e.l.h+"",e.g||(i+="}");else{i+=e.l.d+";for(i in j){";if(!e.g||e.q)i+="if(",e.g||(i+="!(u&&i=='prototype')"),!e.g&&e.q&&(i+="&&"),e.q&&(i+="h.call(j,i)"),i+="){";i+="A=j[i];"+e.l.h+";";if(!e.g||e.q)i+="}"}i+="}";if(e.g){i+="var g=j.constructor;";for(s=0;7>s;s++)i+="i='"+e.o[s]+"';if(","constructor"==e.o[s]&&(i+="!(g&&g.prototype===j)&&"),i+="h.call(j,i)){A=j[i];"+
|
||||
e.l.h+"}"}if(e.c||e.m)i+="}"}return i+=e.e+";return t",Function("D,E,F,I,e,f,J,h,M,O,Q,S,T,X,Y,l,q,v,w,y,z","var G=function("+t+"){"+i+"};return G")(Dt,_,L,u,Q,f,en,Z,T,v,$t,m,Jt,mt,Ht,ut,tt,nt,yt,rt)}function c(e){return"\\"+Bt[e]}function h(e){return Qt[e]}function p(){}function d(e){return Gt[e]}function v(e){return rt.call(e)==ct}function m(e){return"function"==typeof e}function g(e){var t=i;if(!e||"object"!=typeof e||v(e))return t;var n=e.constructor;return(!Lt||"function"==typeof e.toString||"string"!=typeof
|
||||
(e+""))&&(!m(n)||n instanceof n)?xt?(en(e,function(e,n,r){return t=!Z.call(r,n),i}),t===i):(en(e,function(e,n){t=n}),t===i||Z.call(e,t)):t}function y(e,t,n,s,o){if(e==r)return e;n&&(t=i);if(n=Ht[typeof e]){var u=rt.call(e);if(!Pt[u]||Nt&&v(e))return e;var a=u==ht,n=a||(u==mt?Jt(e):n)}if(!n||!t)return n?a?nt.call(e):Zt({},e):e;n=e.constructor;switch(u){case pt:case dt:return new n(+e);case vt:case yt:return new n(e);case gt:return n(e.source,U.exec(e))}s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[
|
||||
u]==e)return o[u];var f=a?n(e.length):{};return s.push(e),o.push(f),(a?mn:tn)(e,function(e,n){f[n]=y(e,t,r,s,o)}),f}function b(e,t,s,o){if(e==r||t==r)return e===t;if(e===t)return 0!==e||1/e==1/t;if(Ht[typeof e]||Ht[typeof t])e=e.__wrapped__||e,t=t.__wrapped__||t;var u=rt.call(e);if(u!=rt.call(t))return i;switch(u){case pt:case dt:return+e==+t;case vt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case gt:case yt:return e==t+""}var a=Dt[u];if(Nt&&!a&&(a=v(e))&&!v(t)||!a&&(u!=mt||Lt&&("function"!=typeof e.
|
||||
toString&&"string"==typeof (e+"")||"function"!=typeof t.toString&&"string"==typeof (t+""))))return i;s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var u=-1,f=n,l=0;s.push(e),o.push(t);if(a){l=e.length;if(f=l==t.length)for(;l--&&(f=b(e[l],t[l],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!m(a)||!(a instanceof a&&m(f)&&f instanceof f)))return i;for(var c in e)if(Z.call(e,c)&&(l++,!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;for(c in t)if(Z.call(t,c)&&!(l--))return i;if(
|
||||
Et)for(;7>++u;)if(c=J[u],Z.call(e,c)&&(!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;return n}function w(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function E(e,t,n,r){var s=e,o=e?e.length:0,u=3>arguments.length;if(o!==+o)var a=sn(e),o=a.length;else kt&&rt.call(e)==yt&&(s=e.split(""));return mn(e,function(e,f,l){f=a?a[--o]:--o,n=u?(u=i,s[f]):t.call(r,n,s[f],f,l)}),n}function S(e,t,n){
|
||||
if(e)return t==r||n?e[0]:nt.call(e,0,t)}function x(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];$t(s)?et.apply(i,t?s:x(s)):i.push(s)}return i}function T(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?at(0,i+n):n||0)-1;else if(n)return r=C(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function N(e,t,n){return e?nt.call(e,t==r||n?1:t):[]}function C(e,t,n,r){var i=0,s=e?e.length:i;if(n){n=f(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 k(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n=f(n,r);++s<o;)if(r=n(e[s],s,e),t?!s||a[a.length-1]!==r:0>T(a,r))a.push(r),u.push(e[s]);return u}function L(e,t){return Ot||it&&2<arguments.length?it.call.apply(it,arguments):a(e,t,nt.call(arguments,2))}function A(e){return e}function O(e){mn(nn(e),function(t){var r=s[t]=e[t];s.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&et.apply(e,arguments)
|
||||
,e=r.apply(s,e),this.__chain__&&(e=new s(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,M="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),_=Array.prototype,D=Object.prototype,P=0,H=30,B=e._,j=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,F=/&(?:amp|lt|gt|quot|#x27);/g,I=/\b__p\+='';/g,q=/\b(__p\+=)''\+/g,R=/(__e\(.*?\)|\b__t\))\+'';/g,U=/\w*$/,z=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,W=RegExp("^"+(D.valueOf+""
|
||||
).replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/($^)/,V=/[&<>"']/g,$=/['\n\r\t\u2028\u2029\\]/g,J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),K=Math.ceil,Q=_.concat,G=Math.floor,Y=W.test(Y=Object.getPrototypeOf)&&Y,Z=D.hasOwnProperty,et=_.push,tt=D.propertyIsEnumerable,nt=_.slice,rt=D.toString,it=W.test(it=nt.bind)&&it,st=W.test(st=Array.isArray)&&st,ot=e.isFinite,ut=W.test(ut=Object.keys)&&ut
|
||||
,at=Math.max,ft=Math.min,lt=Math.random,ct="[object Arguments]",ht="[object Array]",pt="[object Boolean]",dt="[object Date]",vt="[object Number]",mt="[object Object]",gt="[object RegExp]",yt="[object String]",bt=e.clearTimeout,wt=e.setTimeout,Et,St,xt,Tt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments)Tt=!r;Et=4>(n+"").length,xt="x"!=n[0],St=(n.splice.call(t,0,1),t[0])})(1);var Nt=!v(arguments),Ct="x"!=nt.call("x"
|
||||
)[0],kt="xx"!="x"[0]+Object("x")[0];try{var Lt=("[object Object]",rt.call(e.document||0)==mt)}catch(At){}var Ot=it&&/\n|Opera/.test(it+rt.call(e.opera)),Mt=ut&&/^.+$|true/.test(ut+!!e.attachEvent),_t=!Ot,Dt={};Dt[pt]=Dt[dt]=Dt["[object Function]"]=Dt[vt]=Dt[mt]=Dt[gt]=i,Dt[ct]=Dt[ht]=Dt[yt]=n;var Pt={};Pt[ct]=Pt["[object Function]"]=i,Pt[ht]=Pt[pt]=Pt[dt]=Pt[vt]=Pt[mt]=Pt[gt]=Pt[yt]=n;var Ht={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Bt={"\\":"\\","'":"'","\n":"n"
|
||||
,"\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var jt={a:"d,c,x",p:"c=f(c,x)",h:"if(c(A,i,d)===false)return t"},Ft={i:"{}",p:"c=f(c,x)",h:"var p=c(A,i,d);(h.call(t,p)?t[p]++:t[p]=1)"},It={i:"true",h:"if(!c(A,i,d))return!t"},qt={q:i,r:i,a:"m",p:"for(var a=1,b=arguments.length;a<b;a++){if(j=arguments[a]){",h:"t[i]=A",e:"}}"},Rt={i:"[]",h:"c(A,i,d)&&t.push(A)"},Ut={p:"c=f(c,x)"}
|
||||
,zt={h:{k:jt.h}},Wt={i:"d||[]",d:{b:"t=Array(k)",k:"t="+(Mt?"Array(k)":"[]")},h:{b:"t[i]=c(A,i,d)",k:"t"+(Mt?"[n]=":".push")+"(c(A,i,d))"}},Xt={q:i,a:"m,c,x",i:"{}",p:"var R=typeof c=='function';if(R)c=f(c,x);else var s=e.apply(E,arguments)",h:"if(R?!c(A,i,m):M(s,i)<0)t[i]=A"},Vt=l({a:"m",i:"{}",h:"t[A]=i"});Nt&&(v=function(e){return e?Z.call(e,"callee"):i});var $t=st||function(e){return rt.call(e)==ht};m(/x/)&&(m=function(e){return"[object Function]"==rt.call(e)});var Jt=Y?function(e){if(!e||"object"!=typeof
|
||||
e)return i;var t=e.valueOf,n="function"==typeof t&&(n=Y(t))&&Y(n);return n?e==n||Y(e)==n&&!v(e):g(e)}:g,Kt=l({a:"m",i:"[]",h:"t.push(i)"}),Qt={"&":"&","<":"<",">":">",'"':""","'":"'"},Gt=Vt(Qt),Yt=l(qt,{h:"if(t[i]==null)"+qt.h}),Zt=l(qt),en=l(jt,Ut,zt,{q:i}),tn=l(jt,Ut,zt),nn=l({q:i,a:"m",i:"[]",h:"S(A)&&t.push(i)",e:"t.sort()"}),rn=l({a:"A",i:"true",p:"var H=y.call(A),k=A.length;if(D[H]"+(Nt?"||O(A)":"")+"||(H==X&&k===+k&&S(A.splice)))return!k",h:{k:"return false"}}),sn=ut?function(
|
||||
e){var t=typeof e;return"function"==t&&tt.call(e,"prototype")?Kt(e):e&&Ht[t]?ut(e):[]}:Kt,on=l(qt,{a:"m,dd,N",p:"var P,C=arguments,a=0;if(N==I){var b=2,ee=C[3],ff=C[4]}else var b=C.length,ee=[],ff=[];while(++a<b){if(j=C[a]){",h:"if((dd=A)&&((P=Q(dd))||T(dd))){var K=false,gg=ee.length;while(gg--)if(K=ee[gg]==dd)break;if(K){t[i]=ff[gg]}else {ee.push(dd);ff.push(A=(A=t[i],P)?(Q(A)?A:[]):(T(A)?A:{}));t[i]=G(A,dd,I,ee,ff)}}else if(dd!=null)t[i]=dd"}),un=l(Xt),an=l({a:"m",i:"[]",h:"t"+(Mt?"[n]=":".push"
|
||||
)+"([i,A])"}),fn=l(Xt,{p:"if(typeof c!='function'){var i=0,s=e.apply(E,arguments),k=s.length;while(++i<k){var p=s[i];if(p in m)t[p]=m[p]}}else {c=f(c,x)",h:"if(c(A,i,m))t[i]=A",e:"}"}),ln=l({a:"m",i:"[]",h:"t.push(A)"}),cn=l({a:"d,hh",i:"false",n:i,d:{b:"if(y.call(d)==w)return d.indexOf(hh)>-1"},h:"if(A===hh)return true"}),hn=l(jt,Ft),pn=l(jt,It),dn=l(jt,Rt),vn=l(jt,Ut,{i:"z",h:"if(c(A,i,d))return A"}),mn=l(jt,Ut),gn=l(jt,Ft,{h:"var p=c(A,i,d);(h.call(t,p)?t[p]:t[p]=[]).push(A)"}),yn=l(Wt,{a:"d,U"
|
||||
,p:"var C=v.call(arguments,2),R=typeof U=='function'",h:{b:"t[i]=(R?U:A[U]).apply(A,C)",k:"t"+(Mt?"[n]=":".push")+"((R?U:A[U]).apply(A,C))"}}),bn=l(jt,Wt),wn=l(Wt,{a:"d,bb",h:{b:"t[i]=A[bb]",k:"t"+(Mt?"[n]=":".push")+"(A[bb])"}}),En=l({a:"d,c,B,x",i:"B",p:"var V=arguments.length<3;c=f(c,x)",d:{b:"if(V)t=j[++i]"},h:{b:"t=c(t,A,i,d)",k:"t=V?(V=false,A):c(t,A,i,d)"}}),Sn=l(jt,Rt,{h:"!"+Rt.h}),xn=l(jt,It,{i:"false",h:It.h.replace("!","")}),Tn=l(jt,Ft,Wt,{h:{b:"t[i]={a:c(A,i,d),b:i,c:A}",k:"t"+(Mt?"[n]="
|
||||
:".push")+"({a:c(A,i,d),b:i,c:A})"},e:"t.sort(I);k=t.length;while(k--)t[k]=t[k].c"}),Nn=l(Rt,{a:"d,aa",p:"var s=[];J(aa,function(A,p){s.push(p)});var cc=s.length",h:"for(var Z=true,r=0;r<cc;r++){var p=s[r];if(!(Z=A[p]===aa[p]))break}Z&&t.push(A)"}),Cn=l({q:i,r:i,a:"m",p:"var L=arguments,i=0,k=L.length;if(k>1){while(++i<k)t[L[i]]=F(t[L[i]],t);return t}",h:"if(S(A))t[i]=F(A,t)"});s.VERSION="0.8.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=L,s.bindAll=
|
||||
Cn,s.chain=function(e){return e=new s(e),e.__chain__=n,e},s.clone=y,s.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},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=cn,s.countBy=hn,s.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,bt(a),a=wt(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=
|
||||
Yt,s.defer=function(e){var n=nt.call(arguments,1);return wt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=nt.call(arguments,2);return wt(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(_,arguments),i=o(i,r);++n<r;){var s=e[n];i(s)||t.push(s)}return t},s.escape=function(e){return e==r?"":(e+"").replace(V,h)},s.every=pn,s.extend=Zt,s.filter=dn,s.find=vn,s.first=S,s.flatten=x,s.forEach=mn,s.forIn=en,s.forOwn=tn,
|
||||
s.functions=nn,s.groupBy=gn,s.has=function(e,t){return e?Z.call(e,t):i},s.identity=A,s.indexOf=T,s.initial=function(e,t,n){return e?nt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=arguments.length,n=[],r=-1,i=e?e.length:0,s=[];e:for(;++r<i;){var u=e[r];if(0>T(s,u)){for(var a=1;a<t;a++)if(!(n[a]||(n[a]=o(arguments[a])))(u))continue e;s.push(u)}}return s},s.invert=Vt,s.invoke=yn,s.isArguments=v,s.isArray=$t,s.isBoolean=function(e){return e===n||e===i||rt.call(e)==pt},s.isDate=function(
|
||||
e){return rt.call(e)==dt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=rn,s.isEqual=b,s.isFinite=function(e){return ot(e)&&rt.call(e)==vt},s.isFunction=m,s.isNaN=function(e){return rt.call(e)==vt&&e!=+e},s.isNull=function(e){return e===r},s.isNumber=function(e){return rt.call(e)==vt},s.isObject=function(e){return e?Ht[typeof e]:i},s.isPlainObject=Jt,s.isRegExp=function(e){return rt.call(e)==gt},s.isString=function(e){return rt.call(e)==yt},s.isUndefined=function(e){return e===t},s
|
||||
.keys=sn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:nt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?at(0,r+n):ft(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.lateBind=function(e,t){return a(t,e,nt.call(arguments,2))},s.map=bn,s.max=w,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return Z.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=on,s.min=function(e,t,n){var r=
|
||||
Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},s.mixin=O,s.noConflict=function(){return e._=B,this},s.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},s.omit=un,s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},s.pairs=an,s.partial=function(e){return a(e,nt.call(arguments,1))},s.pick=fn,s.pluck=
|
||||
wn,s.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+G(lt()*((+t||0)-e+1))},s.range=function(e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=at(0,K((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=En,s.reduceRight=E,s.reject=Sn,s.rest=N,s.result=function(e,t){var n=e?e[t]:r;return m(n)?e[t]():n},s.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return mn(e,function(e){var r=G(lt()*(++t+1));n[t]=n[r],n[r]=e}),n},s.size=function(e){var t=e?e.length:0;return t===+
|
||||
t?t:sn(e).length},s.some=xn,s.sortBy=Tn,s.sortedIndex=C,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){e||(e=""),n||(n={});var r,i,o=0,u=s.templateSettings,a="__p += '",f=n.variable||u.variable,l=f;e.replace(RegExp((n.escape||u.escape||X).source+"|"+(n.interpolate||u.interpolate||X).source+"|"+(n.evaluate||u.evaluate||X).source+"|$","g"),function(t,n,i,s,u){a+=e.slice(o,u).replace($,c),a+=n?"'+__e("+n+")+'":s?"';"+s+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=s||j.test(
|
||||
n||i)),o=u+t.length}),a+="';",l||(f="obj",r?a="with("+f+"){"+a+"}":(n=RegExp("(\\(\\s*)"+f+"\\."+f+"\\b","g"),a=a.replace(z,"$&"+f+".").replace(n,"$1__d"))),a=(r?a.replace(I,""):a).replace(q,"$1").replace(R,"$1;"),a="function("+f+"){"+(l?"":f+"||("+f+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(l?"":",__d="+f+"."+f+"||"+f)+";")+a+"return __p}";try{i=Function("_","return "+a)(s)}catch(h){throw h.source=a,h}return t?i(t):(i.source=
|
||||
a,i)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=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?(bt(u),a=r,s=e.apply(o,i)):u||(u=wt(n,f)),s}},s.times=function(e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},s.toArray=function(e){if(!e)return[];var t=e.length;return t===+t?(Ct?rt.call(e)==yt:"string"==typeof e)?e.split(""):nt.call(e):ln(e)},s.unescape=function(e){return e==r?"":(e+"").replace(F,d)},s.union=
|
||||
function(){for(var e=-1,t=Q.apply(_,arguments),n=t.length,r=[];++e<n;){var i=t[e];0>T(r,i)&&r.push(i)}return r},s.uniq=k,s.uniqueId=function(e){var t=P++;return e?e+t:t},s.values=ln,s.where=Nn,s.without=function(e){for(var t=-1,n=e?e.length:0,r=o(arguments,1,20),i=[];++t<n;){var s=e[t];r(s)||i.push(s)}return i},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&et.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){for(var t=-1,n=e?w(wn(arguments,"length")):0,r=Array(n);++
|
||||
t<n;)r[t]=wn(arguments,t);return r},s.all=pn,s.any=xn,s.collect=bn,s.detect=vn,s.drop=N,s.each=mn,s.foldl=En,s.foldr=E,s.head=S,s.include=cn,s.inject=En,s.methods=nn,s.select=dn,s.tail=N,s.take=S,s.unique=k,O(s),s.prototype.chain=function(){return this.__chain__=n,this},s.prototype.value=function(){return this.__wrapped__},mn("pop push reverse shift sort splice unshift".split(" "),function(e){var t=_[e];s.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),St&&e.length===0&&delete
|
||||
e[0],this.__chain__&&(e=new s(e),e.__chain__=n),e}}),mn(["concat","join","slice"],function(e){var t=_[e];s.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new s(e),e.__chain__=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):M?"object"==typeof module&&module&&module.exports==M?(module.exports=s)._=s:M._=s:e._=s})(this);
|
||||
36
lodash.underscore.min.js
vendored
Normal file
36
lodash.underscore.min.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
Lo-Dash 0.8.2 lodash.com/license
|
||||
Underscore.js 1.4.2 underscorejs.org/LICENSE
|
||||
*/
|
||||
;(function(e,t){function s(e,t,r){var s;if(!e)return i;var t=x(t,r),o=e.length,r=-1;if(o===+o){for(;++r<o;)if(s=e[r],t(s,r,e))return n}else for(r in e)if(it.call(e,r)&&(s=e[r],t(s,r,e)))return n;return i}function o(e,t,n,r){var s,o,u=n;if(!e)return u;var a=3>arguments.length,t=x(t,r),f=e.length;s=-1;if(f===+f)for(a&&(u=e[++s]);++s<f;)o=e[s],u=t(u,o,s,e);else for(s in e)it.call(e,s)&&(o=e[s],u=a?(a=i,o):t(u,o,s,e));return u}function u(e,t){var n,r,i=e||[];if(!e)return i;var s=e.length;n=-1;if(s===+
|
||||
s)for(i=Array(s);++n<s;)r=e[n],i[n]=r[t];else for(n in i=[],e)it.call(e,n)&&(r=e[n],i.push(r[t]));return i}function a(e,t,n){var r,i=e||[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(i=Array(s);++n<s;)r=e[n],i[n]=t(r,n,e);else for(n in i=[],e)it.call(e,n)&&(r=e[n],i.push(t(r,n,e)));return i}function f(e,t,n){var r;if(!e)return e;var t=x(t,n),i=e.length,n=-1;if(i===+i)for(;++n<i;)r=e[n],t(r,n,e);else for(n in e)it.call(e,n)&&(r=e[n],t(r,n,e));return e}function l(e,n,r){var i,s=t;if(!
|
||||
e)return s;var n=x(n,r),o=e.length,r=-1;if(o===+o){for(;++r<o;)if(i=e[r],n(i,r,e))return i}else for(r in e)if(it.call(e,r)&&(i=e[r],n(i,r,e)))return i;return s}function c(e,t,n){var r,i=[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(;++n<s;)r=e[n],t(r,n,e)&&i.push(r);else for(n in e)it.call(e,n)&&(r=e[n],t(r,n,e)&&i.push(r));return i}function h(e,t,r){var s;if(!e)return n;var t=x(t,r),o=e.length,r=-1;if(o===+o){for(;++r<o;)if(s=e[r],!t(s,r,e))return i}else for(r in e)if(it.call(e,r)&&
|
||||
(s=e[r],!t(s,r,e)))return i;return n}function p(e,t){var r,s;if(!e)return i;var o=e.length;r=-1;if(o===+o){if(ut.call(e)==wt)return-1<e.indexOf(t);for(;++r<o;)if(s=e[r],s===t)return n}else for(r in e)if(it.call(e,r)&&(s=e[r],s===t))return n;return i}function d(e){var t,n,r=[];if(!e)return r;for(t in e)it.call(e,t)&&(n=e[t],r.push(n));return r}function v(e){var t,n,r=[];if(!e)return r;for(t in e)n=e[t],L(n)&&r.push(t);return r.sort(),r}function m(e,t,n){var r;if(!e)return e;t=x(t,n);for(r in e)n=e
|
||||
[r],t(n,r,e);return e}function g(e){var t,n,r=e;if(!e)return e;for(var i=1,s=arguments.length;i<s;i++)if(r=arguments[i])for(t in r)n=r[t],e[t]=n;return e}function y(e){var t,n=[];if(!e)return n;for(t in e)it.call(e,t)&&n.push(t);return n}function b(e){var t,n,r={};if(!e)return r;for(t in e)it.call(e,t)&&(n=e[t],r[n]=t);return r}function w(e){if(e&&e.__wrapped__)return e;if(!(this instanceof w))return new w(e);this.__wrapped__=e}function E(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1
|
||||
;if(e<n||n===t)return-1}return r<i?-1:1}function S(e,t,n){function r(){var i=arguments,s=t;return n.length&&(i=i.length?n.concat(ot.call(i)):n),this instanceof r?(C.prototype=e.prototype,s=new C,(i=e.apply(s,i))&&Tt[typeof i]?i:s):e.apply(s,i)}return r}function x(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:q}function T(e){return"\\"+Nt[e]}function N(e){return kt[e]}function C(){}function k(e){return Lt[e]}function L(e){return"function"==typeof
|
||||
e}function A(e){var t=i;if(!e||"object"!=typeof e||isArguments(e))return t;var n=e.constructor;return!L(n)||n instanceof n?(m(e,function(e,n){t=n}),t===i||it.call(e,t)):t}function O(e,t,s,o){if(e==r||t==r)return e===t;if(e===t)return 0!==e||1/e==1/t;if(Tt[typeof e]||Tt[typeof t])e=e.__wrapped__||e,t=t.__wrapped__||t;var u=ut.call(e);if(u!=ut.call(t))return i;switch(u){case vt:case mt:return+e==+t;case gt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case bt:case wt:return e==t+""}var a=Ct(e);if(!a&&u!=yt
|
||||
)return i;s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var f=n,u=0;s.push(e),o.push(t);if(a){u=e.length;if(f=u==t.length)for(;u--&&(f=O(e[u],t[u],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!L(a)||!(a instanceof a&&L(f)&&f instanceof f)))return i;for(var l in e)if(it.call(e,l)&&(u++,!it.call(t,l)||!O(e[l],t[l],s,o)))return i;for(l in t)if(it.call(t,l)&&!(u--))return i;return n}function M(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=x(t,n),f(e,function(
|
||||
e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function _(e,t,n,r){var s=e?e.length:0,o=3>arguments.length;if(s!==+s)var u=At(e),s=u.length;return f(e,function(a,f,l){f=u?u[--s]:--s,n=o?(o=i,e[f]):t.call(r,n,e[f],f,l)}),n}function D(e,t,n){if(e)return t==r||n?e[0]:ot.call(e,0,t)}function P(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];Ct(s)?st.apply(i,t?s:P(s)):i.push(s)}return i}function H(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?ht(0,
|
||||
i+n):n||0)-1;else if(n)return r=j(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function B(e,t,n){return e?ot.call(e,t==r||n?1:t):[]}function j(e,t,n,r){var i=0,s=e?e.length:i;if(n){n=x(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 F(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n=x(n,r);++s<o;)if(r=n(e[s],s,e),t?!s||a[a.length-1]!==r:0>H(a,r))a.push(r),u.push(e[s]);return u}function I
|
||||
(e,t){return xt||at&&2<arguments.length?at.call.apply(at,arguments):S(e,t,ot.call(arguments,2))}function q(e){return e}function R(e){f(v(e),function(t){var r=w[t]=e[t];w.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&st.apply(e,arguments),e=r.apply(w,e),this.__chain__&&(e=new w(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,U="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),z=Array.prototype,W=Object.prototype,
|
||||
X=0,V=e._,$=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,J=/&(?:amp|lt|gt|quot|#x27);/g,K=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,Q=RegExp("^"+(W.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),G=/($^)/,Y=/[&<>"']/g,Z=/['\n\r\t\u2028\u2029\\]/g,et=Math.ceil,tt=z.concat,nt=Math.floor,rt=Q.test(rt=Object.getPrototypeOf)&&rt,it=W.hasOwnProperty,st=z.push,ot=z.slice,ut=W.toString,at=Q.test(at=ot.bind)&&at,ft=Q.test(ft=Array.isArray
|
||||
)&&ft,lt=e.isFinite,ct=Q.test(ct=Object.keys)&&ct,ht=Math.max,pt=Math.min,dt=Math.random,vt="[object Boolean]",mt="[object Date]",gt="[object Number]",yt="[object Object]",bt="[object RegExp]",wt="[object String]",Et=e.clearTimeout,St=e.setTimeout,xt=at&&/\n|Opera/.test(at+ut.call(e.opera)),Tt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Nt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};w.templateSettings={escape:/<%-([\s\S]+?)%>/g
|
||||
,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},w.isArguments=function(e){return"[object Arguments]"==ut.call(e)},w.isArguments(arguments)||(w.isArguments=function(e){return e?it.call(e,"callee"):i});var Ct=ft||function(e){return"[object Array]"==ut.call(e)};L(/x/)&&(L=function(e){return"[object Function]"==ut.call(e)});var W=rt?function(e){if(!e||"object"!=typeof e)return i;var t=e.valueOf,n="function"==typeof t&&(n=rt(t))&&rt(n);return n?e==n||rt(e)==n&&!isArguments(e):A
|
||||
(e)}:A,kt={"&":"&","<":"<",">":">",'"':""","'":"'"},Lt=b(kt),At=ct?function(e){return e&&Tt[typeof e]?ct(e):[]}:y;w.VERSION="0.8.2",w.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},w.bind=I,w.bindAll=function(e){var t,n,r=e,i=e;if(!e)return i;n=arguments,t=0;var s=n.length;if(1<s){for(;++t<s;)i[n[t]]=I(i[n[t]],i);return i}for(t in r)n=r[t],L(n)&&(i[t]=I(n,i));return i},w.chain=function(e){return e=new w(e),e.__chain__=n,e},w.clone=function(
|
||||
e){return e&&Tt[typeof e]?Ct(e)?ot.call(e):g({},e):e},w.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},w.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},w.contains=p,w.countBy=function(e,t,n){var r,i={};if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(;++n<s;)r=e[n],r=t(r,n,e),it.call(i,r)?i[r]++:i[r]=1;else for(n in e)it.call(e,n)&&(r=e[n],r=t(r,n,e),it.call(i,r)?
|
||||
i[r]++:i[r]=1);return i},w.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,Et(a),a=St(i,t),r&&(o=e.apply(u,s)),o}},w.defaults=function(e){var t,n,i=e;if(!e)return e;for(var s=1,o=arguments.length;s<o;s++)if(i=arguments[s])for(t in i)n=i[t],e[t]==r&&(e[t]=n);return e},w.defer=function(e){var n=ot.call(arguments,1);return St(function(){return e.apply(t,n)},1)},w.delay=function(e,n){var r=ot.call(arguments,2);return St
|
||||
(function(){return e.apply(t,r)},n)},w.difference=function(e){for(var t=-1,n=e.length,r=tt.apply(z,arguments),i=[];++t<n;){var s=e[t];0>H(r,s,n)&&i.push(s)}return i},w.escape=function(e){return e==r?"":(e+"").replace(Y,N)},w.every=h,w.extend=g,w.filter=c,w.find=l,w.first=D,w.flatten=P,w.forEach=f,w.forIn=m,w.forOwn=function(e,t,n){var r;if(!e)return e;t=x(t,n);for(r in e)it.call(e,r)&&(n=e[r],t(n,r,e));return e},w.functions=v,w.groupBy=function(e,t,n){var r,i={};if(!e)return i;var t=x(t,n),s=e.length
|
||||
,n=-1;if(s===+s)for(;++n<s;){r=e[n];var o=t(r,n,e);(it.call(i,o)?i[o]:i[o]=[]).push(r)}else for(n in e)it.call(e,n)&&(r=e[n],o=t(r,n,e),(it.call(i,o)?i[o]:i[o]=[]).push(r));return i},w.has=function(e,t){return e?it.call(e,t):i},w.identity=q,w.indexOf=H,w.initial=function(e,t,n){return e?ot.call(e,0,-(t==r||n?1:t)):[]},w.intersection=function(e){var t=arguments.length,n=-1,r=e.length,i=[];e:for(;++n<r;){var s=e[n];if(0>H(i,s)){for(var o=1;o<t;o++)if(0>H(arguments[o],s))continue e;i.push(s)}}return i
|
||||
},w.invert=b,w.invoke=function(e,t){var n,r,i=e,s=e||[];if(!e)return s;var o=ot.call(arguments,2),u="function"==typeof t,a=i.length;n=-1;if(a===+a)for(s=Array(a);++n<a;)r=i[n],s[n]=(u?t:r[t]).apply(r,o);else for(n in s=[],i)it.call(i,n)&&(r=i[n],s.push((u?t:r[t]).apply(r,o)));return s},w.isArray=Ct,w.isBoolean=function(e){return e===n||e===i||ut.call(e)==vt},w.isDate=function(e){return ut.call(e)==mt},w.isElement=function(e){return e?1===e.nodeType:i},w.isEmpty=function(e){var t;if(!e)return n;var r=
|
||||
ut.call(e),s=e.length;if(Ct(e)||r==wt||r==yt&&s===+s&&L(e.splice))return!s;for(t in e)if(it.call(e,t))return i;return n},w.isEqual=O,w.isFinite=function(e){return lt(e)&&ut.call(e)==gt},w.isFunction=L,w.isNaN=function(e){return ut.call(e)==gt&&e!=+e},w.isNull=function(e){return e===r},w.isNumber=function(e){return ut.call(e)==gt},w.isObject=function(e){return e?Tt[typeof e]:i},w.isPlainObject=W,w.isRegExp=function(e){return ut.call(e)==bt},w.isString=function(e){return ut.call(e)==wt},w.isUndefined=
|
||||
function(e){return e===t},w.keys=At,w.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:ot.call(e,-t||i)}},w.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?ht(0,r+n):pt(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},w.map=a,w.max=M,w.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return it.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},w.min=function(e,t,n){var r=Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+
|
||||
s)t=x(t,n),f(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},w.mixin=R,w.noConflict=function(){return e._=V,this},w.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},w.omit=function(e,t,n){var r,i,s=e,o={};if(!e)return o;var u="function"==typeof t;if(u)t=x(t,n);else var a=tt.apply(z,arguments);for(r in s)if(i=s[r],u?!t(i,r,e):0>H(a,r))o[r]=i;return o},w.once=function(e){var t,s=i;return function(){
|
||||
return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},w.pairs=function(e){var t,n,r=[];if(!e)return r;for(t in e)it.call(e,t)&&(n=e[t],r.push([t,n]));return r},w.pick=function(e,t,n){var r,i,s=e,o={};if(!e)return o;if("function"!=typeof t){r=0,i=tt.apply(z,arguments);for(s=i.length;++r<s;){var u=i[r];u in e&&(o[u]=e[u])}}else for(r in t=x(t,n),s)i=s[r],t(i,r,e)&&(o[r]=i);return o},w.pluck=u,w.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+nt(dt()*((+t||0)-e+1))},w.range=function(
|
||||
e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=ht(0,et((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},w.reduce=o,w.reduceRight=_,w.reject=function(e,t,n){var r,i=[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(;++n<s;)r=e[n],!t(r,n,e)&&i.push(r);else for(n in e)it.call(e,n)&&(r=e[n],!t(r,n,e)&&i.push(r));return i},w.rest=B,w.result=function(e,t){var n=e?e[t]:r;return L(n)?e[t]():n},w.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return f(e,function(e){var r=nt(dt()*(++
|
||||
t+1));n[t]=n[r],n[r]=e}),n},w.size=function(e){var t=e?e.length:0;return t===+t?t:At(e).length},w.some=s,w.sortBy=function(e,t,n){var r,i=e||[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(i=Array(s);++n<s;)r=e[n],i[n]={a:t(r,n,e),b:n,c:r};else for(n in i=[],e)it.call(e,n)&&(r=e[n],i.push({a:t(r,n,e),b:n,c:r}));i.sort(E);for(s=i.length;s--;)i[s]=i[s].c;return i},w.sortedIndex=j,w.tap=function(e,t){return t(e),e},w.template=function(e,t,n){e||(e=""),n||(n={});var r,i,s=0,o=w.templateSettings
|
||||
,u="__p += '",a=n.variable||o.variable,f=a;e.replace(RegExp((n.escape||o.escape||G).source+"|"+(n.interpolate||o.interpolate||G).source+"|"+(n.evaluate||o.evaluate||G).source+"|$","g"),function(t,n,i,o,a){u+=e.slice(s,a).replace(Z,T),u+=n?"'+__e("+n+")+'":o?"';"+o+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=o||$.test(n||i)),s=a+t.length}),u+="';",f||(a="obj",r?u="with("+a+"){"+u+"}":(n=RegExp("(\\(\\s*)"+a+"\\."+a+"\\b","g"),u=u.replace(K,"$&"+a+".").replace(n,"$1__d"))),u="function("+
|
||||
a+"){"+(f?"":a+"||("+a+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(f?"":",__d="+a+"."+a+"||"+a)+";")+u+"return __p}";try{i=Function("_","return "+u)(w)}catch(l){throw l.source=u,l}return t?i(t):(i.source=u,i)},w.throttle=function(e,t){function n(){a=new Date,u=r,s=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?(Et(u),a=r,s=e.apply(o,i)):u||(u=St(n,f)),s}},w.times=function(
|
||||
e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},w.toArray=function(e){if(!e)return[];var t=e.length;return t===+t?"string"==typeof e?e.split(""):ot.call(e):d(e)},w.unescape=function(e){return e==r?"":(e+"").replace(J,k)},w.union=function(){for(var e=-1,t=tt.apply(z,arguments),n=t.length,r=[];++e<n;){var i=t[e];0>H(r,i)&&r.push(i)}return r},w.uniq=F,w.uniqueId=function(e){var t=X++;return e?e+t:t},w.values=d,w.where=function(e,t){var r,i,s=[];if(!e)return s;var o=[];m(t,function(
|
||||
e,t){o.push(t)});var u=o.length,a=e.length;r=-1;if(a===+a)for(;++r<a;){i=e[r];for(var f=n,l=0;l<u&&(f=o[l],f=i[f]===t[f]);l++);f&&s.push(i)}else for(r in e)if(it.call(e,r)){i=e[r],f=n;for(l=0;l<u&&(f=o[l],f=i[f]===t[f]);l++);f&&s.push(i)}return s},w.without=function(e){for(var t=-1,n=e.length,r=[];++t<n;){var i=e[t];0>H(arguments,i,1)&&r.push(i)}return r},w.wrap=function(e,t){return function(){var n=[e];return arguments.length&&st.apply(n,arguments),t.apply(this,n)}},w.zip=function(e){for(var t=-1
|
||||
,n=e?M(u(arguments,"length")):0,r=Array(n);++t<n;)r[t]=u(arguments,t);return r},w.all=h,w.any=s,w.collect=a,w.detect=l,w.drop=B,w.each=f,w.foldl=o,w.foldr=_,w.head=D,w.include=p,w.inject=o,w.methods=v,w.select=c,w.tail=B,w.take=D,w.unique=F,R(w),w.prototype.chain=function(){return this.__chain__=n,this},w.prototype.value=function(){return this.__wrapped__},f("pop push reverse shift sort splice unshift".split(" "),function(e){var t=z[e];w.prototype[e]=function(){var e=this.__wrapped__;return t.apply
|
||||
(e,arguments),this.__chain__&&(e=new w(e),e.__chain__=n),e}}),f(["concat","join","slice"],function(e){var t=z[e];w.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new w(e),e.__chain__=n),e}}),U?"object"==typeof module&&module&&module.exports==U?(module.exports=w)._=w:U._=w:e._=w})(this);
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "lodash",
|
||||
"version": "0.7.0",
|
||||
"version": "0.8.2",
|
||||
"description": "A drop-in replacement for Underscore.js delivering performance, bug fixes, and additional features.",
|
||||
"homepage": "http://lodash.com",
|
||||
"main": "lodash",
|
||||
"main": "./lodash",
|
||||
"keywords": [
|
||||
"browser",
|
||||
"client",
|
||||
@@ -43,10 +43,10 @@
|
||||
"rhino"
|
||||
],
|
||||
"jam": {
|
||||
"main": "./lodash.min.js"
|
||||
"main": "./lodash.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node build",
|
||||
"test": "node test/test"
|
||||
"test": "node test/test && node test/test-build"
|
||||
}
|
||||
}
|
||||
|
||||
102
perf/perf.js
102
perf/perf.js
@@ -276,7 +276,6 @@
|
||||
var twentyFiveValues = Array(25),\
|
||||
twentyFiveValues2 = Array(25),\
|
||||
fiftyValues = Array(50),\
|
||||
fiftyValues2 = Array(50),\
|
||||
seventyFiveValues = Array(75),\
|
||||
seventyFiveValues2 = Array(75),\
|
||||
lowerChars = "abcdefghijklmnopqrstuvwxyz".split(""),\
|
||||
@@ -294,14 +293,11 @@
|
||||
}\
|
||||
fiftyValues[index] =\
|
||||
seventyFiveValues[index] = lowerChars[index];\
|
||||
\
|
||||
fiftyValues2[index] =\
|
||||
seventyFiveValues2[index] = upperChars[index];\
|
||||
}\
|
||||
else {\
|
||||
if (index < 50) {\
|
||||
fiftyValues[index] = index;\
|
||||
fiftyValues2[index] = index + (index < 40 ? 75 : 0);\
|
||||
}\
|
||||
seventyFiveValues[index] = index;\
|
||||
seventyFiveValues2[index] = index + (index < 60 ? 75 : 0);\
|
||||
@@ -575,13 +571,13 @@
|
||||
);
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.difference` iterating 50 elements')
|
||||
Benchmark.Suite('`_.difference` iterating 50 and 75 elements')
|
||||
.add('Lo-Dash', {
|
||||
'fn': 'lodash.difference(fiftyValues, fiftyValues2)',
|
||||
'fn': 'lodash.difference(fiftyValues, seventyFiveValues2)',
|
||||
'teardown': 'function multiArrays(){}'
|
||||
})
|
||||
.add('Underscore', {
|
||||
'fn': '_.difference(fiftyValues, fiftyValues2)',
|
||||
'fn': '_.difference(fiftyValues, seventyFiveValues2)',
|
||||
'teardown': 'function multiArrays(){}'
|
||||
})
|
||||
);
|
||||
@@ -839,13 +835,13 @@
|
||||
);
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.intersection` iterating 50 elements')
|
||||
Benchmark.Suite('`_.intersection` iterating 50 and 75 elements')
|
||||
.add('Lo-Dash', {
|
||||
'fn': 'lodash.intersection(fiftyValues, fiftyValues2)',
|
||||
'fn': 'lodash.intersection(fiftyValues, seventyFiveValues2)',
|
||||
'teardown': 'function multiArrays(){}'
|
||||
})
|
||||
.add('Underscore', {
|
||||
'fn': '_.intersection(fiftyValues, fiftyValues2)',
|
||||
'fn': '_.intersection(fiftyValues, seventyFiveValues2)',
|
||||
'teardown': 'function multiArrays(){}'
|
||||
})
|
||||
);
|
||||
@@ -1152,6 +1148,74 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.reduce` iterating an array')
|
||||
.add('Lo-Dash', '\
|
||||
lodash.reduce(numbers, function(result, value, index) {\
|
||||
result[index] = value;\
|
||||
return result;\
|
||||
}, {});'
|
||||
)
|
||||
.add('Underscore', '\
|
||||
_.reduce(numbers, function(result, value, index) {\
|
||||
result[index] = value;\
|
||||
return result;\
|
||||
}, {});'
|
||||
)
|
||||
);
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.reduce` iterating an object')
|
||||
.add('Lo-Dash', '\
|
||||
lodash.reduce(object, function(result, value, key) {\
|
||||
result.push([key, value]);\
|
||||
return result;\
|
||||
}, []);'
|
||||
)
|
||||
.add('Underscore', '\
|
||||
_.reduce(object, function(result, value, key) {\
|
||||
result.push([key, value]);\
|
||||
return result;\
|
||||
}, []);'
|
||||
)
|
||||
);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.reduceRight` iterating an array')
|
||||
.add('Lo-Dash', '\
|
||||
lodash.reduceRight(numbers, function(result, value, index) {\
|
||||
result[index] = value;\
|
||||
return result;\
|
||||
}, {});'
|
||||
)
|
||||
.add('Underscore', '\
|
||||
_.reduceRight(numbers, function(result, value, index) {\
|
||||
result[index] = value;\
|
||||
return result;\
|
||||
}, {});'
|
||||
)
|
||||
);
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.reduceRight` iterating an object')
|
||||
.add('Lo-Dash', '\
|
||||
lodash.reduceRight(object, function(result, value, key) {\
|
||||
result.push([key, value]);\
|
||||
return result;\
|
||||
}, []);'
|
||||
)
|
||||
.add('Underscore', '\
|
||||
_.reduceRight(object, function(result, value, key) {\
|
||||
result.push([key, value]);\
|
||||
return result;\
|
||||
}, []);'
|
||||
)
|
||||
);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.shuffle`')
|
||||
.add('Lo-Dash', '\
|
||||
@@ -1412,6 +1476,18 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.where`')
|
||||
.add('Lo-Dash', '\
|
||||
lodash.where(objects, { "num": 9 });'
|
||||
)
|
||||
.add('Underscore', '\
|
||||
_.where(objects, { "num": 9 });'
|
||||
)
|
||||
);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.without`')
|
||||
.add('Lo-Dash', '\
|
||||
@@ -1435,13 +1511,13 @@
|
||||
);
|
||||
|
||||
suites.push(
|
||||
Benchmark.Suite('`_.without` iterating an array of 50 elements')
|
||||
Benchmark.Suite('`_.without` iterating an array of 75 and 50 elements')
|
||||
.add('Lo-Dash', {
|
||||
'fn': 'lodash.without.apply(lodash, [fiftyValues].concat(fiftyValues2));',
|
||||
'fn': 'lodash.without.apply(lodash, [seventyFiveValues2].concat(fiftyValues));',
|
||||
'teardown': 'function multiArrays(){}'
|
||||
})
|
||||
.add('Underscore', {
|
||||
'fn': '_.without.apply(_, [fiftyValues].concat(fiftyValues2));',
|
||||
'fn': '_.without.apply(_, [seventyFiveValues2].concat(fiftyValues));',
|
||||
'teardown': 'function multiArrays(){}'
|
||||
})
|
||||
);
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<script>
|
||||
// load Lo-Dash as a module
|
||||
var lodashModule,
|
||||
shimmedModule,
|
||||
underscoreModule;
|
||||
|
||||
window.require && require({
|
||||
@@ -51,15 +52,25 @@
|
||||
'urlArgs': 't=' + (+new Date),
|
||||
'paths': {
|
||||
'lodash': '../../' + QUnit.config.lodashFilename,
|
||||
'underscore': './../../' + QUnit.config.lodashFilename
|
||||
'shimmed': './../../' + QUnit.config.lodashFilename,
|
||||
'underscore': '../underscore/../../' + QUnit.config.lodashFilename
|
||||
},
|
||||
'shim': {
|
||||
'shimmed': {
|
||||
'exports': '_'
|
||||
}
|
||||
}
|
||||
},
|
||||
['lodash', 'underscore'], function(lodash, underscore) {
|
||||
if (lodash.noConflict) {
|
||||
['lodash', 'shimmed', 'underscore'], function(lodash, shimmed, underscore) {
|
||||
if (lodash && lodash.noConflict) {
|
||||
lodashModule = lodash.noConflict();
|
||||
lodashModule.moduleName = 'lodash';
|
||||
}
|
||||
if (underscore.noConflict) {
|
||||
if (shimmed.noConflict) {
|
||||
shimmedModule = shimmed.noConflict();
|
||||
shimmedModule.moduleName = 'shimmed';
|
||||
}
|
||||
if (underscore && underscore.noConflict) {
|
||||
underscoreModule = underscore.noConflict();
|
||||
underscoreModule.moduleName = 'underscore';
|
||||
}
|
||||
|
||||
3
test/template/a.jst
Normal file
3
test/template/a.jst
Normal file
@@ -0,0 +1,3 @@
|
||||
<ul>
|
||||
<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>
|
||||
</ul>
|
||||
1
test/template/b.jst
Normal file
1
test/template/b.jst
Normal file
@@ -0,0 +1 @@
|
||||
<% print("Hello " + epithet); %>.
|
||||
1
test/template/c.tpl
Normal file
1
test/template/c.tpl
Normal file
@@ -0,0 +1 @@
|
||||
Hello {{ name }}!
|
||||
@@ -69,12 +69,9 @@
|
||||
'intersection',
|
||||
'last',
|
||||
'lastIndexOf',
|
||||
'max',
|
||||
'min',
|
||||
'object',
|
||||
'range',
|
||||
'rest',
|
||||
'shuffle',
|
||||
'sortedIndex',
|
||||
'tail',
|
||||
'take',
|
||||
@@ -113,11 +110,14 @@
|
||||
'inject',
|
||||
'invoke',
|
||||
'map',
|
||||
'max',
|
||||
'min',
|
||||
'pluck',
|
||||
'reduce',
|
||||
'reduceRight',
|
||||
'reject',
|
||||
'select',
|
||||
'shuffle',
|
||||
'size',
|
||||
'some',
|
||||
'sortBy',
|
||||
@@ -134,6 +134,7 @@
|
||||
'debounce',
|
||||
'defer',
|
||||
'delay',
|
||||
'lateBind',
|
||||
'memoize',
|
||||
'once',
|
||||
'partial',
|
||||
@@ -164,6 +165,7 @@
|
||||
'isNull',
|
||||
'isNumber',
|
||||
'isObject',
|
||||
'isPlainObject',
|
||||
'isRegExp',
|
||||
'isString',
|
||||
'isUndefined',
|
||||
@@ -237,18 +239,12 @@
|
||||
|
||||
/** List of methods used by Underscore */
|
||||
var underscoreMethods = _.without.apply(_, [allMethods].concat([
|
||||
'countBy',
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'invert',
|
||||
'isPlainObject',
|
||||
'lateBind',
|
||||
'merge',
|
||||
'object',
|
||||
'omit',
|
||||
'pairs',
|
||||
'partial',
|
||||
'random',
|
||||
'unescape',
|
||||
'where'
|
||||
'partial'
|
||||
]));
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -292,6 +288,31 @@
|
||||
return realToAliasMap[funcName] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of methods belonging to the given `category`.
|
||||
*
|
||||
* @private
|
||||
* @param {String} category The category to filter by.
|
||||
* @returns {Array} Returns a new array of method names belonging to the given category.
|
||||
*/
|
||||
function getMethodsByCategory(category) {
|
||||
switch (category) {
|
||||
case 'Arrays':
|
||||
return arraysMethods.slice();
|
||||
case 'Chaining':
|
||||
return chainingMethods.slice();
|
||||
case 'Collections':
|
||||
return collectionsMethods.slice();
|
||||
case 'Functions':
|
||||
return functionsMethods.slice();
|
||||
case 'Objects':
|
||||
return objectsMethods.slice();
|
||||
case 'Utilities':
|
||||
return utilityMethods.slice();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the real name, not alias, of a given function name.
|
||||
*
|
||||
@@ -370,14 +391,16 @@
|
||||
else if (functionsMethods.indexOf(methodName) > -1) {
|
||||
if (methodName == 'after') {
|
||||
func(1, noop);
|
||||
} else if (methodName == 'bindAll') {
|
||||
func({ 'noop': noop });
|
||||
} else if (methodName == 'lateBind') {
|
||||
func(lodash, 'identity', array, string);
|
||||
} else if (/^(?:bind|partial)$/.test(methodName)) {
|
||||
func(noop, object, array, string);
|
||||
} else if (/^(?:compose|memoize|wrap)$/.test(methodName)) {
|
||||
func(noop, noop);
|
||||
} else if (/^(?:debounce|throttle)$/.test(methodName)) {
|
||||
func(noop, 100);
|
||||
} else if (methodName == 'bindAll') {
|
||||
func({ 'noop': noop });
|
||||
} else {
|
||||
func(noop);
|
||||
}
|
||||
@@ -413,102 +436,112 @@
|
||||
console.log(e);
|
||||
pass = false;
|
||||
}
|
||||
equal(pass, true, methodName + ': ' + message);
|
||||
equal(pass, true, '_.' + methodName + ': ' + message);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash build');
|
||||
QUnit.module('minified AMD snippet');
|
||||
|
||||
(function() {
|
||||
var commands = [
|
||||
'backbone',
|
||||
'csp',
|
||||
'legacy',
|
||||
'mobile',
|
||||
'strict',
|
||||
'underscore',
|
||||
'category=arrays',
|
||||
'category=chaining',
|
||||
'category=collections',
|
||||
'category=functions',
|
||||
'category=objects',
|
||||
'category=utilities',
|
||||
'exclude=union,uniq,zip',
|
||||
'include=each,filter,map',
|
||||
'category=collections,functions',
|
||||
'underscore backbone',
|
||||
'backbone legacy category=utilities exclude=first,last',
|
||||
'underscore mobile strict category=functions exports=amd,global include=pick,uniq',
|
||||
]
|
||||
.concat(
|
||||
allMethods.map(function(methodName) {
|
||||
return 'include=' + methodName;
|
||||
})
|
||||
);
|
||||
var start = _.once(QUnit.start);
|
||||
|
||||
commands.forEach(function(command) {
|
||||
asyncTest('`lodash`', function() {
|
||||
build(['-s'], function(source, filePath) {
|
||||
// used by r.js build optimizer
|
||||
var defineHasRegExp = /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
|
||||
basename = path.basename(filePath, '.js');
|
||||
|
||||
ok(!!defineHasRegExp.exec(source), basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('template builds');
|
||||
|
||||
(function() {
|
||||
var templatePath = __dirname + '/template';
|
||||
|
||||
asyncTest('`lodash template=*.jst`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
build(['--silent'].concat(command.split(' ')), function(source, filepath) {
|
||||
var basename = path.basename(filepath, '.js'),
|
||||
context = createContext(),
|
||||
methodNames = [];
|
||||
build(['-s', 'template=' + templatePath + '/*.jst'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) { }
|
||||
var data = {
|
||||
'a': { 'people': ['moe', 'larry', 'curly'] },
|
||||
'b': { 'epithet': 'stooge' }
|
||||
};
|
||||
|
||||
if (/underscore/.test(command)) {
|
||||
methodNames = underscoreMethods;
|
||||
}
|
||||
if (/backbone/.test(command)) {
|
||||
methodNames = backboneDependencies;
|
||||
}
|
||||
if (/include/.test(command)) {
|
||||
methodNames = methodNames.concat(command.match(/include=(\S*)/)[1].split(/, */));
|
||||
}
|
||||
if (/category/.test(command)) {
|
||||
methodNames = command.match(/category=(\S*)/)[1].split(/, */).reduce(function(result, category) {
|
||||
switch (category) {
|
||||
case 'arrays':
|
||||
return result.concat(arraysMethods);
|
||||
case 'chaining':
|
||||
return result.concat(chainingMethods);
|
||||
case 'collections':
|
||||
return result.concat(collectionsMethods);
|
||||
case 'functions':
|
||||
return result.concat(functionsMethods);
|
||||
case 'objects':
|
||||
return result.concat(objectsMethods);
|
||||
case 'utilities':
|
||||
return result.concat(utilityMethods);
|
||||
}
|
||||
return result;
|
||||
}, methodNames);
|
||||
}
|
||||
if (!methodNames.length) {
|
||||
methodNames = allMethods;
|
||||
}
|
||||
context._ = _;
|
||||
vm.runInContext(source, context);
|
||||
var templates = context._.templates;
|
||||
|
||||
if (/exclude/.test(command)) {
|
||||
methodNames = _.without.apply(_, [methodNames].concat(
|
||||
expandMethodNames(command.match(/exclude=(\S*)/)[1].split(/, */))
|
||||
));
|
||||
} else {
|
||||
methodNames = expandMethodNames(methodNames);
|
||||
}
|
||||
equal(templates.a(data.a).replace(/[\r\n]+/g, ''), '<ul><li>moe</li><li>larry</li><li>curly</li></ul>', basename);
|
||||
equal(templates.b(data.b), 'Hello stooge.', basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
var lodash = context._ || {};
|
||||
methodNames = _.unique(methodNames);
|
||||
asyncTest('`lodash settings=...`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
methodNames.forEach(function(methodName) {
|
||||
testMethod(lodash, methodName, basename);
|
||||
});
|
||||
build(['-s', 'template=' + templatePath + '/*.tpl', 'settings={interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/}'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
start();
|
||||
});
|
||||
var data = {
|
||||
'c': { 'name': 'Mustache' }
|
||||
};
|
||||
|
||||
context._ = _;
|
||||
vm.runInContext(source, context);
|
||||
var templates = context._.templates;
|
||||
|
||||
equal(templates.c(data.c), 'Hello Mustache!', basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('independent builds');
|
||||
|
||||
(function() {
|
||||
asyncTest('debug only', function() {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-d', '-s'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('debug custom', function () {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-d', '-s', 'backbone'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash.custom');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('minified only', function() {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-m', '-s'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash.min');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('minified custom', function () {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-m', '-s', 'backbone'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash.custom.min');
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
@@ -524,16 +557,15 @@
|
||||
});
|
||||
|
||||
['non-strict', 'strict'].forEach(function(strictMode, index) {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
asyncTest(strictMode + ' should ' + (index ? 'error': 'silently fail') + ' attempting to overwrite read-only properties', function() {
|
||||
var commands = ['-s', 'include=bindAll,defaults,extend'];
|
||||
var commands = ['-s', 'include=bindAll,defaults,extend'],
|
||||
start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
if (index) {
|
||||
commands.push('strict');
|
||||
}
|
||||
|
||||
build(commands, function(source, filepath) {
|
||||
var basename = path.basename(filepath, '.js'),
|
||||
build(commands, function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext(),
|
||||
pass = !index;
|
||||
|
||||
@@ -559,18 +591,63 @@
|
||||
QUnit.module('underscore modifier');
|
||||
|
||||
(function() {
|
||||
var start = _.once(QUnit.start);
|
||||
asyncTest('modified methods should work correctly', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
asyncTest('should not have deep clone', function() {
|
||||
build(['-s', 'underscore'], function(source, filepath) {
|
||||
var array = [{ 'a': 1 }],
|
||||
basename = path.basename(filepath, '.js'),
|
||||
build(['-s', 'underscore'], function(source, filePath) {
|
||||
var last,
|
||||
array = [{ 'value': 1 }, { 'value': 2 }],
|
||||
basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._;
|
||||
|
||||
ok(lodash.clone(array, true)[0] === array[0], basename);
|
||||
lodash.each(array, function(value) {
|
||||
last = value;
|
||||
return false;
|
||||
});
|
||||
|
||||
equal(last.value, 2, '_.each: ' + basename);
|
||||
equal(lodash.isEmpty('moe'), false, '_.isEmpty: ' + basename);
|
||||
|
||||
var object = { 'fn': lodash.bind(function(x) { return this.x + x; }, { 'x': 1 }, 1) };
|
||||
equal(object.fn(), 2, '_.bind: ' + basename);
|
||||
|
||||
ok(lodash.clone(array, true)[0] === array[0], '_.clone: ' + basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('`lodash underscore include=partial`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'underscore', 'include=partial'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._;
|
||||
|
||||
equal(lodash.partial(_.identity, 2)(), 2, '_.partial: ' + basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('`lodash underscore plus=clone`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'underscore', 'plus=clone'], function(source, filePath) {
|
||||
var array = [{ 'value': 1 }],
|
||||
basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._,
|
||||
clone = lodash.clone(array, true);
|
||||
|
||||
deepEqual(array, clone, basename);
|
||||
notEqual(array, clone, basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
@@ -590,11 +667,11 @@
|
||||
];
|
||||
|
||||
commands.forEach(function(command, index) {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
build(['-s', command], function(source, filepath) {
|
||||
var basename = path.basename(filepath, '.js'),
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', command], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext(),
|
||||
pass = false;
|
||||
|
||||
@@ -644,21 +721,33 @@
|
||||
QUnit.module('iife command');
|
||||
|
||||
(function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
var commands = [
|
||||
'iife=this["lodash"]=(function(window,undefined){%output%;return lodash}(this))',
|
||||
'iife=define(function(window,undefined){return function(){%output%;return lodash}}(this));'
|
||||
];
|
||||
|
||||
asyncTest('`lodash iife=...`', function() {
|
||||
build(['-s', 'iife=!function(window,undefined){%output%}(this)'], function(source, filepath) {
|
||||
var basename = path.basename(filepath, '.js'),
|
||||
context = createContext();
|
||||
commands.forEach(function(command) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) { }
|
||||
build(['-s', 'exports=none', command], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
var lodash = context._ || {};
|
||||
ok(_.isString(lodash.VERSION), basename);
|
||||
ok(/!function/.test(source), basename);
|
||||
start();
|
||||
context.define = function(func) {
|
||||
context.lodash = func();
|
||||
};
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var lodash = context.lodash || {};
|
||||
ok(_.isString(lodash.VERSION), basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
@@ -669,11 +758,11 @@
|
||||
|
||||
(function() {
|
||||
['-o a.js', '--output a.js'].forEach(function(command, index) {
|
||||
var start = _.once(QUnit.start);
|
||||
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
build(['-s'].concat(command.split(' ')), function(source, filepath) {
|
||||
equal(filepath, 'a.js', command);
|
||||
var start = _.once(QUnit.start);
|
||||
|
||||
build(['-s'].concat(command.split(' ')), function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'a', command);
|
||||
start();
|
||||
});
|
||||
});
|
||||
@@ -686,12 +775,18 @@
|
||||
|
||||
(function() {
|
||||
['-c', '--stdout'].forEach(function(command, index) {
|
||||
var descriptor = Object.getOwnPropertyDescriptor(global, 'console'),
|
||||
start = _.once(QUnit.start);
|
||||
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
build([command, 'exports=', 'include='], function(source, filepath) {
|
||||
equal(source, '');
|
||||
var written,
|
||||
start = _.once(QUnit.start),
|
||||
write = process.stdout.write;
|
||||
|
||||
process.stdout.write = function(string) {
|
||||
written = string;
|
||||
};
|
||||
|
||||
build([command, 'exports=', 'include='], function(source) {
|
||||
process.stdout.write = write;
|
||||
equal(written, source);
|
||||
equal(arguments.length, 1);
|
||||
start();
|
||||
});
|
||||
@@ -704,27 +799,170 @@
|
||||
QUnit.module('minify underscore');
|
||||
|
||||
(function() {
|
||||
var start = _.once(QUnit.start);
|
||||
|
||||
asyncTest('`node minify underscore.js`', function() {
|
||||
var source = fs.readFileSync(path.join(__dirname, '..', 'vendor', 'underscore', 'underscore.js'), 'utf8');
|
||||
var source = fs.readFileSync(path.join(__dirname, '..', 'vendor', 'underscore', 'underscore.js'), 'utf8'),
|
||||
start = _.once(QUnit.start);
|
||||
|
||||
minify(source, {
|
||||
'silent': true,
|
||||
'isSilent': true,
|
||||
'workingName': 'underscore.min',
|
||||
'onComplete': function(result) {
|
||||
var context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(result, context);
|
||||
} catch(e) { }
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var underscore = context._ || {};
|
||||
ok(_.isString(underscore.VERSION));
|
||||
ok(result.match(/\n/g).length < source.match(/\n/g).length);
|
||||
ok(!/Lo-Dash/.test(result) && result.match(/\n/g).length < source.match(/\n/g).length);
|
||||
start();
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('mobile build');
|
||||
|
||||
(function() {
|
||||
asyncTest('`lodash mobile`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'mobile'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var array = [1, 2, 3],
|
||||
object1 = [{ 'a': 1 }],
|
||||
object2 = [{ 'b': 2 }],
|
||||
object3 = [{ 'a': 1, 'b': 2 }],
|
||||
circular1 = { 'a': 1 },
|
||||
circular2 = { 'a': 1 },
|
||||
lodash = context._;
|
||||
|
||||
circular1.b = circular1;
|
||||
circular2.b = circular2;
|
||||
|
||||
deepEqual(lodash.merge(object1, object2), object3, basename);
|
||||
deepEqual(lodash.sortBy([3, 2, 1], _.identity), array, basename);
|
||||
equal(lodash.isEqual(circular1, circular2), true, basename);
|
||||
|
||||
var actual = lodash.clone(circular1, true);
|
||||
ok(actual != circular1 && actual.b == actual, basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash build');
|
||||
|
||||
(function() {
|
||||
var commands = [
|
||||
'backbone',
|
||||
'csp',
|
||||
'legacy',
|
||||
'mobile',
|
||||
'strict',
|
||||
'underscore',
|
||||
'category=arrays',
|
||||
'category=chaining',
|
||||
'category=collections',
|
||||
'category=functions',
|
||||
'category=objects',
|
||||
'category=utilities',
|
||||
'exclude=union,uniq,zip',
|
||||
'include=each,filter,map',
|
||||
'include=once plus=bind,Chaining',
|
||||
'category=collections,functions',
|
||||
'underscore backbone',
|
||||
'backbone legacy category=utilities minus=first,last',
|
||||
'underscore include=debounce,throttle plus=after minus=throttle',
|
||||
'underscore mobile strict category=functions exports=amd,global plus=pick,uniq',
|
||||
]
|
||||
.concat(
|
||||
allMethods.map(function(methodName) {
|
||||
return 'include=' + methodName;
|
||||
})
|
||||
);
|
||||
|
||||
commands.forEach(function(command) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['--silent'].concat(command.split(' ')), function(source, filePath) {
|
||||
var methodNames,
|
||||
basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
// add method names explicitly
|
||||
if (/include/.test(command)) {
|
||||
methodNames = command.match(/include=(\S*)/)[1].split(/, */);
|
||||
}
|
||||
// add method names required by Backbone and Underscore builds
|
||||
if (/backbone/.test(command) && !methodNames) {
|
||||
methodNames = backboneDependencies.slice();
|
||||
}
|
||||
if (/underscore/.test(command) && !methodNames) {
|
||||
methodNames = underscoreMethods.slice();
|
||||
}
|
||||
// add method names explicitly by category
|
||||
if (/category/.test(command)) {
|
||||
// resolve method names belonging to each category (case-insensitive)
|
||||
methodNames = command.match(/category=(\S*)/)[1].split(/, */).reduce(function(result, category) {
|
||||
var capitalized = category[0].toUpperCase() + category.toLowerCase().slice(1);
|
||||
return result.concat(getMethodsByCategory(capitalized));
|
||||
}, methodNames || []);
|
||||
}
|
||||
// init `methodNames` if it hasn't been inited
|
||||
if (!methodNames) {
|
||||
methodNames = allMethods.slice();
|
||||
}
|
||||
if (/plus/.test(command)) {
|
||||
methodNames = methodNames.concat(command.match(/plus=(\S*)/)[1].split(/, */));
|
||||
}
|
||||
if (/minus/.test(command)) {
|
||||
methodNames = _.without.apply(_, [methodNames]
|
||||
.concat(expandMethodNames(command.match(/minus=(\S*)/)[1].split(/, */))));
|
||||
}
|
||||
if (/exclude/.test(command)) {
|
||||
methodNames = _.without.apply(_, [methodNames]
|
||||
.concat(expandMethodNames(command.match(/exclude=(\S*)/)[1].split(/, */))));
|
||||
}
|
||||
|
||||
// expand aliases and categories to real method names
|
||||
methodNames = expandMethodNames(methodNames).reduce(function(result, methodName) {
|
||||
return result.concat(methodName, getMethodsByCategory(methodName));
|
||||
}, []);
|
||||
|
||||
// remove nonexistent and duplicate method names
|
||||
methodNames = _.uniq(_.intersection(allMethods, expandMethodNames(methodNames)));
|
||||
|
||||
var lodash = context._ || {};
|
||||
methodNames.forEach(function(methodName) {
|
||||
testMethod(lodash, methodName, basename);
|
||||
});
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
}());
|
||||
|
||||
341
test/test.js
341
test/test.js
@@ -106,7 +106,7 @@
|
||||
|
||||
(function() {
|
||||
// ensure this test is executed before any other template tests to avoid false positives
|
||||
test('should initialize `reEvaluateDelimiter` correctly (test with production build)', function() {
|
||||
test('should initialize `reEvaluateDelimiter` (test with production build)', function() {
|
||||
var data = { 'a': [1, 2] },
|
||||
settings = _.templateSettings;
|
||||
|
||||
@@ -123,6 +123,14 @@
|
||||
}
|
||||
});
|
||||
|
||||
test('supports loading lodash.js with the Require.js "shim" configuration option', function() {
|
||||
if (window.document && window.require) {
|
||||
equal((shimmedModule || {}).moduleName, 'shimmed');
|
||||
} else {
|
||||
skipTest();
|
||||
}
|
||||
});
|
||||
|
||||
test('supports loading lodash.js as the "underscore" module', function() {
|
||||
if (window.document && window.require) {
|
||||
equal((underscoreModule || {}).moduleName, 'underscore');
|
||||
@@ -160,30 +168,13 @@
|
||||
QUnit.module('lodash.bind');
|
||||
|
||||
(function() {
|
||||
test('should correctly append array arguments to partially applied arguments (test in IE < 9)', function() {
|
||||
test('should append array arguments to partially applied arguments (test in IE < 9)', function() {
|
||||
var args,
|
||||
bound = _.bind(function() { args = slice.call(arguments); }, {}, 'a');
|
||||
|
||||
bound(['b'], 'c');
|
||||
deepEqual(args, ['a', ['b'], 'c']);
|
||||
});
|
||||
|
||||
test('supports lazy bind', function() {
|
||||
var object = {
|
||||
'name': 'moe',
|
||||
'greet': function(greeting) {
|
||||
return greeting + ': ' + this.name;
|
||||
}
|
||||
};
|
||||
|
||||
var func = _.bind(object, 'greet', 'hi');
|
||||
equal(func(), 'hi: moe');
|
||||
|
||||
object.greet = function(greeting) {
|
||||
return greeting + ' ' + this.name + '!';
|
||||
};
|
||||
equal(func(), 'hi moe!');
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -221,7 +212,7 @@
|
||||
objects['an array'].length = 5;
|
||||
|
||||
_.forOwn(objects, function(object, key) {
|
||||
test('should deep clone ' + key + ' correctly', function() {
|
||||
test('should deep clone ' + key, function() {
|
||||
var clone = _.clone(object, true);
|
||||
ok(_.isEqual(object, clone));
|
||||
|
||||
@@ -260,19 +251,6 @@
|
||||
ok(clone.bar.b === clone.foo.b && clone === clone.foo.b.foo.c && clone !== object);
|
||||
});
|
||||
|
||||
test('should clone using Klass#clone', function() {
|
||||
var object = new Klass;
|
||||
Klass.prototype.clone = function() { return new Klass; };
|
||||
|
||||
var clone = _.clone(object);
|
||||
ok(clone !== object && clone instanceof Klass);
|
||||
|
||||
clone = _.clone(object, true);
|
||||
ok(clone !== object && clone instanceof Klass);
|
||||
|
||||
delete Klass.prototype.clone;
|
||||
});
|
||||
|
||||
test('should clone problem JScript properties (test in IE < 9)', function() {
|
||||
deepEqual(_.clone(shadowed), shadowed);
|
||||
ok(_.clone(shadowed) != shadowed);
|
||||
@@ -341,7 +319,7 @@
|
||||
QUnit.module('lodash.difference');
|
||||
|
||||
(function() {
|
||||
test('should work correctly when using `cachedContains`', function() {
|
||||
test('should work when using `cachedContains`', function() {
|
||||
var array1 = _.range(27),
|
||||
array2 = array1.slice(),
|
||||
a = {},
|
||||
@@ -400,11 +378,12 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('strict mode checks');
|
||||
|
||||
_.each(['bindAll', 'defaults', 'extend'], function(methodName) {
|
||||
var func = _[methodName];
|
||||
QUnit.module('lodash.' + methodName + ' strict mode checks');
|
||||
|
||||
test('should not throw strict mode errors', function() {
|
||||
test('lodash.' + methodName + ' should not throw strict mode errors', function() {
|
||||
var object = { 'a': null, 'b': function(){} },
|
||||
pass = true;
|
||||
|
||||
@@ -488,18 +467,6 @@
|
||||
equal(_.forEach(collection, Boolean), collection);
|
||||
});
|
||||
|
||||
test('should treat array-like object with invalid `length` as a regular object', function() {
|
||||
var keys = [],
|
||||
object = { 'length': -1 };
|
||||
|
||||
_.forEach(object, function(value, key) { keys.push(key); });
|
||||
deepEqual(keys, ['length']);
|
||||
|
||||
keys = []; object.length = Math.pow(2, 32);
|
||||
_.forEach(object, function(value, key) { keys.push(key); });
|
||||
deepEqual(keys, ['length']);
|
||||
});
|
||||
|
||||
_.each({
|
||||
'literal': 'abc',
|
||||
'object': Object('abc')
|
||||
@@ -551,17 +518,18 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('object iteration bugs');
|
||||
|
||||
_.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
|
||||
var func = _[methodName];
|
||||
QUnit.module('lodash.' + methodName + ' iteration bugs');
|
||||
|
||||
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
|
||||
test('lodash.' + methodName + ' fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
|
||||
var keys = [];
|
||||
func(shadowed, function(value, key) { keys.push(key); });
|
||||
deepEqual(keys.sort(), shadowedKeys);
|
||||
});
|
||||
|
||||
test('skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
|
||||
test('lodash.' + methodName + ' skips the prototype property of functions (test in Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1)', function() {
|
||||
function Foo() {}
|
||||
Foo.prototype.a = 1;
|
||||
|
||||
@@ -578,11 +546,14 @@
|
||||
});
|
||||
});
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('exit early');
|
||||
|
||||
_.each(['forEach', 'forIn', 'forOwn'], function(methodName) {
|
||||
var func = _[methodName];
|
||||
QUnit.module('lodash.' + methodName + ' can exit early');
|
||||
|
||||
test('can exit early when iterating arrays', function() {
|
||||
test('lodash.' + methodName + ' can exit early when iterating arrays', function() {
|
||||
var array = [1, 2, 3],
|
||||
values = [];
|
||||
|
||||
@@ -590,7 +561,7 @@
|
||||
deepEqual(values, [1]);
|
||||
});
|
||||
|
||||
test('can exit early when iterating objects', function() {
|
||||
test('lodash.' + methodName + ' can exit early when iterating objects', function() {
|
||||
var object = { 'a': 1, 'b': 2, 'c': 3 },
|
||||
values = [];
|
||||
|
||||
@@ -675,6 +646,15 @@
|
||||
var array = [1, 2, 3];
|
||||
deepEqual(_.initial(array, 0), []);
|
||||
});
|
||||
|
||||
test('should allow a falsey `array` argument', function() {
|
||||
_.each(falsey, function(index, value) {
|
||||
try {
|
||||
var actual = index ? _.initial(value) : _.initial();
|
||||
} catch(e) { }
|
||||
deepEqual(actual, []);
|
||||
})
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -755,17 +735,6 @@
|
||||
equal(_.isEqual(args1, args3), false);
|
||||
});
|
||||
|
||||
test('should respect custom `isEqual` result despite objects strict equaling each other', function() {
|
||||
var object = { 'isEqual': function() { return false; } };
|
||||
equal(_.isEqual(object, object), false);
|
||||
});
|
||||
|
||||
test('should use custom `isEqual` methods on primitives', function() {
|
||||
Boolean.prototype.isEqual = function() { return true; };
|
||||
equal(_.isEqual(true, false), true);
|
||||
delete Boolean.prototype.isEqual;
|
||||
});
|
||||
|
||||
test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', function() {
|
||||
equal(_.isEqual(shadowed, {}), false);
|
||||
});
|
||||
@@ -827,6 +796,24 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.isPlainObject');
|
||||
|
||||
(function() {
|
||||
test('should detect plain objects', function() {
|
||||
function Foo(a) {
|
||||
this.a = 1;
|
||||
}
|
||||
|
||||
equal(_.isPlainObject(new Foo(1)), false);
|
||||
equal(_.isPlainObject([1, 2, 3]), false);
|
||||
equal(_.isPlainObject({ 'a': 1 }), true);
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('isType checks');
|
||||
|
||||
_.each([
|
||||
'isArguments',
|
||||
'isArray',
|
||||
@@ -846,9 +833,8 @@
|
||||
'isUndefined'
|
||||
], function(methodName) {
|
||||
var func = _[methodName];
|
||||
QUnit.module('lodash.' + methodName + ' result');
|
||||
|
||||
test('should return a boolean', function() {
|
||||
test('lodash.' + methodName + ' should return a boolean', function() {
|
||||
var expected = 'boolean';
|
||||
|
||||
equal(typeof func(arguments), expected);
|
||||
@@ -938,6 +924,42 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.lateBind');
|
||||
|
||||
(function() {
|
||||
test('should work when the target function is overwritten', function() {
|
||||
var object = {
|
||||
'name': 'moe',
|
||||
'greet': function(greeting) {
|
||||
return greeting + ': ' + this.name;
|
||||
}
|
||||
};
|
||||
|
||||
var func = _.lateBind(object, 'greet', 'hi');
|
||||
equal(func(), 'hi: moe');
|
||||
|
||||
object.greet = function(greeting) {
|
||||
return greeting + ' ' + this.name + '!';
|
||||
};
|
||||
equal(func(), 'hi moe!');
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.max and lodash.min object iteration');
|
||||
|
||||
_.each(['max', 'min'], function(methodName) {
|
||||
var func = _[methodName];
|
||||
|
||||
test('lodash.' + methodName + ' should iterate an object', function() {
|
||||
var actual = func({ 'a': 1, 'b': 2, 'c': 3 });
|
||||
equal(actual, methodName == 'max' ? 3 : 1);
|
||||
});
|
||||
});
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.merge');
|
||||
|
||||
(function() {
|
||||
@@ -982,7 +1004,6 @@
|
||||
source.bar.b = source.foo.b;
|
||||
|
||||
var actual = _.merge(object, source);
|
||||
|
||||
ok(actual.bar.b === actual.foo.b && actual.foo.b.foo.c === actual.foo.b.foo.c.foo.b.foo.c);
|
||||
});
|
||||
|
||||
@@ -1185,9 +1206,9 @@
|
||||
QUnit.module('lodash.random');
|
||||
|
||||
(function() {
|
||||
test('should work like `Math.random` if no arguments are passed', function() {
|
||||
test('should return `0` or `1` when no arguments are passed', function() {
|
||||
var actual = _.random();
|
||||
ok(actual >= 0 && actual < 1);
|
||||
ok(actual === 0 || actual === 1);
|
||||
});
|
||||
|
||||
test('supports not passing a `max` argument', function() {
|
||||
@@ -1270,22 +1291,6 @@
|
||||
deepEqual(args, expected);
|
||||
});
|
||||
|
||||
test('should treat array-like object with invalid `length` as a regular object', function() {
|
||||
var args,
|
||||
object = { 'a': 1, 'length': -1 },
|
||||
lastKey = _.keys(object).pop();
|
||||
|
||||
var expected = lastKey == 'length'
|
||||
? [-1, 1, 'a', object]
|
||||
: [1, -1, 'length', object];
|
||||
|
||||
_.reduceRight(object, function() {
|
||||
args || (args = slice.call(arguments));
|
||||
});
|
||||
|
||||
deepEqual(args, expected);
|
||||
});
|
||||
|
||||
_.each({
|
||||
'literal': 'abc',
|
||||
'object': Object('abc')
|
||||
@@ -1307,6 +1312,32 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.rest');
|
||||
|
||||
(function() {
|
||||
test('should allow a falsey `array` argument', function() {
|
||||
_.each(falsey, function(index, value) {
|
||||
try {
|
||||
var actual = index ? _.rest(value) : _.rest();
|
||||
} catch(e) { }
|
||||
deepEqual(actual, []);
|
||||
})
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.shuffle');
|
||||
|
||||
(function() {
|
||||
test('should shuffle an object', function() {
|
||||
var actual = _.shuffle({ 'a': 1, 'b': 2, 'c': 3 });
|
||||
deepEqual(actual.sort(), [1, 2, 3]);
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.size');
|
||||
|
||||
(function() {
|
||||
@@ -1508,7 +1539,7 @@
|
||||
ok(pass);
|
||||
});
|
||||
|
||||
test('should tokenize delimiters correctly', function() {
|
||||
test('should tokenize delimiters', function() {
|
||||
var compiled = _.template('<span class="icon-<%= type %>2"></span>');
|
||||
equal(compiled({ 'type': 1 }), '<span class="icon-12"></span>');
|
||||
});
|
||||
@@ -1517,6 +1548,13 @@
|
||||
var compiled = _.template('<%= value ? value : "b" %>');
|
||||
equal(compiled({ 'value': 'a' }), 'a');
|
||||
});
|
||||
|
||||
test('should parse delimiters with newlines', function() {
|
||||
var expected = '<<\nprint("<p>" + (value ? "yes" : "no") + "</p>")\n>>',
|
||||
compiled = _.template(expected, null, { 'evaluate': /<<(.+?)>>/g });
|
||||
|
||||
equal(compiled({ 'value': true }), expected);
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -1559,6 +1597,31 @@
|
||||
|
||||
throttled();
|
||||
});
|
||||
|
||||
asyncTest('should clear timeout when `func` is called', function() {
|
||||
var now = new Date,
|
||||
times = [];
|
||||
|
||||
var throttled = _.throttle(function() {
|
||||
times.push(new Date - now);
|
||||
}, 20);
|
||||
|
||||
setTimeout(throttled, 20);
|
||||
setTimeout(throttled, 20);
|
||||
setTimeout(throttled, 40);
|
||||
setTimeout(throttled, 40);
|
||||
|
||||
setTimeout(function() {
|
||||
var actual = _.every(times, function(value, index) {
|
||||
return index
|
||||
? (value - times[index - 1]) > 2
|
||||
: true;
|
||||
});
|
||||
|
||||
ok(actual);
|
||||
QUnit.start();
|
||||
}, 120);
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -1568,27 +1631,12 @@
|
||||
(function() {
|
||||
var args = arguments;
|
||||
|
||||
_.each({
|
||||
'an array': ['a', 'b', 'c'],
|
||||
'a string': Object('abc')
|
||||
}, function(collection, key) {
|
||||
test('should call custom `toArray` method of ' + key, function() {
|
||||
collection.toArray = function() { return [3, 2, 1]; };
|
||||
deepEqual(_.toArray(collection), [3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
test('should treat array-like objects like arrays', function() {
|
||||
var object = { '0': 'a', '1': 'b', '2': 'c', 'length': 3 };
|
||||
deepEqual(_.toArray(object), ['a', 'b', 'c']);
|
||||
deepEqual(_.toArray(args), [1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should treat array-like object with invalid `length` as a regular object', function() {
|
||||
var object = { 'length': -1 };
|
||||
deepEqual(_.toArray(object), [-1]);
|
||||
});
|
||||
|
||||
test('should work with a string for `collection` (test in Opera < 10.52)', function() {
|
||||
deepEqual(_.toArray('abc'), ['a', 'b', 'c']);
|
||||
deepEqual(_.toArray(Object('abc')), ['a', 'b', 'c']);
|
||||
@@ -1597,6 +1645,16 @@
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.times');
|
||||
|
||||
(function() {
|
||||
test('should return an array of the results of each `callback` execution', function() {
|
||||
deepEqual(_.times(3, function(n) { return n * 2; }), [0, 2, 4]);
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash.unescape');
|
||||
|
||||
(function() {
|
||||
@@ -1717,6 +1775,18 @@
|
||||
|
||||
(function() {
|
||||
test('should allow falsey arguments', function() {
|
||||
var returnArrays = [
|
||||
'filter',
|
||||
'invoke',
|
||||
'map',
|
||||
'pluck',
|
||||
'reject',
|
||||
'shuffle',
|
||||
'sortBy',
|
||||
'toArray',
|
||||
'where'
|
||||
];
|
||||
|
||||
var funcs = _.without.apply(_, [_.functions(_)].concat([
|
||||
'_',
|
||||
'_iteratorTemplate',
|
||||
@@ -1738,18 +1808,79 @@
|
||||
]));
|
||||
|
||||
_.each(funcs, function(methodName) {
|
||||
var func = _[methodName],
|
||||
var actual = [],
|
||||
expected = _.times(falsey.length, function() { return []; }),
|
||||
func = _[methodName],
|
||||
pass = true;
|
||||
|
||||
_.each(falsey, function(value, index) {
|
||||
try {
|
||||
index ? func(value) : func();
|
||||
actual.push(index ? func(value) : func());
|
||||
} catch(e) {
|
||||
pass = false;
|
||||
}
|
||||
});
|
||||
|
||||
ok(pass, methodName + ' allows falsey arguments');
|
||||
if (_.indexOf(returnArrays, methodName) > -1) {
|
||||
deepEqual(actual, expected, '_.' + methodName + ' returns an array');
|
||||
} else {
|
||||
skipTest(falsey.length);
|
||||
}
|
||||
ok(pass, '_.' + methodName + ' allows falsey arguments');
|
||||
});
|
||||
});
|
||||
|
||||
test('should handle `null` `thisArg` arguments', function() {
|
||||
var thisArg,
|
||||
array = ['a'],
|
||||
callback = function() { thisArg = this; },
|
||||
expected = (function() { return this; }).call(null);
|
||||
|
||||
var funcs = [
|
||||
'countBy',
|
||||
'every',
|
||||
'filter',
|
||||
'find',
|
||||
'forEach',
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'groupBy',
|
||||
'map',
|
||||
'max',
|
||||
'min',
|
||||
'omit',
|
||||
'pick',
|
||||
'reduce',
|
||||
'reduceRight',
|
||||
'reject',
|
||||
'some',
|
||||
'sortBy',
|
||||
'sortedIndex',
|
||||
'times',
|
||||
'uniq'
|
||||
];
|
||||
|
||||
_.each(funcs, function(methodName) {
|
||||
var func = _[methodName],
|
||||
message = '_.' + methodName + ' handles `null` `thisArg` arguments';
|
||||
|
||||
thisArg = undefined;
|
||||
|
||||
if (/^reduce/.test(methodName)) {
|
||||
func(array, callback, 0, null);
|
||||
} else if (methodName == 'sortedIndex') {
|
||||
func(array, 'a', callback, null);
|
||||
} else if (methodName == 'times') {
|
||||
func(1, callback, null);
|
||||
} else {
|
||||
func(array, callback, null);
|
||||
}
|
||||
|
||||
if (expected === null) {
|
||||
deepEqual(thisArg, null, message);
|
||||
} else {
|
||||
equal(thisArg, expected, message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
260
vendor/backbone/backbone.js
vendored
260
vendor/backbone/backbone.js
vendored
@@ -20,6 +20,7 @@
|
||||
|
||||
// Create a local reference to array methods.
|
||||
var ArrayProto = Array.prototype;
|
||||
var push = ArrayProto.push;
|
||||
var slice = ArrayProto.slice;
|
||||
var splice = ArrayProto.splice;
|
||||
|
||||
@@ -182,22 +183,22 @@
|
||||
// is automatically generated and assigned for you.
|
||||
var Model = Backbone.Model = function(attributes, options) {
|
||||
var defaults;
|
||||
attributes || (attributes = {});
|
||||
var attrs = attributes || {};
|
||||
if (options && options.collection) this.collection = options.collection;
|
||||
if (options && options.parse) attributes = this.parse(attributes);
|
||||
if (defaults = _.result(this, 'defaults')) {
|
||||
attributes = _.extend({}, defaults, attributes);
|
||||
attrs = _.extend({}, defaults, attrs);
|
||||
}
|
||||
this.attributes = {};
|
||||
this._escapedAttributes = {};
|
||||
this.cid = _.uniqueId('c');
|
||||
this.changed = {};
|
||||
this._silent = {};
|
||||
this._changes = {};
|
||||
this._pending = {};
|
||||
this.set(attributes, {silent: true});
|
||||
this.set(attrs, {silent: true});
|
||||
// Reset change tracking.
|
||||
this.changed = {};
|
||||
this._silent = {};
|
||||
this._changes = {};
|
||||
this._pending = {};
|
||||
this._previousAttributes = _.clone(this.attributes);
|
||||
this.initialize.apply(this, arguments);
|
||||
@@ -209,14 +210,18 @@
|
||||
// A hash of attributes whose current and previous value differ.
|
||||
changed: null,
|
||||
|
||||
// A hash of attributes that have silently changed since the last time
|
||||
// `change` was called. Will become pending attributes on the next call.
|
||||
_silent: null,
|
||||
// A hash of attributes that have changed since the last time `change`
|
||||
// was called.
|
||||
_changes: null,
|
||||
|
||||
// A hash of attributes that have changed since the last `'change'` event
|
||||
// A hash of attributes that have changed since the last `change` event
|
||||
// began.
|
||||
_pending: null,
|
||||
|
||||
// A hash of attributes with the current model state to determine if
|
||||
// a `change` should be recorded within a nested `change` block.
|
||||
_changing : null,
|
||||
|
||||
// The default name for the JSON `id` attribute is `"id"`. MongoDB and
|
||||
// CouchDB users may want to set this to `"_id"`.
|
||||
idAttribute: 'id',
|
||||
@@ -256,23 +261,22 @@
|
||||
|
||||
// Set a hash of model attributes on the object, firing `"change"` unless
|
||||
// you choose to silence it.
|
||||
set: function(key, value, options) {
|
||||
var attrs, attr, val;
|
||||
set: function(attrs, options) {
|
||||
var attr, key, val;
|
||||
if (attrs == null) return this;
|
||||
|
||||
// Handle both `"key", value` and `{key: value}` -style arguments.
|
||||
if (_.isObject(key) || key == null) {
|
||||
attrs = key;
|
||||
options = value;
|
||||
} else {
|
||||
attrs = {};
|
||||
attrs[key] = value;
|
||||
if (!_.isObject(attrs)) {
|
||||
key = attrs;
|
||||
(attrs = {})[key] = options;
|
||||
options = arguments[2];
|
||||
}
|
||||
|
||||
// Extract attributes and options.
|
||||
options || (options = {});
|
||||
if (!attrs) return this;
|
||||
var silent = options && options.silent;
|
||||
var unset = options && options.unset;
|
||||
if (attrs instanceof Model) attrs = attrs.attributes;
|
||||
if (options.unset) for (attr in attrs) attrs[attr] = void 0;
|
||||
if (unset) for (attr in attrs) attrs[attr] = void 0;
|
||||
|
||||
// Run validation.
|
||||
if (!this._validate(attrs, options)) return false;
|
||||
@@ -280,7 +284,7 @@
|
||||
// Check for changes of `id`.
|
||||
if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
|
||||
|
||||
var changes = options.changes = {};
|
||||
var changing = this._changing;
|
||||
var now = this.attributes;
|
||||
var escaped = this._escapedAttributes;
|
||||
var prev = this._previousAttributes || {};
|
||||
@@ -290,27 +294,30 @@
|
||||
val = attrs[attr];
|
||||
|
||||
// If the new and current value differ, record the change.
|
||||
if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) {
|
||||
if (!_.isEqual(now[attr], val) || (unset && _.has(now, attr))) {
|
||||
delete escaped[attr];
|
||||
(options.silent ? this._silent : changes)[attr] = true;
|
||||
this._changes[attr] = true;
|
||||
}
|
||||
|
||||
// Update or delete the current value.
|
||||
options.unset ? delete now[attr] : now[attr] = val;
|
||||
unset ? delete now[attr] : now[attr] = val;
|
||||
|
||||
// If the new and previous value differ, record the change. If not,
|
||||
// then remove changes for this attribute.
|
||||
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) !== _.has(prev, attr))) {
|
||||
this.changed[attr] = val;
|
||||
if (!options.silent) this._pending[attr] = true;
|
||||
if (!silent) this._pending[attr] = true;
|
||||
} else {
|
||||
delete this.changed[attr];
|
||||
delete this._pending[attr];
|
||||
if (!changing) delete this._changes[attr];
|
||||
}
|
||||
|
||||
if (changing && _.isEqual(now[attr], changing[attr])) delete this._changes[attr];
|
||||
}
|
||||
|
||||
// Fire the `"change"` events.
|
||||
if (!options.silent) this.change(options);
|
||||
if (!silent) this.change(options);
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -345,16 +352,14 @@
|
||||
// Set a hash of model attributes, and sync the model to the server.
|
||||
// If the server returns an attributes hash that differs, the model's
|
||||
// state will be `set` again.
|
||||
save: function(key, value, options) {
|
||||
var attrs, current, done;
|
||||
save: function(attrs, options) {
|
||||
var key, current, done;
|
||||
|
||||
// Handle both `("key", value)` and `({key: value})` -style calls.
|
||||
if (_.isObject(key) || key == null) {
|
||||
attrs = key;
|
||||
options = value;
|
||||
} else {
|
||||
attrs = {};
|
||||
attrs[key] = value;
|
||||
// Handle both `"key", value` and `{key: value}` -style arguments.
|
||||
if (attrs != null && !_.isObject(attrs)) {
|
||||
key = attrs;
|
||||
(attrs = {})[key] = options;
|
||||
options = arguments[2];
|
||||
}
|
||||
options = options ? _.clone(options) : {};
|
||||
|
||||
@@ -371,7 +376,7 @@
|
||||
}
|
||||
|
||||
// Do not persist invalid models.
|
||||
if (!attrs && !this.isValid()) return false;
|
||||
if (!attrs && !this._validate(null, options)) return false;
|
||||
|
||||
// After a successful server-side save, the client is (optionally)
|
||||
// updated with the server-side state.
|
||||
@@ -454,18 +459,25 @@
|
||||
// a `"change:attribute"` event for each changed attribute.
|
||||
// Calling this will cause all objects observing the model to update.
|
||||
change: function(options) {
|
||||
options || (options = {});
|
||||
var changing = this._changing;
|
||||
this._changing = true;
|
||||
var current = this._changing = {};
|
||||
|
||||
// Silent changes become pending changes.
|
||||
for (var attr in this._silent) this._pending[attr] = true;
|
||||
for (var attr in this._changes) this._pending[attr] = true;
|
||||
|
||||
// Silent changes are triggered.
|
||||
var changes = _.extend({}, options.changes, this._silent);
|
||||
this._silent = {};
|
||||
// Trigger 'change:attr' for any new or silent changes.
|
||||
var changes = this._changes;
|
||||
this._changes = {};
|
||||
|
||||
// Set the correct state for this._changing values
|
||||
var triggers = [];
|
||||
for (var attr in changes) {
|
||||
this.trigger('change:' + attr, this, this.get(attr), options);
|
||||
current[attr] = this.get(attr);
|
||||
triggers.push(attr);
|
||||
}
|
||||
|
||||
for (var i=0, l=triggers.length; i < l; i++) {
|
||||
this.trigger('change:' + triggers[i], this, current[triggers[i]], options);
|
||||
}
|
||||
if (changing) return this;
|
||||
|
||||
@@ -475,13 +487,13 @@
|
||||
this.trigger('change', this, options);
|
||||
// Pending and silent changes still remain.
|
||||
for (var attr in this.changed) {
|
||||
if (this._pending[attr] || this._silent[attr]) continue;
|
||||
if (this._pending[attr] || this._changes[attr]) continue;
|
||||
delete this.changed[attr];
|
||||
}
|
||||
this._previousAttributes = _.clone(this.attributes);
|
||||
}
|
||||
|
||||
this._changing = false;
|
||||
this._changing = null;
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -531,7 +543,7 @@
|
||||
// returning `true` if all is well. If a specific `error` callback has
|
||||
// been passed, call that instead of firing the general `"error"` event.
|
||||
_validate: function(attrs, options) {
|
||||
if (options.silent || !this.validate) return true;
|
||||
if (options && options.silent || !this.validate) return true;
|
||||
attrs = _.extend({}, this.attributes, attrs);
|
||||
var error = this.validate(attrs, options);
|
||||
if (!error) return true;
|
||||
@@ -585,59 +597,51 @@
|
||||
// Add a model, or list of models to the set. Pass **silent** to avoid
|
||||
// firing the `add` event for every new model.
|
||||
add: function(models, options) {
|
||||
var i, index, length, model, cid, id, cids = {}, ids = {}, dups = [];
|
||||
options || (options = {});
|
||||
var i, args, length, model, existing;
|
||||
var at = options && options.at;
|
||||
models = _.isArray(models) ? models.slice() : [models];
|
||||
|
||||
// Begin by turning bare objects into model references, and preventing
|
||||
// invalid models or duplicate models from being added.
|
||||
// invalid models from being added.
|
||||
for (i = 0, length = models.length; i < length; i++) {
|
||||
if (!(model = models[i] = this._prepareModel(models[i], options))) {
|
||||
throw new Error("Can't add an invalid model to a collection");
|
||||
}
|
||||
cid = model.cid;
|
||||
id = model.id;
|
||||
if (cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) {
|
||||
dups.push(i);
|
||||
if (models[i] = this._prepareModel(models[i], options)) continue;
|
||||
throw new Error("Can't add an invalid model to a collection");
|
||||
}
|
||||
|
||||
for (i = models.length - 1; i >= 0; i--) {
|
||||
model = models[i];
|
||||
existing = model.id != null && this._byId[model.id];
|
||||
|
||||
// If a duplicate is found, splice it out and optionally merge it into
|
||||
// the existing model.
|
||||
if (existing || this._byCid[model.cid]) {
|
||||
if (options && options.merge && existing) {
|
||||
existing.set(model, options);
|
||||
}
|
||||
models.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
cids[cid] = ids[id] = model;
|
||||
}
|
||||
|
||||
// Remove duplicates.
|
||||
i = dups.length;
|
||||
while (i--) {
|
||||
dups[i] = models.splice(dups[i], 1)[0];
|
||||
}
|
||||
|
||||
// Listen to added models' events, and index models for lookup by
|
||||
// `id` and by `cid`.
|
||||
for (i = 0, length = models.length; i < length; i++) {
|
||||
(model = models[i]).on('all', this._onModelEvent, this);
|
||||
// Listen to added models' events, and index models for lookup by
|
||||
// `id` and by `cid`.
|
||||
model.on('all', this._onModelEvent, this);
|
||||
this._byCid[model.cid] = model;
|
||||
if (model.id != null) this._byId[model.id] = model;
|
||||
}
|
||||
|
||||
// Insert models into the collection, re-sorting if needed, and triggering
|
||||
// `add` events unless silenced.
|
||||
this.length += length;
|
||||
index = options.at != null ? options.at : this.models.length;
|
||||
splice.apply(this.models, [index, 0].concat(models));
|
||||
|
||||
// Merge in duplicate models.
|
||||
if (options.merge) {
|
||||
for (i = 0, length = dups.length; i < length; i++) {
|
||||
if (model = this._byId[dups[i].id]) model.set(dups[i], options);
|
||||
}
|
||||
}
|
||||
// Update `length` and splice in new models.
|
||||
this.length += models.length;
|
||||
args = [at != null ? at : this.models.length, 0];
|
||||
push.apply(args, models);
|
||||
splice.apply(this.models, args);
|
||||
|
||||
// Sort the collection if appropriate.
|
||||
if (this.comparator && options.at == null) this.sort({silent: true});
|
||||
if (this.comparator && at == null) this.sort({silent: true});
|
||||
|
||||
if (options.silent) return this;
|
||||
for (i = 0, length = this.models.length; i < length; i++) {
|
||||
if (!cids[(model = this.models[i]).cid]) continue;
|
||||
options.index = i;
|
||||
if (options && options.silent) return this;
|
||||
|
||||
// Trigger `add` events.
|
||||
while (model = models.shift()) {
|
||||
model.trigger('add', model, this, options);
|
||||
}
|
||||
|
||||
@@ -731,35 +735,35 @@
|
||||
// normal circumstances, as the set will maintain sort order as each item
|
||||
// is added.
|
||||
sort: function(options) {
|
||||
options || (options = {});
|
||||
if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
|
||||
var boundComparator = _.bind(this.comparator, this);
|
||||
if (this.comparator.length === 1) {
|
||||
this.models = this.sortBy(boundComparator);
|
||||
} else {
|
||||
this.models.sort(boundComparator);
|
||||
if (!this.comparator) {
|
||||
throw new Error('Cannot sort a set without a comparator');
|
||||
}
|
||||
if (!options.silent) this.trigger('reset', this, options);
|
||||
|
||||
if (_.isString(this.comparator) || this.comparator.length === 1) {
|
||||
this.models = this.sortBy(this.comparator, this);
|
||||
} else {
|
||||
this.models.sort(_.bind(this.comparator, this));
|
||||
}
|
||||
|
||||
if (!options || !options.silent) this.trigger('reset', this, options);
|
||||
return this;
|
||||
},
|
||||
|
||||
// Pluck an attribute from each model in the collection.
|
||||
pluck: function(attr) {
|
||||
return _.map(this.models, function(model){ return model.get(attr); });
|
||||
return _.invoke(this.models, 'get', attr);
|
||||
},
|
||||
|
||||
// When you have more items than you want to add or remove individually,
|
||||
// you can reset the entire set with a new list of models, without firing
|
||||
// any `add` or `remove` events. Fires `reset` when finished.
|
||||
reset: function(models, options) {
|
||||
models || (models = []);
|
||||
options || (options = {});
|
||||
for (var i = 0, l = this.models.length; i < l; i++) {
|
||||
this._removeReference(this.models[i]);
|
||||
}
|
||||
this._reset();
|
||||
this.add(models, _.extend({silent: true}, options));
|
||||
if (!options.silent) this.trigger('reset', this, options);
|
||||
if (models) this.add(models, _.extend({silent: true}, options));
|
||||
if (!options || !options.silent) this.trigger('reset', this, options);
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -861,9 +865,9 @@
|
||||
var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
|
||||
'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
|
||||
'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
|
||||
'max', 'min', 'sortBy', 'sortedIndex', 'toArray', 'size', 'first', 'head',
|
||||
'take', 'initial', 'rest', 'tail', 'last', 'without', 'indexOf', 'shuffle',
|
||||
'lastIndexOf', 'isEmpty', 'groupBy'];
|
||||
'max', 'min', 'sortedIndex', 'toArray', 'size', 'first', 'head', 'take',
|
||||
'initial', 'rest', 'tail', 'last', 'without', 'indexOf', 'shuffle',
|
||||
'lastIndexOf', 'isEmpty'];
|
||||
|
||||
// Mix in each Underscore method as a proxy to `Collection#models`.
|
||||
_.each(methods, function(method) {
|
||||
@@ -874,6 +878,19 @@
|
||||
};
|
||||
});
|
||||
|
||||
// Underscore methods that take a property name as an argument.
|
||||
var attributeMethods = ['groupBy', 'countBy', 'sortBy'];
|
||||
|
||||
// Use attributes instead of properties.
|
||||
_.each(attributeMethods, function(method) {
|
||||
Collection.prototype[method] = function(value, context) {
|
||||
var iterator = _.isFunction(value) ? value : function(model) {
|
||||
return model.get(value);
|
||||
};
|
||||
return _[method](this.models, iterator, context);
|
||||
};
|
||||
});
|
||||
|
||||
// Backbone.Router
|
||||
// -------------------
|
||||
|
||||
@@ -888,9 +905,10 @@
|
||||
|
||||
// Cached regular expressions for matching named param parts and splatted
|
||||
// parts of route strings.
|
||||
var optionalParam = /\((.*?)\)/g;
|
||||
var namedParam = /:\w+/g;
|
||||
var splatParam = /\*\w+/g;
|
||||
var escapeRegExp = /[-[\]{}()+?.,\\^$|#\s]/g;
|
||||
var escapeRegExp = /[-{}[\]+?.,\\^$|#\s]/g;
|
||||
|
||||
// Set up all inheritable **Backbone.Router** properties and methods.
|
||||
_.extend(Router.prototype, Events, {
|
||||
@@ -920,6 +938,7 @@
|
||||
// Simple proxy to `Backbone.history` to save a fragment into the history.
|
||||
navigate: function(fragment, options) {
|
||||
Backbone.history.navigate(fragment, options);
|
||||
return this;
|
||||
},
|
||||
|
||||
// Bind all defined routes to `Backbone.history`. We have to reverse the
|
||||
@@ -940,6 +959,7 @@
|
||||
// against the current location hash.
|
||||
_routeToRegExp: function(route) {
|
||||
route = route.replace(escapeRegExp, '\\$&')
|
||||
.replace(optionalParam, '(?:$1)?')
|
||||
.replace(namedParam, '([^\/]+)')
|
||||
.replace(splatParam, '(.*?)');
|
||||
return new RegExp('^' + route + '$');
|
||||
@@ -958,11 +978,15 @@
|
||||
|
||||
// Handles cross-browser history management, based on URL fragments. If the
|
||||
// browser does not support `onhashchange`, falls back to polling.
|
||||
var History = Backbone.History = function(options) {
|
||||
var History = Backbone.History = function() {
|
||||
this.handlers = [];
|
||||
_.bindAll(this, 'checkUrl');
|
||||
this.location = options && options.location || root.location;
|
||||
this.history = options && options.history || root.history;
|
||||
|
||||
// #1653 - Ensure that `History` can be used outside of the browser.
|
||||
if (typeof window !== 'undefined') {
|
||||
this.location = window.location;
|
||||
this.history = window.history;
|
||||
}
|
||||
};
|
||||
|
||||
// Cached regex for cleaning leading hashes and slashes.
|
||||
@@ -1048,7 +1072,7 @@
|
||||
// opened by a non-pushState browser.
|
||||
this.fragment = fragment;
|
||||
var loc = this.location;
|
||||
var atRoot = (loc.pathname.replace(/[^/]$/, '$&/') === this.root) && !loc.search;
|
||||
var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;
|
||||
|
||||
// If we've started off with a route from a `pushState`-enabled browser,
|
||||
// but we're currently in a browser that doesn't support it...
|
||||
@@ -1062,7 +1086,7 @@
|
||||
// in a browser where it could be `pushState`-based instead...
|
||||
} else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
|
||||
this.fragment = this.getHash().replace(routeStripper, '');
|
||||
this.history.replaceState({}, document.title, this.root + this.fragment);
|
||||
this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
|
||||
}
|
||||
|
||||
if (!this.options.silent) return this.loadUrl();
|
||||
@@ -1121,7 +1145,7 @@
|
||||
fragment = this.getFragment(fragment || '');
|
||||
if (this.fragment === fragment) return;
|
||||
this.fragment = fragment;
|
||||
var url = (fragment.indexOf(this.root) !== 0 ? this.root : '') + fragment;
|
||||
var url = this.root + fragment;
|
||||
|
||||
// If pushState is available, we use it to set the fragment as a real URL.
|
||||
if (this._hasPushState) {
|
||||
@@ -1151,9 +1175,11 @@
|
||||
// a new one to the browser history.
|
||||
_updateHash: function(location, fragment, replace) {
|
||||
if (replace) {
|
||||
location.replace(location.href.replace(/(javascript:|#).*$/, '') + '#' + fragment);
|
||||
var href = location.href.replace(/(javascript:|#).*$/, '');
|
||||
location.replace(href + '#' + fragment);
|
||||
} else {
|
||||
location.hash = fragment;
|
||||
// #1649 - Some browsers require that `hash` contains a leading #.
|
||||
location.hash = '#' + fragment;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1208,8 +1234,8 @@
|
||||
// memory leaks.
|
||||
dispose: function() {
|
||||
this.undelegateEvents();
|
||||
if (this.model) this.model.off(null, null, this);
|
||||
if (this.collection) this.collection.off(null, null, this);
|
||||
if (this.model && this.model.off) this.model.off(null, null, this);
|
||||
if (this.collection && this.collection.off) this.collection.off(null, null, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -1307,7 +1333,7 @@
|
||||
if (this.className) attrs['class'] = _.result(this, 'className');
|
||||
this.setElement(this.make(_.result(this, 'tagName'), attrs), false);
|
||||
} else {
|
||||
this.setElement(this.el, false);
|
||||
this.setElement(_.result(this, 'el'), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1422,9 +1448,12 @@
|
||||
child = function(){ parent.apply(this, arguments); };
|
||||
}
|
||||
|
||||
// Add static properties to the constructor function, if supplied.
|
||||
_.extend(child, parent, staticProps);
|
||||
|
||||
// Set the prototype chain to inherit from `parent`, without calling
|
||||
// `parent`'s constructor function.
|
||||
function Surrogate(){ this.constructor = child; };
|
||||
var Surrogate = function(){ this.constructor = child; };
|
||||
Surrogate.prototype = parent.prototype;
|
||||
child.prototype = new Surrogate;
|
||||
|
||||
@@ -1432,9 +1461,6 @@
|
||||
// if supplied.
|
||||
if (protoProps) _.extend(child.prototype, protoProps);
|
||||
|
||||
// Add static properties to the constructor function, if supplied.
|
||||
_.extend(child, parent, staticProps);
|
||||
|
||||
// Set a convenience property in case the parent's prototype is needed
|
||||
// later.
|
||||
child.__super__ = parent.prototype;
|
||||
|
||||
79
vendor/backbone/test/collection.js
vendored
79
vendor/backbone/test/collection.js
vendored
@@ -34,6 +34,15 @@ $(document).ready(function() {
|
||||
equal(col.length, 4);
|
||||
});
|
||||
|
||||
test("String comparator.", 1, function() {
|
||||
var collection = new Backbone.Collection([
|
||||
{id: 3},
|
||||
{id: 1},
|
||||
{id: 2}
|
||||
], {comparator: 'id'});
|
||||
deepEqual(collection.pluck('id'), [1, 2, 3]);
|
||||
});
|
||||
|
||||
test("new and parse", 3, function() {
|
||||
var Collection = Backbone.Collection.extend({
|
||||
parse : function(data) {
|
||||
@@ -88,7 +97,7 @@ $(document).ready(function() {
|
||||
equal(col.pluck('label').join(' '), 'a b c d');
|
||||
});
|
||||
|
||||
test("add", 11, function() {
|
||||
test("add", 10, function() {
|
||||
var added, opts, secondAdded;
|
||||
added = opts = secondAdded = null;
|
||||
e = new Backbone.Model({id: 10, label : 'e'});
|
||||
@@ -98,7 +107,6 @@ $(document).ready(function() {
|
||||
});
|
||||
col.on('add', function(model, collection, options){
|
||||
added = model.get('label');
|
||||
equal(options.index, 4);
|
||||
opts = options;
|
||||
});
|
||||
col.add(e, {amazing: true});
|
||||
@@ -222,7 +230,7 @@ $(document).ready(function() {
|
||||
equal(col.indexOf(tom), 2);
|
||||
});
|
||||
|
||||
test("comparator that depends on `this`", 1, function() {
|
||||
test("comparator that depends on `this`", 2, function() {
|
||||
var col = new Backbone.Collection;
|
||||
col.negative = function(num) {
|
||||
return -num;
|
||||
@@ -231,7 +239,12 @@ $(document).ready(function() {
|
||||
return this.negative(a.id);
|
||||
};
|
||||
col.add([{id: 1}, {id: 2}, {id: 3}]);
|
||||
equal(col.pluck('id').join(' '), '3 2 1');
|
||||
deepEqual(col.pluck('id'), [3, 2, 1]);
|
||||
col.comparator = function(a, b) {
|
||||
return this.negative(b.id) - this.negative(a.id);
|
||||
};
|
||||
col.sort();
|
||||
deepEqual(col.pluck('id'), [1, 2, 3]);
|
||||
});
|
||||
|
||||
test("remove", 5, function() {
|
||||
@@ -549,23 +562,6 @@ $(document).ready(function() {
|
||||
});
|
||||
});
|
||||
|
||||
test("index with comparator", 4, function() {
|
||||
var counter = 0;
|
||||
var col = new Backbone.Collection([{id: 2}, {id: 4}], {
|
||||
comparator: function(model){ return model.id; }
|
||||
}).on('add', function(model, colleciton, options){
|
||||
if (model.id == 1) {
|
||||
equal(options.index, 0);
|
||||
equal(counter++, 0);
|
||||
}
|
||||
if (model.id == 3) {
|
||||
equal(options.index, 2);
|
||||
equal(counter++, 1);
|
||||
}
|
||||
});
|
||||
col.add([{id: 3}, {id: 1}]);
|
||||
});
|
||||
|
||||
test("throwing during add leaves consistent state", 4, function() {
|
||||
var col = new Backbone.Collection();
|
||||
col.on('test', function() { ok(false); });
|
||||
@@ -651,7 +647,7 @@ $(document).ready(function() {
|
||||
collection.create({id: 1});
|
||||
});
|
||||
|
||||
test("#1447 - create with wait adds model.", function() {
|
||||
test("#1447 - create with wait adds model.", 1, function() {
|
||||
var collection = new Backbone.Collection;
|
||||
var model = new Backbone.Model;
|
||||
model.sync = function(method, model, options){ options.success(); };
|
||||
@@ -659,7 +655,7 @@ $(document).ready(function() {
|
||||
collection.create(model, {wait: true});
|
||||
});
|
||||
|
||||
test("#1448 - add sorts collection after merge.", function() {
|
||||
test("#1448 - add sorts collection after merge.", 1, function() {
|
||||
var collection = new Backbone.Collection([
|
||||
{id: 1, x: 1},
|
||||
{id: 2, x: 2}
|
||||
@@ -668,4 +664,41 @@ $(document).ready(function() {
|
||||
collection.add({id: 1, x: 3}, {merge: true});
|
||||
deepEqual(collection.pluck('id'), [2, 1]);
|
||||
});
|
||||
|
||||
test("#1655 - groupBy can be used with a string argument.", 3, function() {
|
||||
var collection = new Backbone.Collection([{x: 1}, {x: 2}]);
|
||||
var grouped = collection.groupBy('x');
|
||||
strictEqual(_.keys(grouped).length, 2);
|
||||
strictEqual(grouped[1][0].get('x'), 1);
|
||||
strictEqual(grouped[2][0].get('x'), 2);
|
||||
});
|
||||
|
||||
test("#1655 - sortBy can be used with a string argument.", 1, function() {
|
||||
var collection = new Backbone.Collection([{x: 3}, {x: 1}, {x: 2}]);
|
||||
var values = _.map(collection.sortBy('x'), function(model) {
|
||||
return model.get('x');
|
||||
});
|
||||
deepEqual(values, [1, 2, 3]);
|
||||
});
|
||||
|
||||
test("#1604 - Removal during iteration.", 0, function() {
|
||||
var collection = new Backbone.Collection([{}, {}]);
|
||||
collection.on('add', function() {
|
||||
collection.at(0).destroy();
|
||||
});
|
||||
collection.add({}, {at: 0});
|
||||
});
|
||||
|
||||
test("#1638 - `sort` during `add` triggers correctly.", function() {
|
||||
var collection = new Backbone.Collection;
|
||||
collection.comparator = function(model) { return model.get('x'); };
|
||||
var added = [];
|
||||
collection.on('add', function(model) {
|
||||
model.set({x: 3});
|
||||
collection.sort();
|
||||
added.push(model.id);
|
||||
});
|
||||
collection.add([{id: 1, x: 1}, {id: 2, x: 2}]);
|
||||
deepEqual(added, [1, 2]);
|
||||
});
|
||||
});
|
||||
|
||||
66
vendor/backbone/test/model.js
vendored
66
vendor/backbone/test/model.js
vendored
@@ -740,9 +740,9 @@ $(document).ready(function() {
|
||||
model.set({b: 2}, {silent: true});
|
||||
});
|
||||
model.set({b: 0});
|
||||
deepEqual(changes, [0, 1, 1]);
|
||||
deepEqual(changes, [0, 1]);
|
||||
model.change();
|
||||
deepEqual(changes, [0, 1, 1, 2, 1]);
|
||||
deepEqual(changes, [0, 1, 2, 1]);
|
||||
});
|
||||
|
||||
test("nested set multiple times", 1, function() {
|
||||
@@ -816,4 +816,66 @@ $(document).ready(function() {
|
||||
strictEqual(model.save(), false);
|
||||
});
|
||||
|
||||
test("#1377 - Save without attrs triggers 'error'.", 1, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
url: '/test/',
|
||||
sync: function(method, model, options){ options.success(); },
|
||||
validate: function(){ return 'invalid'; }
|
||||
});
|
||||
var model = new Model({id: 1});
|
||||
model.on('error', function(){ ok(true); });
|
||||
model.save();
|
||||
});
|
||||
|
||||
test("#1545 - `undefined` can be passed to a model constructor without coersion", function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
defaults: { one: 1 },
|
||||
initialize : function(attrs, opts) {
|
||||
equal(attrs, undefined);
|
||||
}
|
||||
});
|
||||
var emptyattrs = new Model();
|
||||
var undefinedattrs = new Model(undefined);
|
||||
});
|
||||
|
||||
asyncTest("#1478 - Model `save` does not trigger change on unchanged attributes", 0, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
sync: function(method, model, options) {
|
||||
setTimeout(function(){
|
||||
options.success();
|
||||
start();
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
new Model({x: true})
|
||||
.on('change:x', function(){ ok(false); })
|
||||
.save(null, {wait: true});
|
||||
});
|
||||
|
||||
test("#1664 - Changing from one value, silently to another, back to original does not trigger change.", 0, function() {
|
||||
var model = new Backbone.Model({x:1});
|
||||
model.on('change:x', function() { ok(false); });
|
||||
model.set({x:2},{silent:true});
|
||||
model.set({x:3},{silent:true});
|
||||
model.set({x:1});
|
||||
});
|
||||
|
||||
test("#1664 - multiple silent changes nested inside a change event", 2, function() {
|
||||
var changes = [];
|
||||
var model = new Backbone.Model();
|
||||
model.on('change', function() {
|
||||
model.set({a:'c'}, {silent:true});
|
||||
model.set({b:2}, {silent:true});
|
||||
model.unset('c', {silent:true});
|
||||
model.set({a:'a'}, {silent:true});
|
||||
model.set({b:1}, {silent:true});
|
||||
model.set({c:'item'}, {silent:true});
|
||||
});
|
||||
model.on('change:a change:b change:c', function(model, val) { changes.push(val); });
|
||||
model.set({a:'a', b:1, c:'item'});
|
||||
deepEqual(changes, ['a',1,'item']);
|
||||
model.change();
|
||||
deepEqual(changes, ['a',1,'item']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
62
vendor/backbone/test/router.js
vendored
62
vendor/backbone/test/router.js
vendored
@@ -41,7 +41,7 @@ $(document).ready(function() {
|
||||
|
||||
setup: function() {
|
||||
location = new Location('http://example.com');
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
router = new Router({testing: 101});
|
||||
Backbone.history.interval = 9;
|
||||
Backbone.history.start({pushState: false});
|
||||
@@ -69,6 +69,7 @@ $(document).ready(function() {
|
||||
"contacts": "contacts",
|
||||
"contacts/new": "newContact",
|
||||
"contacts/:id": "loadContact",
|
||||
"optional(/:item)": "optionalItem",
|
||||
"splat/*args/end": "splat",
|
||||
"*first/complex-:part/*rest": "complex",
|
||||
":entity?*args": "query",
|
||||
@@ -105,6 +106,10 @@ $(document).ready(function() {
|
||||
this.contact = 'load';
|
||||
},
|
||||
|
||||
optionalItem: function(arg){
|
||||
this.arg = arg !== undefined ? arg : null;
|
||||
},
|
||||
|
||||
splat : function(args) {
|
||||
this.args = args;
|
||||
},
|
||||
@@ -199,6 +204,15 @@ $(document).ready(function() {
|
||||
equal(router.args, 'long-list/of/splatted_99args');
|
||||
});
|
||||
|
||||
test("routes (optional)", 2, function() {
|
||||
location.replace('http://example.com#optional');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.arg, null);
|
||||
location.replace('http://example.com#optional/thing');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.arg, 'thing');
|
||||
});
|
||||
|
||||
test("routes (complex)", 3, function() {
|
||||
location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven');
|
||||
Backbone.history.checkUrl();
|
||||
@@ -233,12 +247,12 @@ $(document).ready(function() {
|
||||
location.replace('http://example.com/root/foo');
|
||||
|
||||
Backbone.history.stop();
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({root: '/root', hashChange: false, silent: true});
|
||||
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||
|
||||
Backbone.history.stop();
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({root: '/root/', hashChange: false, silent: true});
|
||||
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||
});
|
||||
@@ -272,7 +286,7 @@ $(document).ready(function() {
|
||||
test("#1185 - Use pathname when hashChange is not wanted.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/path/name#hash');
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({hashChange: false});
|
||||
var fragment = Backbone.history.getFragment();
|
||||
strictEqual(fragment, location.pathname.replace(/^\//, ''));
|
||||
@@ -281,7 +295,7 @@ $(document).ready(function() {
|
||||
test("#1206 - Strip leading slash before location.assign.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root/');
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({hashChange: false, root: '/root/'});
|
||||
location.assign = function(pathname) {
|
||||
strictEqual(pathname, '/root/fragment');
|
||||
@@ -292,7 +306,7 @@ $(document).ready(function() {
|
||||
test("#1387 - Root fragment without trailing slash.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root');
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({hashChange: false, root: '/root/', silent: true});
|
||||
strictEqual(Backbone.history.getFragment(), '');
|
||||
});
|
||||
@@ -300,7 +314,7 @@ $(document).ready(function() {
|
||||
test("#1366 - History does not prepend root to fragment.", 2, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root/');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(state, title, url) {
|
||||
@@ -320,7 +334,7 @@ $(document).ready(function() {
|
||||
test("Normalize root.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(state, title, url) {
|
||||
@@ -339,7 +353,7 @@ $(document).ready(function() {
|
||||
test("Normalize root.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root#fragment');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(state, title, url) {},
|
||||
@@ -357,7 +371,7 @@ $(document).ready(function() {
|
||||
test("Normalize root.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root');
|
||||
Backbone.history = new Backbone.History({location: location});
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.loadUrl = function() { ok(true); };
|
||||
Backbone.history.start({
|
||||
pushState: true,
|
||||
@@ -368,7 +382,7 @@ $(document).ready(function() {
|
||||
test("Normalize root - leading slash.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(){},
|
||||
@@ -382,7 +396,7 @@ $(document).ready(function() {
|
||||
test("Transition from hashChange to pushState.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root#x/y');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(){},
|
||||
@@ -400,7 +414,7 @@ $(document).ready(function() {
|
||||
test("#1619: Router: Normalize empty root", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(){},
|
||||
@@ -414,7 +428,7 @@ $(document).ready(function() {
|
||||
test("#1619: Router: nagivate with empty root", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/');
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(state, title, url) {
|
||||
@@ -436,7 +450,7 @@ $(document).ready(function() {
|
||||
location.replace = function(url) {
|
||||
strictEqual(url, '/root/?a=b#x/y');
|
||||
};
|
||||
Backbone.history = new Backbone.History({
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: null,
|
||||
@@ -449,4 +463,22 @@ $(document).ready(function() {
|
||||
});
|
||||
});
|
||||
|
||||
test("#1695 - hashChange to pushState with search.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root?a=b#x/y');
|
||||
Backbone.history = _.extend(new Backbone.History, {
|
||||
location: location,
|
||||
history: {
|
||||
pushState: function(){},
|
||||
replaceState: function(state, title, url){
|
||||
strictEqual(url, '/root/x/y?a=b');
|
||||
}
|
||||
}
|
||||
});
|
||||
Backbone.history.start({
|
||||
root: 'root',
|
||||
pushState: true
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
16
vendor/backbone/test/view.js
vendored
16
vendor/backbone/test/view.js
vendored
@@ -305,6 +305,11 @@ $(document).ready(function() {
|
||||
view.$el.click();
|
||||
});
|
||||
|
||||
test("dispose with non Backbone objects", 0, function() {
|
||||
var view = new Backbone.View({model: {}, collection: {}});
|
||||
view.dispose();
|
||||
});
|
||||
|
||||
test("view#remove calls dispose.", 1, function() {
|
||||
var view = new Backbone.View();
|
||||
|
||||
@@ -312,4 +317,15 @@ $(document).ready(function() {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
test("Provide function for el.", 1, function() {
|
||||
var View = Backbone.View.extend({
|
||||
el: function() {
|
||||
return "<p><a></a></p>";
|
||||
}
|
||||
});
|
||||
|
||||
var view = new View;
|
||||
ok(view.$el.is('p:has(a)'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
1
vendor/benchmark.js/README.md
vendored
1
vendor/benchmark.js/README.md
vendored
@@ -1,4 +1,5 @@
|
||||
# Benchmark.js <sup>v1.0.0</sup>
|
||||
[](http://travis-ci.org/bestiejs/benchmark.js)
|
||||
|
||||
A [robust](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/ "Bulletproof JavaScript benchmarks") benchmarking library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>, supports high-resolution timers, and returns statistically significant results. As seen on [jsPerf](http://jsperf.com/).
|
||||
|
||||
|
||||
2
vendor/docdown/docdown.php
vendored
2
vendor/docdown/docdown.php
vendored
@@ -8,7 +8,7 @@ require(dirname(__FILE__) . '/src/DocDown/Generator.php');
|
||||
|
||||
/**
|
||||
* Generates Markdown from JSDoc entries in a given file.
|
||||
*
|
||||
*
|
||||
* @param {Array} [$options=array()] The options array.
|
||||
* @returns {String} The generated Markdown.
|
||||
* @example
|
||||
|
||||
13
vendor/docdown/src/DocDown/Alias.php
vendored
13
vendor/docdown/src/DocDown/Alias.php
vendored
@@ -22,10 +22,11 @@ class Alias {
|
||||
* @param {String} $name The alias name.
|
||||
* @param {Object} $owner The alias owner.
|
||||
*/
|
||||
public function __construct($name, $owner) {
|
||||
public function __construct( $name, $owner ) {
|
||||
$this->owner = $owner;
|
||||
$this->_name = $name;
|
||||
$this->_call = $owner->getCall();
|
||||
$this->_category = $owner->getCategory();
|
||||
$this->_desc = $owner->getDesc();
|
||||
$this->_example = $owner->getExample();
|
||||
$this->_lineNumber = $owner->getLineNumber();
|
||||
@@ -65,6 +66,16 @@ class Alias {
|
||||
return $this->_call;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the owner entry's `category` data.
|
||||
*
|
||||
* @memberOf Alias
|
||||
* @returns {String} The owner entry's `category` data.
|
||||
*/
|
||||
public function getCategory() {
|
||||
return $this->_category;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the owner entry's description.
|
||||
*
|
||||
|
||||
21
vendor/docdown/src/DocDown/Entry.php
vendored
21
vendor/docdown/src/DocDown/Entry.php
vendored
@@ -152,6 +152,27 @@ class Entry {
|
||||
return $this->_call;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the entry's `category` data.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {String} The entry's `category` data.
|
||||
*/
|
||||
public function getCategory() {
|
||||
if (isset($this->_category)) {
|
||||
return $this->_category;
|
||||
}
|
||||
|
||||
preg_match('#\* *@category\s+([^\n]+)#', $this->entry, $result);
|
||||
if (count($result)) {
|
||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||
} else {
|
||||
$result = $this->getType() == 'Function' ? 'Methods' : 'Properties';
|
||||
}
|
||||
$this->_category = $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the entry's description.
|
||||
*
|
||||
|
||||
348
vendor/docdown/src/DocDown/Generator.php
vendored
348
vendor/docdown/src/DocDown/Generator.php
vendored
@@ -7,6 +7,15 @@ require(dirname(__FILE__) . "/Entry.php");
|
||||
*/
|
||||
class Generator {
|
||||
|
||||
/**
|
||||
* The HTML for the close tag.
|
||||
*
|
||||
* @static
|
||||
* @memberOf Generator
|
||||
* @type String
|
||||
*/
|
||||
public $closeTag = "\n<!-- /div -->\n";
|
||||
|
||||
/**
|
||||
* An array of JSDoc entries.
|
||||
*
|
||||
@@ -15,6 +24,15 @@ class Generator {
|
||||
*/
|
||||
public $entries = array();
|
||||
|
||||
/**
|
||||
* The HTML for the open tag.
|
||||
*
|
||||
* @static
|
||||
* @memberOf Generator
|
||||
* @type String
|
||||
*/
|
||||
public $openTag = "\n<!-- div -->\n";
|
||||
|
||||
/**
|
||||
* An options array used to configure the generator.
|
||||
*
|
||||
@@ -24,7 +42,7 @@ class Generator {
|
||||
public $options = array();
|
||||
|
||||
/**
|
||||
* The entire file's source code.
|
||||
* The file's source code.
|
||||
*
|
||||
* @memberOf Generator
|
||||
* @type String
|
||||
@@ -65,6 +83,9 @@ class Generator {
|
||||
if (!isset($options['lang'])) {
|
||||
$options['lang'] = 'js';
|
||||
}
|
||||
if (!isset($options['toc'])) {
|
||||
$options['toc'] = 'properties';
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->source = str_replace(PHP_EOL, "\n", $options['source']);
|
||||
@@ -86,7 +107,7 @@ class Generator {
|
||||
* @param {String} $string The string to format.
|
||||
* @returns {String} The formatted string.
|
||||
*/
|
||||
private static function format($string) {
|
||||
private static function format( $string ) {
|
||||
$counter = 0;
|
||||
|
||||
// tokenize inline code snippets
|
||||
@@ -121,7 +142,7 @@ class Generator {
|
||||
* @param {Array|Object} $object The template object.
|
||||
* @returns {String} The modified string.
|
||||
*/
|
||||
private static function interpolate($string, $object) {
|
||||
private static function interpolate( $string, $object ) {
|
||||
preg_match_all('/#\{([^}]+)\}/', $string, $tokens);
|
||||
$tokens = array_unique(array_pop($tokens));
|
||||
|
||||
@@ -149,6 +170,63 @@ class Generator {
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Adds the given `$entries` to the `$result` array.
|
||||
*
|
||||
* @private
|
||||
* @memberOf Generator
|
||||
* @param {Array} $result The result array to modify.
|
||||
* @param {Array} $entries The entries to add to the `$result`.
|
||||
*/
|
||||
private function addEntries( &$result, $entries ) {
|
||||
foreach ($entries as $entry) {
|
||||
// skip aliases
|
||||
if ($entry->isAlias()) {
|
||||
continue;
|
||||
}
|
||||
// name and description
|
||||
array_push(
|
||||
$result,
|
||||
$this->openTag,
|
||||
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [Ⓢ](#{href} \"View in source\") [Ⓣ][1]\n\n#{desc}", $entry)
|
||||
);
|
||||
|
||||
// @alias
|
||||
if (count($aliases = $entry->getAliases())) {
|
||||
array_push($result, '', '#### Aliases');
|
||||
foreach ($aliases as $index => $alias) {
|
||||
$aliases[$index] = $alias->getName();
|
||||
}
|
||||
$result[] = '*' . implode(', ', $aliases) . '*';
|
||||
}
|
||||
// @param
|
||||
if (count($params = $entry->getParams())) {
|
||||
array_push($result, '', '#### Arguments');
|
||||
foreach ($params as $index => $param) {
|
||||
$result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
|
||||
'desc' => $param[2],
|
||||
'name' => $param[1],
|
||||
'num' => $index + 1,
|
||||
'type' => $param[0]
|
||||
));
|
||||
}
|
||||
}
|
||||
// @returns
|
||||
if (count($returns = $entry->getReturns())) {
|
||||
array_push(
|
||||
$result, '',
|
||||
'#### Returns',
|
||||
Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0]))
|
||||
);
|
||||
}
|
||||
// @example
|
||||
if ($example = $entry->getExample()) {
|
||||
array_push($result, '', '#### Example', $example);
|
||||
}
|
||||
array_push($result, "\n* * *", $this->closeTag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the entry's hash used to navigate the documentation.
|
||||
*
|
||||
@@ -204,9 +282,11 @@ class Generator {
|
||||
*/
|
||||
public function generate() {
|
||||
$api = array();
|
||||
$byCategory = $this->options['toc'] == 'categories';
|
||||
$categories = array();
|
||||
$closeTag = $this->closeTag;
|
||||
$compiling = false;
|
||||
$openTag = "\n<!-- div -->\n";
|
||||
$closeTag = "\n<!-- /div -->\n";
|
||||
$openTag = $this->openTag;
|
||||
$result = array('# ' . $this->options['title']);
|
||||
$toc = 'toc';
|
||||
|
||||
@@ -223,14 +303,14 @@ class Generator {
|
||||
|
||||
foreach ($members as $member) {
|
||||
// create api category arrays
|
||||
if (!isset($api[$member]) && $member) {
|
||||
if ($member && !isset($api[$member])) {
|
||||
// create temporary entry to be replaced later
|
||||
$api[$member] = new Entry('', '', $entry->lang);
|
||||
$api[$member] = new stdClass;
|
||||
$api[$member]->static = array();
|
||||
$api[$member]->plugin = array();
|
||||
}
|
||||
|
||||
// append entry to api category
|
||||
// append entry to api member
|
||||
if (!$member || $entry->isCtor() || ($entry->getType() == 'Object' &&
|
||||
!preg_match('/[=:]\s*(?:null|undefined)\s*[,;]?$/', $entry->entry))) {
|
||||
|
||||
@@ -261,6 +341,26 @@ class Generator {
|
||||
}
|
||||
}
|
||||
|
||||
// add properties to each entry
|
||||
foreach ($api as $entry) {
|
||||
$entry->hash = $this->getHash($entry);
|
||||
$entry->href = $this->getLineUrl($entry);
|
||||
|
||||
$member = $entry->getMembers(0);
|
||||
$member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
|
||||
$entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
|
||||
|
||||
// add properties to static and plugin sub-entries
|
||||
foreach (array('static', 'plugin') as $kind) {
|
||||
foreach ($entry->{$kind} as $subentry) {
|
||||
$subentry->hash = $this->getHash($subentry);
|
||||
$subentry->href = $this->getLineUrl($subentry);
|
||||
$subentry->member = $member;
|
||||
$subentry->separator = $this->getSeparator($subentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
// custom sort for root level entries
|
||||
@@ -268,19 +368,19 @@ class Generator {
|
||||
function sortCompare($a, $b) {
|
||||
$score = array( 'a' => 0, 'b' => 0);
|
||||
foreach (array( 'a' => $a, 'b' => $b) as $key => $value) {
|
||||
// capitalized keys that represent constructor properties are last
|
||||
// capitalized properties are last
|
||||
if (preg_match('/[#.][A-Z]/', $value)) {
|
||||
$score[$key] = 0;
|
||||
}
|
||||
// lowercase keys with prototype properties are next to last
|
||||
// lowercase prototype properties are next to last
|
||||
else if (preg_match('/#[a-z]/', $value)) {
|
||||
$score[$key] = 1;
|
||||
}
|
||||
// lowercase keys with static properties next to first
|
||||
// lowercase static properties next to first
|
||||
else if (preg_match('/\.[a-z]/', $value)) {
|
||||
$score[$key] = 2;
|
||||
}
|
||||
// lowercase keys with no properties are first
|
||||
// root properties are first
|
||||
else if (preg_match('/^[^#.]+$/', $value)) {
|
||||
$score[$key] = 3;
|
||||
}
|
||||
@@ -310,48 +410,90 @@ class Generator {
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
// add categories
|
||||
foreach ($api as $entry) {
|
||||
$categories[$entry->getCategory()][] = $entry;
|
||||
foreach (array('static', 'plugin') as $kind) {
|
||||
foreach ($entry->{$kind} as $subentry) {
|
||||
$categories[$subentry->getCategory()][] = $subentry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort categories
|
||||
ksort($categories);
|
||||
|
||||
foreach(array('Methods', 'Properties') as $category) {
|
||||
if (isset($categories[$category])) {
|
||||
$entries = $categories[$category];
|
||||
unset($categories[$category]);
|
||||
$categories[$category] = $entries;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
// compile TOC
|
||||
$result[] = $openTag;
|
||||
|
||||
foreach ($api as $key => $entry) {
|
||||
$entry->hash = $this->getHash($entry);
|
||||
$entry->href = $this->getLineUrl($entry);
|
||||
|
||||
$member = $entry->getMembers(0);
|
||||
$member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
|
||||
|
||||
$entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
|
||||
|
||||
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
||||
|
||||
// assign TOC hash
|
||||
if (count($result) == 2) {
|
||||
$toc = $member;
|
||||
}
|
||||
|
||||
// add root entry
|
||||
array_push(
|
||||
$result,
|
||||
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`',
|
||||
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
||||
);
|
||||
|
||||
// add static and plugin sub-entries
|
||||
foreach (array('static', 'plugin') as $kind) {
|
||||
if ($kind == 'plugin' && count($entry->plugin)) {
|
||||
array_push(
|
||||
$result,
|
||||
$closeTag,
|
||||
$openTag,
|
||||
'## `' . $member . ($entry->isCtor() ? '.prototype`' : '`')
|
||||
);
|
||||
// compile TOC by categories
|
||||
if ($byCategory) {
|
||||
foreach ($categories as $category => $entries) {
|
||||
if ($compiling) {
|
||||
$result[] = $closeTag;
|
||||
} else {
|
||||
$compiling = true;
|
||||
}
|
||||
foreach ($entry->{$kind} as $subentry) {
|
||||
$subentry->hash = $this->getHash($subentry);
|
||||
$subentry->href = $this->getLineUrl($subentry);
|
||||
$subentry->member = $member;
|
||||
$subentry->separator = $this->getSeparator($subentry);
|
||||
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
|
||||
// assign TOC hash
|
||||
if (count($result) == 2) {
|
||||
$toc = $category;
|
||||
}
|
||||
// add category
|
||||
array_push(
|
||||
$result,
|
||||
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $category . '`'
|
||||
);
|
||||
// add entries
|
||||
foreach ($entries as $entry) {
|
||||
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
// compile TOC by namespace
|
||||
else {
|
||||
foreach ($api as $entry) {
|
||||
if ($compiling) {
|
||||
$result[] = $closeTag;
|
||||
} else {
|
||||
$compiling = true;
|
||||
}
|
||||
$member = $entry->member . $entry->getName();
|
||||
|
||||
// assign TOC hash
|
||||
if (count($result) == 2) {
|
||||
$toc = $member;
|
||||
}
|
||||
// add root entry
|
||||
array_push(
|
||||
$result,
|
||||
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`',
|
||||
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
||||
);
|
||||
|
||||
// add static and plugin sub-entries
|
||||
foreach (array('static', 'plugin') as $kind) {
|
||||
if ($kind == 'plugin' && count($entry->plugin)) {
|
||||
array_push(
|
||||
$result,
|
||||
$closeTag,
|
||||
$openTag,
|
||||
'## `' . $member . ($entry->isCtor() ? '.prototype`' : '`')
|
||||
);
|
||||
}
|
||||
foreach ($entry->{$kind} as $subentry) {
|
||||
$subentry->member = $member;
|
||||
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,81 +506,51 @@ class Generator {
|
||||
$compiling = false;
|
||||
$result[] = $openTag;
|
||||
|
||||
foreach ($api as $entry) {
|
||||
// skip aliases
|
||||
if ($entry->isAlias()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add root entry
|
||||
$member = $entry->member . $entry->getName();
|
||||
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
||||
|
||||
array_push($result, $openTag, '## `' . $member . '`');
|
||||
|
||||
foreach (array($entry, 'static', 'plugin') as $kind) {
|
||||
$subentries = is_string($kind) ? $entry->{$kind} : array($kind);
|
||||
|
||||
// title
|
||||
if ($kind != 'static' && $entry->getType() != 'Object' &&
|
||||
count($subentries) && $subentries[0] != $kind) {
|
||||
if ($kind == 'plugin') {
|
||||
$result[] = $closeTag;
|
||||
}
|
||||
array_push(
|
||||
$result,
|
||||
$openTag,
|
||||
'## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`')
|
||||
);
|
||||
if ($byCategory) {
|
||||
foreach ($categories as $category => $entries) {
|
||||
if ($compiling) {
|
||||
$result[] = $closeTag;
|
||||
} else {
|
||||
$compiling = true;
|
||||
}
|
||||
if ($category != 'Methods' && $category != 'Properties') {
|
||||
$category = '“' . $category . '” Methods';
|
||||
}
|
||||
array_push($result, $openTag, '## `' . $category . '`');
|
||||
$this->addEntries($result, $entries);
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach ($api as $entry) {
|
||||
// skip aliases
|
||||
if ($entry->isAlias()) {
|
||||
continue;
|
||||
}
|
||||
if ($compiling) {
|
||||
$result[] = $closeTag;
|
||||
} else {
|
||||
$compiling = true;
|
||||
}
|
||||
// add root entry name
|
||||
$member = $entry->member . $entry->getName();
|
||||
array_push($result, $openTag, '## `' . $member . '`');
|
||||
|
||||
// body
|
||||
foreach ($subentries as $subentry) {
|
||||
// skip aliases
|
||||
if ($subentry->isAlias()) {
|
||||
continue;
|
||||
}
|
||||
foreach (array($entry, 'static', 'plugin') as $kind) {
|
||||
$subentries = is_string($kind) ? $entry->{$kind} : array($kind);
|
||||
|
||||
// description
|
||||
array_push(
|
||||
$result,
|
||||
$openTag,
|
||||
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [Ⓢ](#{href} \"View in source\") [Ⓣ][1]\n\n#{desc}", $subentry)
|
||||
);
|
||||
|
||||
// @alias
|
||||
if (count($aliases = $subentry->getAliases())) {
|
||||
array_push($result, '', '#### Aliases');
|
||||
foreach ($aliases as $index => $alias) {
|
||||
$aliases[$index] = $alias->getName();
|
||||
// add sub-entry name
|
||||
if ($kind != 'static' && $entry->getType() != 'Object' &&
|
||||
count($subentries) && $subentries[0] != $kind) {
|
||||
if ($kind == 'plugin') {
|
||||
$result[] = $closeTag;
|
||||
}
|
||||
$result[] = '*' . implode(', ', $aliases) . '*';
|
||||
}
|
||||
// @param
|
||||
if (count($params = $subentry->getParams())) {
|
||||
array_push($result, '', '#### Arguments');
|
||||
foreach ($params as $index => $param) {
|
||||
$result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
|
||||
'desc' => $param[2],
|
||||
'name' => $param[1],
|
||||
'num' => $index + 1,
|
||||
'type' => $param[0]
|
||||
));
|
||||
}
|
||||
}
|
||||
// @returns
|
||||
if (count($returns = $subentry->getReturns())) {
|
||||
array_push(
|
||||
$result, '',
|
||||
'#### Returns',
|
||||
Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0]))
|
||||
$result,
|
||||
$openTag,
|
||||
'## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`')
|
||||
);
|
||||
}
|
||||
// @example
|
||||
if ($example = $subentry->getExample()) {
|
||||
array_push($result, '', '#### Example', $example);
|
||||
}
|
||||
array_push($result, "\n* * *", $closeTag);
|
||||
$this->addEntries($result, $subentries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/platform.js/platform.js
vendored
4
vendor/platform.js/platform.js
vendored
@@ -830,10 +830,10 @@
|
||||
};
|
||||
}
|
||||
// add browser/OS architecture
|
||||
if ((data = / (?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
|
||||
if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
|
||||
if (os) {
|
||||
os.architecture = 64;
|
||||
os.family = os.family.replace(data, '');
|
||||
os.family = os.family.replace(RegExp(' *' + data), '');
|
||||
}
|
||||
if (name && (/WOW64/i.test(ua) ||
|
||||
(useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
|
||||
|
||||
7
vendor/qunit-clib/qunit-clib.js
vendored
7
vendor/qunit-clib/qunit-clib.js
vendored
@@ -171,7 +171,12 @@
|
||||
|
||||
// exit out of Node.js
|
||||
try {
|
||||
process.exit();
|
||||
if (details.failed) {
|
||||
console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
|
||||
process.exit(1);
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
} catch(e) { }
|
||||
}
|
||||
|
||||
|
||||
14
vendor/qunit/README.md
vendored
14
vendor/qunit/README.md
vendored
@@ -1,4 +1,4 @@
|
||||
[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework.
|
||||
[QUnit](http://docs.jquery.com/QUnit) - A JavaScript Unit Testing framework.
|
||||
================================
|
||||
|
||||
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
|
||||
@@ -35,8 +35,7 @@ the change, run `grunt` to lint and test it, then commit, push and create a pull
|
||||
Include some background for the change in the commit message and `Fixes #nnn`, referring
|
||||
to the issue number you're addressing.
|
||||
|
||||
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global
|
||||
grunt binary. For additional grunt tasks, also run `npm install`.
|
||||
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`.
|
||||
|
||||
Releases
|
||||
--------
|
||||
@@ -48,12 +47,3 @@ tag, update them again to the next version, commit and push commits and tags
|
||||
|
||||
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
|
||||
or whitespace cleanups.
|
||||
|
||||
To upload to code.jquery.com (replace $version accordingly):
|
||||
|
||||
scp -q qunit/qunit.js jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.js
|
||||
scp -q qunit/qunit.css jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.css
|
||||
|
||||
Then update /var/www/html/code.jquery.com/index.html and purge it with:
|
||||
|
||||
curl -s http://code.origin.jquery.com/?reload
|
||||
16
vendor/qunit/qunit/qunit.css
vendored
16
vendor/qunit/qunit/qunit.css
vendored
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
|
||||
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
|
||||
*
|
||||
* http://qunitjs.com
|
||||
* http://docs.jquery.com/QUnit
|
||||
*
|
||||
* Copyright 2012 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
* Copyright (c) 2012 John Resig, Jörn Zaefferer
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* or GPL (GPL-LICENSE.txt) licenses.
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -67,7 +67,6 @@
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
@@ -77,9 +76,6 @@
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
|
||||
89
vendor/qunit/qunit/qunit.js
vendored
89
vendor/qunit/qunit/qunit.js
vendored
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
|
||||
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
|
||||
*
|
||||
* http://qunitjs.com
|
||||
* http://docs.jquery.com/QUnit
|
||||
*
|
||||
* Copyright 2012 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
* Copyright (c) 2012 John Resig, Jörn Zaefferer
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* or GPL (GPL-LICENSE.txt) licenses.
|
||||
*/
|
||||
|
||||
(function( window ) {
|
||||
@@ -17,8 +17,6 @@ var QUnit,
|
||||
fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
|
||||
toString = Object.prototype.toString,
|
||||
hasOwn = Object.prototype.hasOwnProperty,
|
||||
// Keep a local reference to Date (GH-283)
|
||||
Date = window.Date,
|
||||
defined = {
|
||||
setTimeout: typeof window.setTimeout !== "undefined",
|
||||
sessionStorage: (function() {
|
||||
@@ -306,8 +304,7 @@ QUnit = {
|
||||
// call on start of module test to prepend name to all tests
|
||||
module: function( name, testEnvironment ) {
|
||||
config.currentModule = name;
|
||||
config.currentModuleTestEnvironment = testEnvironment;
|
||||
config.modules[name] = true;
|
||||
config.currentModuleTestEnviroment = testEnvironment;
|
||||
},
|
||||
|
||||
asyncTest: function( testName, expected, callback ) {
|
||||
@@ -339,7 +336,7 @@ QUnit = {
|
||||
async: async,
|
||||
callback: callback,
|
||||
module: config.currentModule,
|
||||
moduleTestEnvironment: config.currentModuleTestEnvironment,
|
||||
moduleTestEnvironment: config.currentModuleTestEnviroment,
|
||||
stack: sourceFromStacktrace( 2 )
|
||||
});
|
||||
|
||||
@@ -352,11 +349,7 @@ QUnit = {
|
||||
|
||||
// Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
|
||||
expect: function( asserts ) {
|
||||
if (arguments.length === 1) {
|
||||
config.current.expected = asserts;
|
||||
} else {
|
||||
return config.current.expected;
|
||||
}
|
||||
config.current.expected = asserts;
|
||||
},
|
||||
|
||||
start: function( count ) {
|
||||
@@ -422,8 +415,6 @@ QUnit.assert = {
|
||||
|
||||
var source,
|
||||
details = {
|
||||
module: config.current.module,
|
||||
name: config.current.testName,
|
||||
result: result,
|
||||
message: msg
|
||||
};
|
||||
@@ -609,9 +600,6 @@ config = {
|
||||
}
|
||||
],
|
||||
|
||||
// Set of all modules.
|
||||
modules: {},
|
||||
|
||||
// logging callback queues
|
||||
begin: [],
|
||||
done: [],
|
||||
@@ -722,10 +710,17 @@ extend( QUnit, {
|
||||
},
|
||||
|
||||
// Resets the test setup. Useful for tests that modify the DOM.
|
||||
// If jQuery is available, uses jQuery's html(), otherwise just innerHTML.
|
||||
reset: function() {
|
||||
var fixture = id( "qunit-fixture" );
|
||||
if ( fixture ) {
|
||||
fixture.innerHTML = config.fixture;
|
||||
var fixture;
|
||||
|
||||
if ( window.jQuery ) {
|
||||
jQuery( "#qunit-fixture" ).html( config.fixture );
|
||||
} else {
|
||||
fixture = id( "qunit-fixture" );
|
||||
if ( fixture ) {
|
||||
fixture.innerHTML = config.fixture;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -786,8 +781,6 @@ extend( QUnit, {
|
||||
|
||||
var output, source,
|
||||
details = {
|
||||
module: config.current.module,
|
||||
name: config.current.testName,
|
||||
result: result,
|
||||
message: message,
|
||||
actual: actual,
|
||||
@@ -833,8 +826,6 @@ extend( QUnit, {
|
||||
|
||||
var output,
|
||||
details = {
|
||||
module: config.current.module,
|
||||
name: config.current.testName,
|
||||
result: false,
|
||||
message: message
|
||||
};
|
||||
@@ -925,9 +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, urlConfigCheckboxes, moduleFilter,
|
||||
numModules = 0,
|
||||
moduleFilterHtml = "",
|
||||
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes,
|
||||
urlConfigHtml = "",
|
||||
oldconfig = extend( {}, config );
|
||||
|
||||
@@ -951,15 +940,6 @@ QUnit.load = function() {
|
||||
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>";
|
||||
}
|
||||
|
||||
moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>";
|
||||
for ( i in config.modules ) {
|
||||
if ( config.modules.hasOwnProperty( i ) ) {
|
||||
numModules += 1;
|
||||
moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>";
|
||||
}
|
||||
}
|
||||
moduleFilterHtml += "</select>";
|
||||
|
||||
// `userAgent` initialized at top of scope
|
||||
userAgent = id( "qunit-userAgent" );
|
||||
if ( userAgent ) {
|
||||
@@ -1022,19 +1002,6 @@ QUnit.load = function() {
|
||||
window.location = QUnit.url( params );
|
||||
});
|
||||
toolbar.appendChild( urlConfigCheckboxes );
|
||||
|
||||
if (numModules > 1) {
|
||||
moduleFilter = document.createElement( 'span' );
|
||||
moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
|
||||
moduleFilter.innerHTML = moduleFilterHtml;
|
||||
addEvent( moduleFilter, "change", function() {
|
||||
var selectBox = moduleFilter.getElementsByTagName("select")[0],
|
||||
selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
|
||||
|
||||
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
|
||||
});
|
||||
toolbar.appendChild(moduleFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// `main` initialized at top of scope
|
||||
@@ -1072,9 +1039,9 @@ window.onerror = function ( error, filePath, linerNr ) {
|
||||
}
|
||||
QUnit.pushFailure( error, filePath + ":" + linerNr );
|
||||
} else {
|
||||
QUnit.test( "global failure", extend( function() {
|
||||
QUnit.test( "global failure", function() {
|
||||
QUnit.pushFailure( error, filePath + ":" + linerNr );
|
||||
}, { validTest: validTest } ) );
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1141,11 +1108,6 @@ function done() {
|
||||
}
|
||||
}
|
||||
|
||||
// scroll back to top to show results
|
||||
if ( window.scrollTo ) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
runLoggingCallbacks( "done", QUnit, {
|
||||
failed: config.stats.bad,
|
||||
passed: passed,
|
||||
@@ -1161,12 +1123,6 @@ function validTest( test ) {
|
||||
module = config.module && config.module.toLowerCase(),
|
||||
fullName = (test.module + ": " + test.testName).toLowerCase();
|
||||
|
||||
// Internally-generated tests are always valid
|
||||
if ( test.callback && test.callback.validTest === validTest ) {
|
||||
delete test.callback.validTest;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( config.testNumber ) {
|
||||
return test.testNumber === config.testNumber;
|
||||
}
|
||||
@@ -1448,8 +1404,7 @@ QUnit.equiv = (function() {
|
||||
a.global === b.global &&
|
||||
// (gmi) ...
|
||||
a.ignoreCase === b.ignoreCase &&
|
||||
a.multiline === b.multiline &&
|
||||
a.sticky === b.sticky;
|
||||
a.multiline === b.multiline;
|
||||
},
|
||||
|
||||
// - skip when the property is a method of an instance (OOP)
|
||||
|
||||
679
vendor/requirejs/require.js
vendored
679
vendor/requirejs/require.js
vendored
@@ -1,5 +1,5 @@
|
||||
/** vim: et:ts=4:sw=4:sts=4
|
||||
* @license RequireJS 2.0.6 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
* @license RequireJS 2.1.0 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/requirejs for details
|
||||
*/
|
||||
@@ -12,7 +12,7 @@ var requirejs, require, define;
|
||||
(function (global) {
|
||||
var req, s, head, baseElement, dataMain, src,
|
||||
interactiveScript, currentlyAddingScript, mainScript, subPath,
|
||||
version = '2.0.6',
|
||||
version = '2.1.0',
|
||||
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
|
||||
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
|
||||
jsSuffixRegExp = /\.js$/,
|
||||
@@ -147,41 +147,6 @@ var requirejs, require, define;
|
||||
return g;
|
||||
}
|
||||
|
||||
function makeContextModuleFunc(func, relMap, enableBuildCallback) {
|
||||
return function () {
|
||||
//A version of a require function that passes a moduleName
|
||||
//value for items that may need to
|
||||
//look up paths relative to the moduleName
|
||||
var args = aps.call(arguments, 0), lastArg;
|
||||
if (enableBuildCallback &&
|
||||
isFunction((lastArg = args[args.length - 1]))) {
|
||||
lastArg.__requireJsBuild = true;
|
||||
}
|
||||
args.push(relMap);
|
||||
return func.apply(null, args);
|
||||
};
|
||||
}
|
||||
|
||||
function addRequireMethods(req, context, relMap) {
|
||||
each([
|
||||
['toUrl'],
|
||||
['undef'],
|
||||
['defined', 'requireDefined'],
|
||||
['specified', 'requireSpecified']
|
||||
], function (item) {
|
||||
var prop = item[1] || item[0];
|
||||
req[item[0]] = context ? makeContextModuleFunc(context[prop], relMap) :
|
||||
//If no context, then use default context. Reference from
|
||||
//contexts instead of early binding to default context, so
|
||||
//that during builds, the latest instance of the default
|
||||
//context with its config gets used.
|
||||
function () {
|
||||
var ctx = contexts[defContextName];
|
||||
return ctx[prop].apply(ctx, arguments);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an error with a pointer to an URL with more information.
|
||||
* @param {String} id the error ID that maps to an ID on a web page.
|
||||
@@ -238,12 +203,7 @@ var requirejs, require, define;
|
||||
defined = {},
|
||||
urlFetched = {},
|
||||
requireCounter = 1,
|
||||
unnormalizedCounter = 1,
|
||||
//Used to track the order in which modules
|
||||
//should be executed, by the order they
|
||||
//load. Important for consistent cycle resolution
|
||||
//behavior.
|
||||
waitAry = [];
|
||||
unnormalizedCounter = 1;
|
||||
|
||||
/**
|
||||
* Trims the . and .. from an array of path segments.
|
||||
@@ -405,12 +365,25 @@ var requirejs, require, define;
|
||||
//Pop off the first array value, since it failed, and
|
||||
//retry
|
||||
pathConfig.shift();
|
||||
context.undef(id);
|
||||
context.require.undef(id);
|
||||
context.require([id]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Turns a plugin!resource to [plugin, resource]
|
||||
//with the plugin being undefined if the name
|
||||
//did not have a plugin prefix.
|
||||
function splitPrefix(name) {
|
||||
var prefix,
|
||||
index = name ? name.indexOf('!') : -1;
|
||||
if (index > -1) {
|
||||
prefix = name.substring(0, index);
|
||||
name = name.substring(index + 1, name.length);
|
||||
}
|
||||
return [prefix, name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a module mapping that includes plugin prefix, module
|
||||
* name, and path. If parentModuleMap is provided it will
|
||||
@@ -427,8 +400,7 @@ var requirejs, require, define;
|
||||
* @returns {Object}
|
||||
*/
|
||||
function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
|
||||
var url, pluginModule, suffix,
|
||||
index = name ? name.indexOf('!') : -1,
|
||||
var url, pluginModule, suffix, nameParts,
|
||||
prefix = null,
|
||||
parentName = parentModuleMap ? parentModuleMap.name : null,
|
||||
originalName = name,
|
||||
@@ -442,10 +414,9 @@ var requirejs, require, define;
|
||||
name = '_@r' + (requireCounter += 1);
|
||||
}
|
||||
|
||||
if (index !== -1) {
|
||||
prefix = name.substring(0, index);
|
||||
name = name.substring(index + 1, name.length);
|
||||
}
|
||||
nameParts = splitPrefix(name);
|
||||
prefix = nameParts[0];
|
||||
name = nameParts[1];
|
||||
|
||||
if (prefix) {
|
||||
prefix = normalize(prefix, parentName, applyMap);
|
||||
@@ -466,6 +437,15 @@ var requirejs, require, define;
|
||||
} else {
|
||||
//A regular module.
|
||||
normalizedName = normalize(name, parentName, applyMap);
|
||||
|
||||
//Normalized name may be a plugin ID due to map config
|
||||
//application in normalize. The map config values must
|
||||
//already be normalized, so do not need to redo that part.
|
||||
nameParts = splitPrefix(normalizedName);
|
||||
prefix = nameParts[0];
|
||||
normalizedName = nameParts[1];
|
||||
isNormalized = true;
|
||||
|
||||
url = context.nameToUrl(normalizedName);
|
||||
}
|
||||
}
|
||||
@@ -557,148 +537,71 @@ var requirejs, require, define;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that creates a require function object to give to
|
||||
* modules that ask for it as a dependency. It needs to be specific
|
||||
* per module because of the implication of path mappings that may
|
||||
* need to be relative to the module name.
|
||||
*/
|
||||
function makeRequire(mod, enableBuildCallback, altRequire) {
|
||||
var relMap = mod && mod.map,
|
||||
modRequire = makeContextModuleFunc(altRequire || context.require,
|
||||
relMap,
|
||||
enableBuildCallback);
|
||||
|
||||
addRequireMethods(modRequire, context, relMap);
|
||||
modRequire.isBrowser = isBrowser;
|
||||
|
||||
return modRequire;
|
||||
}
|
||||
|
||||
handlers = {
|
||||
'require': function (mod) {
|
||||
return makeRequire(mod);
|
||||
if (mod.require) {
|
||||
return mod.require;
|
||||
} else {
|
||||
return (mod.require = context.makeRequire(mod.map));
|
||||
}
|
||||
},
|
||||
'exports': function (mod) {
|
||||
mod.usingExports = true;
|
||||
if (mod.map.isDefine) {
|
||||
return (mod.exports = defined[mod.map.id] = {});
|
||||
if (mod.exports) {
|
||||
return mod.exports;
|
||||
} else {
|
||||
return (mod.exports = defined[mod.map.id] = {});
|
||||
}
|
||||
}
|
||||
},
|
||||
'module': function (mod) {
|
||||
return (mod.module = {
|
||||
id: mod.map.id,
|
||||
uri: mod.map.url,
|
||||
config: function () {
|
||||
return (config.config && config.config[mod.map.id]) || {};
|
||||
},
|
||||
exports: defined[mod.map.id]
|
||||
});
|
||||
if (mod.module) {
|
||||
return mod.module;
|
||||
} else {
|
||||
return (mod.module = {
|
||||
id: mod.map.id,
|
||||
uri: mod.map.url,
|
||||
config: function () {
|
||||
return (config.config && config.config[mod.map.id]) || {};
|
||||
},
|
||||
exports: defined[mod.map.id]
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function removeWaiting(id) {
|
||||
function cleanRegistry(id) {
|
||||
//Clean up machinery used for waiting modules.
|
||||
delete registry[id];
|
||||
|
||||
each(waitAry, function (mod, i) {
|
||||
if (mod.map.id === id) {
|
||||
waitAry.splice(i, 1);
|
||||
if (!mod.defined) {
|
||||
context.waitCount -= 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function findCycle(mod, traced, processed) {
|
||||
var id = mod.map.id,
|
||||
depArray = mod.depMaps,
|
||||
foundModule;
|
||||
function breakCycle(mod, traced, processed) {
|
||||
var id = mod.map.id;
|
||||
|
||||
//Do not bother with unitialized modules or not yet enabled
|
||||
//modules.
|
||||
if (!mod.inited) {
|
||||
return;
|
||||
}
|
||||
if (mod.error) {
|
||||
mod.emit('error', mod.error);
|
||||
} else {
|
||||
traced[id] = true;
|
||||
each(mod.depMaps, function (depMap, i) {
|
||||
var depId = depMap.id,
|
||||
dep = registry[depId];
|
||||
|
||||
//Found the cycle.
|
||||
if (traced[id]) {
|
||||
return mod;
|
||||
}
|
||||
|
||||
traced[id] = true;
|
||||
|
||||
//Trace through the dependencies.
|
||||
each(depArray, function (depMap) {
|
||||
var depId = depMap.id,
|
||||
depMod = registry[depId];
|
||||
|
||||
if (!depMod || processed[depId] ||
|
||||
!depMod.inited || !depMod.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (foundModule = findCycle(depMod, traced, processed));
|
||||
});
|
||||
|
||||
processed[id] = true;
|
||||
|
||||
return foundModule;
|
||||
}
|
||||
|
||||
function forceExec(mod, traced, uninited) {
|
||||
var id = mod.map.id,
|
||||
depArray = mod.depMaps;
|
||||
|
||||
if (!mod.inited || !mod.map.isDefine) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (traced[id]) {
|
||||
return defined[id];
|
||||
}
|
||||
|
||||
traced[id] = mod;
|
||||
|
||||
each(depArray, function (depMap) {
|
||||
var depId = depMap.id,
|
||||
depMod = registry[depId],
|
||||
value;
|
||||
|
||||
if (handlers[depId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (depMod) {
|
||||
if (!depMod.inited || !depMod.enabled) {
|
||||
//Dependency is not inited,
|
||||
//so this module cannot be
|
||||
//given a forced value yet.
|
||||
uninited[id] = true;
|
||||
return;
|
||||
//Only force things that have not completed
|
||||
//being defined, so still in the registry,
|
||||
//and only if it has not been matched up
|
||||
//in the module already.
|
||||
if (dep && !mod.depMatched[i] && !processed[depId]) {
|
||||
if (traced[depId]) {
|
||||
mod.defineDep(i, defined[depId]);
|
||||
mod.check(); //pass false?
|
||||
} else {
|
||||
breakCycle(dep, traced, processed);
|
||||
}
|
||||
}
|
||||
|
||||
//Get the value for the current dependency
|
||||
value = forceExec(depMod, traced, uninited);
|
||||
|
||||
//Even with forcing it may not be done,
|
||||
//in particular if the module is waiting
|
||||
//on a plugin resource.
|
||||
if (!uninited[depId]) {
|
||||
mod.defineDepById(depId, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mod.check(true);
|
||||
|
||||
return defined[id];
|
||||
}
|
||||
|
||||
function modCheck(mod) {
|
||||
mod.check();
|
||||
});
|
||||
processed[id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
function checkLoaded() {
|
||||
@@ -707,6 +610,7 @@ var requirejs, require, define;
|
||||
//It is possible to disable the wait interval by using waitSeconds of 0.
|
||||
expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
|
||||
noLoads = [],
|
||||
reqCalls = [],
|
||||
stillLoading = false,
|
||||
needCycleCheck = true;
|
||||
|
||||
@@ -727,6 +631,10 @@ var requirejs, require, define;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!map.isDefine) {
|
||||
reqCalls.push(mod);
|
||||
}
|
||||
|
||||
if (!mod.error) {
|
||||
//If the module should be executed, and it has not
|
||||
//been inited and time is up, remember it.
|
||||
@@ -761,31 +669,9 @@ var requirejs, require, define;
|
||||
|
||||
//Not expired, check for a cycle.
|
||||
if (needCycleCheck) {
|
||||
|
||||
each(waitAry, function (mod) {
|
||||
if (mod.defined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var cycleMod = findCycle(mod, {}, {}),
|
||||
traced = {};
|
||||
|
||||
if (cycleMod) {
|
||||
forceExec(cycleMod, traced, {});
|
||||
|
||||
//traced modules may have been
|
||||
//removed from the registry, but
|
||||
//their listeners still need to
|
||||
//be called.
|
||||
eachProp(traced, modCheck);
|
||||
}
|
||||
each(reqCalls, function (mod) {
|
||||
breakCycle(mod, {}, {});
|
||||
});
|
||||
|
||||
//Now that dependencies have
|
||||
//been satisfied, trigger the
|
||||
//completion check that then
|
||||
//notifies listeners.
|
||||
eachProp(registry, modCheck);
|
||||
}
|
||||
|
||||
//If still waiting on loads, and the waiting load is something
|
||||
@@ -851,7 +737,6 @@ var requirejs, require, define;
|
||||
//doing a direct modification of the depMaps array
|
||||
//would affect that config.
|
||||
this.depMaps = depMaps && depMaps.slice(0);
|
||||
this.depMaps.rjsSkipMap = depMaps.rjsSkipMap;
|
||||
|
||||
this.errback = errback;
|
||||
|
||||
@@ -873,20 +758,6 @@ var requirejs, require, define;
|
||||
}
|
||||
},
|
||||
|
||||
defineDepById: function (id, depExports) {
|
||||
var i;
|
||||
|
||||
//Find the index for this dependency.
|
||||
each(this.depMaps, function (map, index) {
|
||||
if (map.id === id) {
|
||||
i = index;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return this.defineDep(i, depExports);
|
||||
},
|
||||
|
||||
defineDep: function (i, depExports) {
|
||||
//Because of cycles, defined callback for a given
|
||||
//export can be called more than once.
|
||||
@@ -910,7 +781,9 @@ var requirejs, require, define;
|
||||
//If the manager is for a plugin managed resource,
|
||||
//ask the plugin to load it now.
|
||||
if (this.shim) {
|
||||
makeRequire(this, true)(this.shim.deps || [], bind(this, function () {
|
||||
context.makeRequire(this.map, {
|
||||
enableBuildCallback: true
|
||||
})(this.shim.deps || [], bind(this, function () {
|
||||
return map.prefix ? this.callPlugin() : this.load();
|
||||
}));
|
||||
} else {
|
||||
@@ -931,11 +804,9 @@ var requirejs, require, define;
|
||||
|
||||
/**
|
||||
* Checks is the module is ready to define itself, and if so,
|
||||
* define it. If the silent argument is true, then it will just
|
||||
* define, but not notify listeners, and not ask for a context-wide
|
||||
* check of all loaded modules. That is useful for cycle breaking.
|
||||
* define it.
|
||||
*/
|
||||
check: function (silent) {
|
||||
check: function () {
|
||||
if (!this.enabled || this.enabling) {
|
||||
return;
|
||||
}
|
||||
@@ -1013,11 +884,6 @@ var requirejs, require, define;
|
||||
delete registry[id];
|
||||
|
||||
this.defined = true;
|
||||
context.waitCount -= 1;
|
||||
if (context.waitCount === 0) {
|
||||
//Clear the wait array used for cycles.
|
||||
waitAry = [];
|
||||
}
|
||||
}
|
||||
|
||||
//Finished the define stage. Allow calling check again
|
||||
@@ -1025,25 +891,33 @@ var requirejs, require, define;
|
||||
//cycle.
|
||||
this.defining = false;
|
||||
|
||||
if (!silent) {
|
||||
if (this.defined && !this.defineEmitted) {
|
||||
this.defineEmitted = true;
|
||||
this.emit('defined', this.exports);
|
||||
this.defineEmitComplete = true;
|
||||
}
|
||||
if (this.defined && !this.defineEmitted) {
|
||||
this.defineEmitted = true;
|
||||
this.emit('defined', this.exports);
|
||||
this.defineEmitComplete = true;
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
callPlugin: function () {
|
||||
var map = this.map,
|
||||
id = map.id,
|
||||
pluginMap = makeModuleMap(map.prefix, null, false, true);
|
||||
//Map already normalized the prefix.
|
||||
pluginMap = makeModuleMap(map.prefix);
|
||||
|
||||
//Mark this as a dependency for this plugin, so it
|
||||
//can be traced for cycles.
|
||||
this.depMaps.push(pluginMap);
|
||||
|
||||
on(pluginMap, 'defined', bind(this, function (plugin) {
|
||||
var load, normalizedMap, normalizedMod,
|
||||
name = this.map.name,
|
||||
parentName = this.map.parentMap ? this.map.parentMap.name : null;
|
||||
parentName = this.map.parentMap ? this.map.parentMap.name : null,
|
||||
localRequire = context.makeRequire(map.parentMap, {
|
||||
enableBuildCallback: true,
|
||||
skipMap: true
|
||||
});
|
||||
|
||||
//If current map is not normalized, wait for that
|
||||
//normalized name to load instead of continuing.
|
||||
@@ -1055,10 +929,10 @@ var requirejs, require, define;
|
||||
}) || '';
|
||||
}
|
||||
|
||||
//prefix and name should already be normalized, no need
|
||||
//for applying map config again either.
|
||||
normalizedMap = makeModuleMap(map.prefix + '!' + name,
|
||||
this.map.parentMap,
|
||||
false,
|
||||
true);
|
||||
this.map.parentMap);
|
||||
on(normalizedMap,
|
||||
'defined', bind(this, function (value) {
|
||||
this.init([], function () { return value; }, null, {
|
||||
@@ -1066,8 +940,13 @@ var requirejs, require, define;
|
||||
ignore: true
|
||||
});
|
||||
}));
|
||||
|
||||
normalizedMod = registry[normalizedMap.id];
|
||||
if (normalizedMod) {
|
||||
//Mark this as a dependency for this plugin, so it
|
||||
//can be traced for cycles.
|
||||
this.depMaps.push(normalizedMap);
|
||||
|
||||
if (this.events.error) {
|
||||
normalizedMod.on('error', bind(this, function (err) {
|
||||
this.emit('error', err);
|
||||
@@ -1094,7 +973,7 @@ var requirejs, require, define;
|
||||
//since they will never be resolved otherwise now.
|
||||
eachProp(registry, function (mod) {
|
||||
if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
|
||||
removeWaiting(mod.map.id);
|
||||
cleanRegistry(mod.map.id);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1103,9 +982,19 @@ var requirejs, require, define;
|
||||
|
||||
//Allow plugins to load other code without having to know the
|
||||
//context or how to 'complete' the load.
|
||||
load.fromText = function (moduleName, text) {
|
||||
load.fromText = bind(this, function (text, textAlt) {
|
||||
/*jslint evil: true */
|
||||
var hasInteractive = useInteractive;
|
||||
var moduleName = map.name,
|
||||
moduleMap = makeModuleMap(moduleName),
|
||||
hasInteractive = useInteractive;
|
||||
|
||||
//As of 2.1.0, support just passing the text, to reinforce
|
||||
//fromText only being called once per resource. Still
|
||||
//support old style of passing moduleName but discard
|
||||
//that moduleName in favor of the internal ref.
|
||||
if (textAlt) {
|
||||
text = textAlt;
|
||||
}
|
||||
|
||||
//Turn off interactive script matching for IE for any define
|
||||
//calls in the text, then turn it back on at the end.
|
||||
@@ -1115,25 +1004,35 @@ var requirejs, require, define;
|
||||
|
||||
//Prime the system by creating a module instance for
|
||||
//it.
|
||||
getModule(makeModuleMap(moduleName));
|
||||
getModule(moduleMap);
|
||||
|
||||
req.exec(text);
|
||||
try {
|
||||
req.exec(text);
|
||||
} catch (e) {
|
||||
throw new Error('fromText eval for ' + moduleName +
|
||||
' failed: ' + e);
|
||||
}
|
||||
|
||||
if (hasInteractive) {
|
||||
useInteractive = true;
|
||||
}
|
||||
|
||||
//Mark this as a dependency for the plugin
|
||||
//resource
|
||||
this.depMaps.push(moduleMap);
|
||||
|
||||
//Support anonymous modules.
|
||||
context.completeLoad(moduleName);
|
||||
};
|
||||
|
||||
//Bind the value of that module to the value for this
|
||||
//resource ID.
|
||||
localRequire([moduleName], load);
|
||||
});
|
||||
|
||||
//Use parentName here since the plugin's name is not reliable,
|
||||
//could be some weird string with no path that actually wants to
|
||||
//reference the parentName's path.
|
||||
plugin.load(map.name, makeRequire(map.parentMap, true, function (deps, cb, er) {
|
||||
deps.rjsSkipMap = true;
|
||||
return context.require(deps, cb, er);
|
||||
}), load, config);
|
||||
plugin.load(map.name, localRequire, load, config);
|
||||
}));
|
||||
|
||||
context.enable(pluginMap, this);
|
||||
@@ -1143,12 +1042,6 @@ var requirejs, require, define;
|
||||
enable: function () {
|
||||
this.enabled = true;
|
||||
|
||||
if (!this.waitPushed) {
|
||||
waitAry.push(this);
|
||||
context.waitCount += 1;
|
||||
this.waitPushed = true;
|
||||
}
|
||||
|
||||
//Set flag mentioning that the module is enabling,
|
||||
//so that immediate calls to the defined callbacks
|
||||
//for dependencies do not trigger inadvertent load
|
||||
@@ -1165,7 +1058,7 @@ var requirejs, require, define;
|
||||
depMap = makeModuleMap(depMap,
|
||||
(this.map.isDefine ? this.map : this.map.parentMap),
|
||||
false,
|
||||
!this.depMaps.rjsSkipMap);
|
||||
!this.skipMap);
|
||||
this.depMaps[i] = depMap;
|
||||
|
||||
handler = handlers[depMap.id];
|
||||
@@ -1227,7 +1120,7 @@ var requirejs, require, define;
|
||||
if (name === 'error') {
|
||||
//Now that the error handler was triggered, remove
|
||||
//the listeners, since this broken Module instance
|
||||
//can stay around for a while in the registry/waitAry.
|
||||
//can stay around for a while in the registry.
|
||||
delete this.events[name];
|
||||
}
|
||||
}
|
||||
@@ -1274,16 +1167,16 @@ var requirejs, require, define;
|
||||
};
|
||||
}
|
||||
|
||||
return (context = {
|
||||
context = {
|
||||
config: config,
|
||||
contextName: contextName,
|
||||
registry: registry,
|
||||
defined: defined,
|
||||
urlFetched: urlFetched,
|
||||
waitCount: 0,
|
||||
defQueue: defQueue,
|
||||
Module: Module,
|
||||
makeModuleMap: makeModuleMap,
|
||||
nextTick: req.nextTick,
|
||||
|
||||
/**
|
||||
* Set a configuration for the context.
|
||||
@@ -1325,8 +1218,8 @@ var requirejs, require, define;
|
||||
deps: value
|
||||
};
|
||||
}
|
||||
if (value.exports && !value.exports.__buildReady) {
|
||||
value.exports = context.makeShimExports(value.exports);
|
||||
if (value.exports && !value.exportsFn) {
|
||||
value.exportsFn = context.makeShimExports(value);
|
||||
}
|
||||
shim[id] = value;
|
||||
});
|
||||
@@ -1381,125 +1274,152 @@ var requirejs, require, define;
|
||||
}
|
||||
},
|
||||
|
||||
makeShimExports: function (exports) {
|
||||
var func;
|
||||
if (typeof exports === 'string') {
|
||||
func = function () {
|
||||
return getGlobal(exports);
|
||||
};
|
||||
//Save the exports for use in nodefine checking.
|
||||
func.exports = exports;
|
||||
return func;
|
||||
} else {
|
||||
return function () {
|
||||
return exports.apply(global, arguments);
|
||||
};
|
||||
makeShimExports: function (value) {
|
||||
function fn() {
|
||||
var ret;
|
||||
if (value.init) {
|
||||
ret = value.init.apply(global, arguments);
|
||||
}
|
||||
return ret || getGlobal(value.exports);
|
||||
}
|
||||
return fn;
|
||||
},
|
||||
|
||||
requireDefined: function (id, relMap) {
|
||||
return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
|
||||
},
|
||||
makeRequire: function (relMap, options) {
|
||||
options = options || {};
|
||||
|
||||
requireSpecified: function (id, relMap) {
|
||||
id = makeModuleMap(id, relMap, false, true).id;
|
||||
return hasProp(defined, id) || hasProp(registry, id);
|
||||
},
|
||||
function require(deps, callback, errback) {
|
||||
var id, map, requireMod, args;
|
||||
|
||||
require: function (deps, callback, errback, relMap) {
|
||||
var moduleName, id, map, requireMod, args;
|
||||
if (typeof deps === 'string') {
|
||||
if (isFunction(callback)) {
|
||||
//Invalid call
|
||||
return onError(makeError('requireargs', 'Invalid require call'), errback);
|
||||
if (options.enableBuildCallback && callback && isFunction(callback)) {
|
||||
callback.__requireJsBuild = true;
|
||||
}
|
||||
|
||||
//Synchronous access to one module. If require.get is
|
||||
//available (as in the Node adapter), prefer that.
|
||||
//In this case deps is the moduleName and callback is
|
||||
//the relMap
|
||||
if (req.get) {
|
||||
return req.get(context, deps, callback);
|
||||
if (typeof deps === 'string') {
|
||||
if (isFunction(callback)) {
|
||||
//Invalid call
|
||||
return onError(makeError('requireargs', 'Invalid require call'), errback);
|
||||
}
|
||||
|
||||
//If require|exports|module are requested, get the
|
||||
//value for them from the special handlers. Caveat:
|
||||
//this only works while module is being defined.
|
||||
if (relMap && handlers[deps]) {
|
||||
return handlers[deps](registry[relMap.id]);
|
||||
}
|
||||
|
||||
//Synchronous access to one module. If require.get is
|
||||
//available (as in the Node adapter), prefer that.
|
||||
if (req.get) {
|
||||
return req.get(context, deps, relMap);
|
||||
}
|
||||
|
||||
//Normalize module name, if it contains . or ..
|
||||
map = makeModuleMap(deps, relMap, false, true);
|
||||
id = map.id;
|
||||
|
||||
if (!hasProp(defined, id)) {
|
||||
return onError(makeError('notloaded', 'Module name "' +
|
||||
id +
|
||||
'" has not been loaded yet for context: ' +
|
||||
contextName +
|
||||
(relMap ? '' : '. Use require([])')));
|
||||
}
|
||||
return defined[id];
|
||||
}
|
||||
|
||||
//Just return the module wanted. In this scenario, the
|
||||
//second arg (if passed) is just the relMap.
|
||||
moduleName = deps;
|
||||
relMap = callback;
|
||||
//Any defined modules in the global queue, intake them now.
|
||||
takeGlobalQueue();
|
||||
|
||||
//Normalize module name, if it contains . or ..
|
||||
map = makeModuleMap(moduleName, relMap, false, true);
|
||||
id = map.id;
|
||||
|
||||
if (!hasProp(defined, id)) {
|
||||
return onError(makeError('notloaded', 'Module name "' +
|
||||
id +
|
||||
'" has not been loaded yet for context: ' +
|
||||
contextName));
|
||||
//Make sure any remaining defQueue items get properly processed.
|
||||
while (defQueue.length) {
|
||||
args = defQueue.shift();
|
||||
if (args[0] === null) {
|
||||
return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
|
||||
} else {
|
||||
//args are id, deps, factory. Should be normalized by the
|
||||
//define() function.
|
||||
callGetModule(args);
|
||||
}
|
||||
}
|
||||
return defined[id];
|
||||
|
||||
//Mark all the dependencies as needing to be loaded.
|
||||
context.nextTick(function () {
|
||||
requireMod = getModule(makeModuleMap(null, relMap));
|
||||
|
||||
//Store if map config should be applied to this require
|
||||
//call for dependencies.
|
||||
requireMod.skipMap = options.skipMap;
|
||||
|
||||
requireMod.init(deps, callback, errback, {
|
||||
enabled: true
|
||||
});
|
||||
|
||||
checkLoaded();
|
||||
});
|
||||
|
||||
return require;
|
||||
}
|
||||
|
||||
//Callback require. Normalize args. if callback or errback is
|
||||
//not a function, it means it is a relMap. Test errback first.
|
||||
if (errback && !isFunction(errback)) {
|
||||
relMap = errback;
|
||||
errback = undefined;
|
||||
}
|
||||
if (callback && !isFunction(callback)) {
|
||||
relMap = callback;
|
||||
callback = undefined;
|
||||
}
|
||||
mixin(require, {
|
||||
isBrowser: isBrowser,
|
||||
|
||||
//Any defined modules in the global queue, intake them now.
|
||||
takeGlobalQueue();
|
||||
/**
|
||||
* Converts a module name + .extension into an URL path.
|
||||
* *Requires* the use of a module name. It does not support using
|
||||
* plain URLs like nameToUrl.
|
||||
*/
|
||||
toUrl: function (moduleNamePlusExt) {
|
||||
var index = moduleNamePlusExt.lastIndexOf('.'),
|
||||
ext = null;
|
||||
|
||||
//Make sure any remaining defQueue items get properly processed.
|
||||
while (defQueue.length) {
|
||||
args = defQueue.shift();
|
||||
if (args[0] === null) {
|
||||
return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));
|
||||
} else {
|
||||
//args are id, deps, factory. Should be normalized by the
|
||||
//define() function.
|
||||
callGetModule(args);
|
||||
if (index !== -1) {
|
||||
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
|
||||
moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
|
||||
}
|
||||
|
||||
return context.nameToUrl(normalize(moduleNamePlusExt,
|
||||
relMap && relMap.id, true), ext);
|
||||
},
|
||||
|
||||
defined: function (id) {
|
||||
return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
|
||||
},
|
||||
|
||||
specified: function (id) {
|
||||
id = makeModuleMap(id, relMap, false, true).id;
|
||||
return hasProp(defined, id) || hasProp(registry, id);
|
||||
}
|
||||
}
|
||||
|
||||
//Mark all the dependencies as needing to be loaded.
|
||||
requireMod = getModule(makeModuleMap(null, relMap));
|
||||
|
||||
requireMod.init(deps, callback, errback, {
|
||||
enabled: true
|
||||
});
|
||||
|
||||
checkLoaded();
|
||||
//Only allow undef on top level require calls
|
||||
if (!relMap) {
|
||||
require.undef = function (id) {
|
||||
//Bind any waiting define() calls to this context,
|
||||
//fix for #408
|
||||
takeGlobalQueue();
|
||||
|
||||
return context.require;
|
||||
},
|
||||
var map = makeModuleMap(id, relMap, true),
|
||||
mod = registry[id];
|
||||
|
||||
undef: function (id) {
|
||||
//Bind any waiting define() calls to this context,
|
||||
//fix for #408
|
||||
takeGlobalQueue();
|
||||
delete defined[id];
|
||||
delete urlFetched[map.url];
|
||||
delete undefEvents[id];
|
||||
|
||||
var map = makeModuleMap(id, null, true),
|
||||
mod = registry[id];
|
||||
if (mod) {
|
||||
//Hold on to listeners in case the
|
||||
//module will be attempted to be reloaded
|
||||
//using a different config.
|
||||
if (mod.events.defined) {
|
||||
undefEvents[id] = mod.events;
|
||||
}
|
||||
|
||||
delete defined[id];
|
||||
delete urlFetched[map.url];
|
||||
delete undefEvents[id];
|
||||
|
||||
if (mod) {
|
||||
//Hold on to listeners in case the
|
||||
//module will be attempted to be reloaded
|
||||
//using a different config.
|
||||
if (mod.events.defined) {
|
||||
undefEvents[id] = mod.events;
|
||||
}
|
||||
|
||||
removeWaiting(id);
|
||||
cleanRegistry(id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return require;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -1523,7 +1443,7 @@ var requirejs, require, define;
|
||||
completeLoad: function (moduleName) {
|
||||
var found, args, mod,
|
||||
shim = config.shim[moduleName] || {},
|
||||
shExports = shim.exports && shim.exports.exports;
|
||||
shExports = shim.exports;
|
||||
|
||||
takeGlobalQueue();
|
||||
|
||||
@@ -1563,31 +1483,13 @@ var requirejs, require, define;
|
||||
} else {
|
||||
//A script that does not call define(), so just simulate
|
||||
//the call for it.
|
||||
callGetModule([moduleName, (shim.deps || []), shim.exports]);
|
||||
callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
|
||||
}
|
||||
}
|
||||
|
||||
checkLoaded();
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a module name + .extension into an URL path.
|
||||
* *Requires* the use of a module name. It does not support using
|
||||
* plain URLs like nameToUrl.
|
||||
*/
|
||||
toUrl: function (moduleNamePlusExt, relModuleMap) {
|
||||
var index = moduleNamePlusExt.lastIndexOf('.'),
|
||||
ext = null;
|
||||
|
||||
if (index !== -1) {
|
||||
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
|
||||
moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
|
||||
}
|
||||
|
||||
return context.nameToUrl(normalize(moduleNamePlusExt, relModuleMap && relModuleMap.id, true),
|
||||
ext);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts a module name to a file path. Supports cases where
|
||||
* moduleName may actually be just an URL.
|
||||
@@ -1701,7 +1603,10 @@ var requirejs, require, define;
|
||||
return onError(makeError('scripterror', 'Script error', evt, [data.id]));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
context.require = context.makeRequire();
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1762,6 +1667,16 @@ var requirejs, require, define;
|
||||
return req(config);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute something after the current tick
|
||||
* of the event loop. Override for other envs
|
||||
* that have a better solution than setTimeout.
|
||||
* @param {Function} fn function to execute later.
|
||||
*/
|
||||
req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
|
||||
setTimeout(fn, 4);
|
||||
} : function (fn) { fn(); };
|
||||
|
||||
/**
|
||||
* Export require as a global, but only if it does not already exist.
|
||||
*/
|
||||
@@ -1782,9 +1697,21 @@ var requirejs, require, define;
|
||||
//Create default context.
|
||||
req({});
|
||||
|
||||
//Exports some context-sensitive methods on global require, using
|
||||
//default context if no context specified.
|
||||
addRequireMethods(req);
|
||||
//Exports some context-sensitive methods on global require.
|
||||
each([
|
||||
'toUrl',
|
||||
'undef',
|
||||
'defined',
|
||||
'specified'
|
||||
], function (prop) {
|
||||
//Reference from contexts instead of early binding to default context,
|
||||
//so that during builds, the latest instance of the default context
|
||||
//with its config gets used.
|
||||
req[prop] = function () {
|
||||
var ctx = contexts[defContextName];
|
||||
return ctx.require[prop].apply(ctx, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
if (isBrowser) {
|
||||
head = s.head = document.getElementsByTagName('head')[0];
|
||||
@@ -1962,7 +1889,7 @@ var requirejs, require, define;
|
||||
define = function (name, deps, callback) {
|
||||
var node, context;
|
||||
|
||||
//Allow for anonymous functions
|
||||
//Allow for anonymous modules
|
||||
if (typeof name !== 'string') {
|
||||
//Adjust args appropriately
|
||||
callback = deps;
|
||||
|
||||
19
vendor/underscore/test/arrays.js
vendored
19
vendor/underscore/test/arrays.js
vendored
@@ -14,6 +14,8 @@ $(document).ready(function() {
|
||||
equal(result.join(','), '1,1', 'works well with _.map');
|
||||
result = (function() { return _.take([1,2,3], 2); })();
|
||||
equal(result.join(','), '1,2', 'aliased as take');
|
||||
|
||||
equal(_.first(null), undefined, 'handles nulls');
|
||||
});
|
||||
|
||||
test("rest", function() {
|
||||
@@ -47,6 +49,8 @@ $(document).ready(function() {
|
||||
equal(result, 4, 'works on an arguments object');
|
||||
result = _.map([[1,2,3],[1,2,3]], _.last);
|
||||
equal(result.join(','), '3,3', 'works well with _.map');
|
||||
|
||||
equal(_.last(null), undefined, 'handles nulls');
|
||||
});
|
||||
|
||||
test("compact", function() {
|
||||
@@ -136,6 +140,8 @@ $(document).ready(function() {
|
||||
|
||||
var stooges = {moe: 30, larry: 40, curly: 50};
|
||||
ok(_.isEqual(_.object(_.pairs(stooges)), stooges), 'an object converted to pairs and back to an object');
|
||||
|
||||
ok(_.isEqual(_.object(null), {}), 'handles nulls');
|
||||
});
|
||||
|
||||
test("indexOf", function() {
|
||||
@@ -157,16 +163,27 @@ $(document).ready(function() {
|
||||
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
||||
index = _.indexOf(numbers, num, true);
|
||||
equal(index, 1, '40 is in the list');
|
||||
|
||||
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||
index = _.indexOf(numbers, 2, 5);
|
||||
equal(index, 7, 'supports the fromIndex argument');
|
||||
});
|
||||
|
||||
test("lastIndexOf", function() {
|
||||
var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||
var numbers = [1, 0, 1];
|
||||
equal(_.lastIndexOf(numbers, 1), 2);
|
||||
|
||||
numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||
numbers.lastIndexOf = null;
|
||||
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||
equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
||||
var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);
|
||||
equal(result, 5, 'works on an arguments object');
|
||||
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||
|
||||
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||
index = _.lastIndexOf(numbers, 2, 2);
|
||||
equal(index, 1, 'supports the fromIndex argument');
|
||||
});
|
||||
|
||||
test("range", function() {
|
||||
|
||||
119
vendor/underscore/test/collections.js
vendored
119
vendor/underscore/test/collections.js
vendored
@@ -44,8 +44,13 @@ $(document).ready(function() {
|
||||
var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
|
||||
equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');
|
||||
|
||||
if (document.querySelectorAll) {
|
||||
var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; });
|
||||
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.');
|
||||
}
|
||||
|
||||
var ids = _.map($('#map-test').children(), function(n){ return n.id; });
|
||||
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.');
|
||||
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.');
|
||||
|
||||
var ids = _.map(document.images, function(n){ return n.id; });
|
||||
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
|
||||
@@ -102,10 +107,46 @@ $(document).ready(function() {
|
||||
}
|
||||
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
||||
|
||||
var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; });
|
||||
equal(sum, 6, 'default initial value on object');
|
||||
|
||||
ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');
|
||||
|
||||
equal(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case');
|
||||
raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
|
||||
|
||||
// Assert that the correct arguments are being passed.
|
||||
|
||||
var args,
|
||||
memo = {},
|
||||
object = {a: 1, b: 2},
|
||||
lastKey = _.keys(object).pop();
|
||||
|
||||
var expected = lastKey == 'a'
|
||||
? [memo, 1, 'a', object]
|
||||
: [memo, 2, 'b', object];
|
||||
|
||||
_.reduceRight(object, function() {
|
||||
args || (args = _.toArray(arguments));
|
||||
}, memo);
|
||||
|
||||
deepEqual(args, expected);
|
||||
|
||||
// And again, with numeric keys.
|
||||
|
||||
object = {'2': 'a', '1': 'b'};
|
||||
lastKey = _.keys(object).pop();
|
||||
args = null;
|
||||
|
||||
expected = lastKey == '2'
|
||||
? [memo, 'a', '2', object]
|
||||
: [memo, 'b', '1', object];
|
||||
|
||||
_.reduceRight(object, function() {
|
||||
args || (args = _.toArray(arguments));
|
||||
}, memo);
|
||||
|
||||
deepEqual(args, expected);
|
||||
});
|
||||
|
||||
test('find', function() {
|
||||
@@ -201,6 +242,16 @@ $(document).ready(function() {
|
||||
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');
|
||||
});
|
||||
|
||||
test('where', function() {
|
||||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||
var result = _.where(list, {a: 1});
|
||||
equal(result.length, 3);
|
||||
equal(result[result.length - 1].b, 4);
|
||||
result = _.where(list, {b: 2});
|
||||
equal(result.length, 2);
|
||||
equal(result[0].a, 1);
|
||||
});
|
||||
|
||||
test('max', function() {
|
||||
equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
|
||||
|
||||
@@ -240,6 +291,29 @@ $(document).ready(function() {
|
||||
var list = ["one", "two", "three", "four", "five"];
|
||||
var sorted = _.sortBy(list, 'length');
|
||||
equal(sorted.join(' '), 'one two four five three', 'sorted by length');
|
||||
|
||||
function Pair(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
var collection = [
|
||||
new Pair(1, 1), new Pair(1, 2),
|
||||
new Pair(1, 3), new Pair(1, 4),
|
||||
new Pair(1, 5), new Pair(1, 6),
|
||||
new Pair(2, 1), new Pair(2, 2),
|
||||
new Pair(2, 3), new Pair(2, 4),
|
||||
new Pair(2, 5), new Pair(2, 6),
|
||||
new Pair(undefined, 1), new Pair(undefined, 2),
|
||||
new Pair(undefined, 3), new Pair(undefined, 4),
|
||||
new Pair(undefined, 5), new Pair(undefined, 6)
|
||||
];
|
||||
|
||||
var actual = _.sortBy(collection, function(pair) {
|
||||
return pair.x;
|
||||
});
|
||||
|
||||
deepEqual(actual, collection, 'sortBy should be stable');
|
||||
});
|
||||
|
||||
test('groupBy', function() {
|
||||
@@ -252,6 +326,18 @@ $(document).ready(function() {
|
||||
equal(grouped['3'].join(' '), 'one two six ten');
|
||||
equal(grouped['4'].join(' '), 'four five nine');
|
||||
equal(grouped['5'].join(' '), 'three seven eight');
|
||||
|
||||
var context = {};
|
||||
_.groupBy([{}], function(){ ok(this === context); }, context);
|
||||
|
||||
grouped = _.groupBy([4.2, 6.1, 6.4], function(num) {
|
||||
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
|
||||
});
|
||||
equal(grouped.constructor.length, 1);
|
||||
equal(grouped.hasOwnProperty.length, 2);
|
||||
|
||||
var array = [{}];
|
||||
_.groupBy(array, function(value, index, obj){ ok(obj === array); });
|
||||
});
|
||||
|
||||
test('countBy', function() {
|
||||
@@ -264,6 +350,18 @@ $(document).ready(function() {
|
||||
equal(grouped['3'], 4);
|
||||
equal(grouped['4'], 3);
|
||||
equal(grouped['5'], 3);
|
||||
|
||||
var context = {};
|
||||
_.countBy([{}], function(){ ok(this === context); }, context);
|
||||
|
||||
grouped = _.countBy([4.2, 6.1, 6.4], function(num) {
|
||||
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
|
||||
});
|
||||
equal(grouped.constructor, 1);
|
||||
equal(grouped.hasOwnProperty, 2);
|
||||
|
||||
var array = [{}];
|
||||
_.countBy(array, function(value, index, obj){ ok(obj === array); });
|
||||
});
|
||||
|
||||
test('sortedIndex', function() {
|
||||
@@ -273,6 +371,15 @@ $(document).ready(function() {
|
||||
|
||||
var indexFor30 = _.sortedIndex(numbers, 30);
|
||||
equal(indexFor30, 2, '30 should be inserted at index 2');
|
||||
|
||||
var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];
|
||||
var iterator = function(obj){ return obj.x; };
|
||||
strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2);
|
||||
strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3);
|
||||
|
||||
var context = {1: 2, 2: 3, 3: 4};
|
||||
iterator = function(obj){ return this[obj]; };
|
||||
strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1);
|
||||
});
|
||||
|
||||
test('shuffle', function() {
|
||||
@@ -291,14 +398,6 @@ $(document).ready(function() {
|
||||
|
||||
var numbers = _.toArray({one : 1, two : 2, three : 3});
|
||||
equal(numbers.join(', '), '1, 2, 3', 'object flattened into array');
|
||||
|
||||
var objectWithToArrayFunction = {toArray: function() {
|
||||
return [1, 2, 3];
|
||||
}};
|
||||
equal(_.toArray(objectWithToArrayFunction).join(', '), '1, 2, 3', 'toArray method used if present');
|
||||
|
||||
var objectWithToArrayValue = {toArray: 1};
|
||||
equal(_.toArray(objectWithToArrayValue).join(', '), '1', 'toArray property ignored if not a function');
|
||||
});
|
||||
|
||||
test('size', function() {
|
||||
@@ -312,6 +411,8 @@ $(document).ready(function() {
|
||||
equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object');
|
||||
|
||||
equal(_.size('hello'), 5, 'can compute the size of a string');
|
||||
|
||||
equal(_.size(null), 0, 'handles nulls');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
16
vendor/underscore/test/functions.js
vendored
16
vendor/underscore/test/functions.js
vendored
@@ -141,7 +141,7 @@ $(document).ready(function() {
|
||||
var incr = function(){ return ++counter; };
|
||||
var throttledIncr = _.throttle(incr, 100);
|
||||
var results = [];
|
||||
var saveResult = function() { results.push(throttledIncr()); }
|
||||
var saveResult = function() { results.push(throttledIncr()); };
|
||||
saveResult(); saveResult(); saveResult();
|
||||
setTimeout(saveResult, 70);
|
||||
setTimeout(saveResult, 120);
|
||||
@@ -159,7 +159,7 @@ $(document).ready(function() {
|
||||
equal(results[6], 2, "incr was throttled");
|
||||
equal(results[7], 3, "incr was called thrice");
|
||||
equal(results[8], 3, "incr was throttled");
|
||||
start();
|
||||
start();
|
||||
}, 400);
|
||||
});
|
||||
|
||||
@@ -176,11 +176,17 @@ $(document).ready(function() {
|
||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
|
||||
});
|
||||
|
||||
asyncTest("debounce asap", 2, function() {
|
||||
asyncTest("debounce asap", 5, function() {
|
||||
var a, b, c;
|
||||
var counter = 0;
|
||||
var incr = function(){ counter++; };
|
||||
var incr = function(){ return ++counter; };
|
||||
var debouncedIncr = _.debounce(incr, 50, true);
|
||||
debouncedIncr(); debouncedIncr(); debouncedIncr();
|
||||
a = debouncedIncr();
|
||||
b = debouncedIncr();
|
||||
c = debouncedIncr();
|
||||
equal(a, 1);
|
||||
equal(b, 1);
|
||||
equal(c, 1);
|
||||
equal(counter, 1, 'incr was called immediately');
|
||||
setTimeout(debouncedIncr, 30);
|
||||
setTimeout(debouncedIncr, 60);
|
||||
|
||||
70
vendor/underscore/test/objects.js
vendored
70
vendor/underscore/test/objects.js
vendored
@@ -15,17 +15,22 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
test("values", function() {
|
||||
equal(_.values({one : 1, two : 2}).join(', '), '1, 2', 'can extract the values from an object');
|
||||
equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object');
|
||||
equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is "length"');
|
||||
});
|
||||
|
||||
test("pairs", function() {
|
||||
deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs');
|
||||
deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"');
|
||||
});
|
||||
|
||||
test("invert", function() {
|
||||
var obj = {first: 'Moe', second: 'Larry', third: 'Curly'};
|
||||
equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object');
|
||||
ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started');
|
||||
|
||||
var obj = {length: 3};
|
||||
ok(_.invert(obj)['3'] == 'length', 'can invert an object with "length"')
|
||||
});
|
||||
|
||||
test("functions", function() {
|
||||
@@ -228,14 +233,6 @@ $(document).ready(function() {
|
||||
ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal");
|
||||
ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty");
|
||||
|
||||
// According to the Microsoft deviations spec, section 2.1.26, JScript 5.x treats `undefined`
|
||||
// elements in arrays as elisions. Thus, sparse arrays and dense arrays containing `undefined`
|
||||
// values are equivalent.
|
||||
if (0 in [undefined]) {
|
||||
ok(!_.isEqual(Array(3), [undefined, undefined, undefined]), "Sparse and dense arrays are not equal");
|
||||
ok(!_.isEqual([undefined, undefined, undefined], Array(3)), "Commutative equality is implemented for sparse and dense arrays");
|
||||
}
|
||||
|
||||
// Simple objects.
|
||||
ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal");
|
||||
ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal");
|
||||
@@ -351,57 +348,8 @@ $(document).ready(function() {
|
||||
ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal');
|
||||
ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods');
|
||||
|
||||
// Custom `isEqual` methods - comparing different types
|
||||
LocalizedString = (function() {
|
||||
function LocalizedString(id) { this.id = id; this.string = (this.id===10)? 'Bonjour': ''; }
|
||||
LocalizedString.prototype.isEqual = function(that) {
|
||||
if (_.isString(that)) return this.string == that;
|
||||
else if (that instanceof LocalizedString) return this.id == that.id;
|
||||
return false;
|
||||
};
|
||||
return LocalizedString;
|
||||
})();
|
||||
var localized_string1 = new LocalizedString(10), localized_string2 = new LocalizedString(10), localized_string3 = new LocalizedString(11);
|
||||
ok(_.isEqual(localized_string1, localized_string2), 'comparing same typed instances with same ids');
|
||||
ok(!_.isEqual(localized_string1, localized_string3), 'comparing same typed instances with different ids');
|
||||
ok(_.isEqual(localized_string1, 'Bonjour'), 'comparing different typed instances with same values');
|
||||
ok(_.isEqual('Bonjour', localized_string1), 'comparing different typed instances with same values');
|
||||
ok(!_.isEqual('Bonjour', localized_string3), 'comparing two localized strings with different ids');
|
||||
ok(!_.isEqual(localized_string1, 'Au revoir'), 'comparing different typed instances with different values');
|
||||
ok(!_.isEqual('Au revoir', localized_string1), 'comparing different typed instances with different values');
|
||||
|
||||
// Custom `isEqual` methods - comparing with serialized data
|
||||
Date.prototype.toJSON = function() {
|
||||
return {
|
||||
_type:'Date',
|
||||
year:this.getUTCFullYear(),
|
||||
month:this.getUTCMonth(),
|
||||
day:this.getUTCDate(),
|
||||
hours:this.getUTCHours(),
|
||||
minutes:this.getUTCMinutes(),
|
||||
seconds:this.getUTCSeconds()
|
||||
};
|
||||
};
|
||||
Date.prototype.isEqual = function(that) {
|
||||
var this_date_components = this.toJSON();
|
||||
var that_date_components = (that instanceof Date) ? that.toJSON() : that;
|
||||
delete this_date_components['_type']; delete that_date_components['_type'];
|
||||
return _.isEqual(this_date_components, that_date_components);
|
||||
};
|
||||
|
||||
var date = new Date();
|
||||
var date_json = {
|
||||
_type:'Date',
|
||||
year:date.getUTCFullYear(),
|
||||
month:date.getUTCMonth(),
|
||||
day:date.getUTCDate(),
|
||||
hours:date.getUTCHours(),
|
||||
minutes:date.getUTCMinutes(),
|
||||
seconds:date.getUTCSeconds()
|
||||
};
|
||||
|
||||
ok(_.isEqual(date_json, date), 'serialized date matches date');
|
||||
ok(_.isEqual(date, date_json), 'date matches serialized date');
|
||||
// Objects from another frame.
|
||||
ok(_.isEqual({}, iObject));
|
||||
});
|
||||
|
||||
test("isEmpty", function() {
|
||||
@@ -438,6 +386,7 @@ $(document).ready(function() {
|
||||
parent.iNull = null;\
|
||||
parent.iBoolean = new Boolean(false);\
|
||||
parent.iUndefined = undefined;\
|
||||
parent.iObject = {};\
|
||||
</script>"
|
||||
);
|
||||
iDoc.close();
|
||||
@@ -550,6 +499,7 @@ $(document).ready(function() {
|
||||
ok(!_.isNaN(0), '0 is not NaN');
|
||||
ok(_.isNaN(NaN), 'but NaN is');
|
||||
ok(_.isNaN(iNaN), 'even from another frame');
|
||||
ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN');
|
||||
});
|
||||
|
||||
test("isNull", function() {
|
||||
|
||||
5
vendor/underscore/test/utility.js
vendored
5
vendor/underscore/test/utility.js
vendored
@@ -241,4 +241,9 @@ $(document).ready(function() {
|
||||
deepEqual(settings, {});
|
||||
});
|
||||
|
||||
test('#779 - delimeters are applied to unescaped text.', 1, function() {
|
||||
var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
|
||||
strictEqual(template(), '<<\nx\n>>');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
38
vendor/underscore/underscore-min.js
vendored
38
vendor/underscore/underscore-min.js
vendored
File diff suppressed because one or more lines are too long
321
vendor/underscore/underscore.js
vendored
321
vendor/underscore/underscore.js
vendored
@@ -1,10 +1,7 @@
|
||||
// Underscore.js 1.3.3
|
||||
// Underscore.js 1.4.2
|
||||
// http://underscorejs.org
|
||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore may be freely distributed under the MIT license.
|
||||
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore
|
||||
|
||||
(function() {
|
||||
|
||||
@@ -26,6 +23,7 @@
|
||||
// Create quick reference variables for speed access to core prototypes.
|
||||
var push = ArrayProto.push,
|
||||
slice = ArrayProto.slice,
|
||||
concat = ArrayProto.concat,
|
||||
unshift = ArrayProto.unshift,
|
||||
toString = ObjProto.toString,
|
||||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||
@@ -67,7 +65,7 @@
|
||||
}
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '1.3.3';
|
||||
_.VERSION = '1.4.2';
|
||||
|
||||
// Collection Functions
|
||||
// --------------------
|
||||
@@ -132,11 +130,24 @@
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
}
|
||||
var reversed = _.toArray(obj).reverse();
|
||||
if (context && !initial) iterator = _.bind(iterator, context);
|
||||
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
|
||||
var length = obj.length;
|
||||
if (length !== +length) {
|
||||
var keys = _.keys(obj);
|
||||
length = keys.length;
|
||||
}
|
||||
each(obj, function(value, index, list) {
|
||||
index = keys ? keys[--length] : --length;
|
||||
if (!initial) {
|
||||
memo = obj[index];
|
||||
initial = true;
|
||||
} else {
|
||||
memo = iterator.call(context, memo, obj[index], index, list);
|
||||
}
|
||||
});
|
||||
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||
return memo;
|
||||
};
|
||||
|
||||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||
@@ -202,9 +213,9 @@
|
||||
return !!result;
|
||||
};
|
||||
|
||||
// Determine if a given value is included in the array or object using `===`.
|
||||
// Aliased as `contains`.
|
||||
_.include = _.contains = function(obj, target) {
|
||||
// Determine if the array or object contains a given value (using `===`).
|
||||
// Aliased as `include`.
|
||||
_.contains = _.include = function(obj, target) {
|
||||
var found = false;
|
||||
if (obj == null) return found;
|
||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||
@@ -227,6 +238,18 @@
|
||||
return _.map(obj, function(value){ return value[key]; });
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `filter`: selecting only objects
|
||||
// with specific `key:value` pairs.
|
||||
_.where = function(obj, attrs) {
|
||||
if (_.isEmpty(attrs)) return [];
|
||||
return _.filter(obj, function(value) {
|
||||
for (var key in attrs) {
|
||||
if (attrs[key] !== value[key]) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
// Return the maximum element or (element-based computation).
|
||||
// Can't optimize arrays of integers longer than 65,535 elements.
|
||||
// See: https://bugs.webkit.org/show_bug.cgi?id=80797
|
||||
@@ -263,40 +286,44 @@
|
||||
var index = 0;
|
||||
var shuffled = [];
|
||||
each(obj, function(value) {
|
||||
rand = Math.floor(Math.random() * ++index);
|
||||
rand = _.random(index++);
|
||||
shuffled[index - 1] = shuffled[rand];
|
||||
shuffled[rand] = value;
|
||||
});
|
||||
return shuffled;
|
||||
};
|
||||
|
||||
// An internal function to generate lookup iterators.
|
||||
var lookupIterator = function(value) {
|
||||
return _.isFunction(value) ? value : function(obj){ return obj[value]; };
|
||||
};
|
||||
|
||||
// Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = function(obj, val, context) {
|
||||
var iterator = lookupIterator(obj, val);
|
||||
_.sortBy = function(obj, value, context) {
|
||||
var iterator = lookupIterator(value);
|
||||
return _.pluck(_.map(obj, function(value, index, list) {
|
||||
return {
|
||||
value : value,
|
||||
index : index,
|
||||
criteria : iterator.call(context, value, index, list)
|
||||
};
|
||||
}).sort(function(left, right) {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
if (a === void 0) return 1;
|
||||
if (b === void 0) return -1;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
var a = left.criteria;
|
||||
var b = right.criteria;
|
||||
if (a !== b) {
|
||||
if (a > b || a === void 0) return 1;
|
||||
if (a < b || b === void 0) return -1;
|
||||
}
|
||||
return left.index < right.index ? -1 : 1;
|
||||
}), 'value');
|
||||
};
|
||||
|
||||
// An internal function to generate lookup iterators.
|
||||
var lookupIterator = function(obj, val) {
|
||||
return _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
||||
};
|
||||
|
||||
// An internal function used for aggregate "group by" operations.
|
||||
var group = function(obj, val, behavior) {
|
||||
var group = function(obj, value, context, behavior) {
|
||||
var result = {};
|
||||
var iterator = lookupIterator(obj, val);
|
||||
var iterator = lookupIterator(value);
|
||||
each(obj, function(value, index) {
|
||||
var key = iterator(value, index);
|
||||
var key = iterator.call(context, value, index, obj);
|
||||
behavior(result, key, value);
|
||||
});
|
||||
return result;
|
||||
@@ -304,45 +331,45 @@
|
||||
|
||||
// Groups the object's values by a criterion. Pass either a string attribute
|
||||
// to group by, or a function that returns the criterion.
|
||||
_.groupBy = function(obj, val) {
|
||||
return group(obj, val, function(result, key, value) {
|
||||
(result[key] || (result[key] = [])).push(value);
|
||||
_.groupBy = function(obj, value, context) {
|
||||
return group(obj, value, context, function(result, key, value) {
|
||||
(_.has(result, key) ? result[key] : (result[key] = [])).push(value);
|
||||
});
|
||||
};
|
||||
|
||||
// Counts instances of an object that group by a certain criterion. Pass
|
||||
// either a string attribute to count by, or a function that returns the
|
||||
// criterion.
|
||||
_.countBy = function(obj, val) {
|
||||
return group(obj, val, function(result, key, value) {
|
||||
result[key] || (result[key] = 0);
|
||||
_.countBy = function(obj, value, context) {
|
||||
return group(obj, value, context, function(result, key, value) {
|
||||
if (!_.has(result, key)) result[key] = 0;
|
||||
result[key]++;
|
||||
});
|
||||
};
|
||||
|
||||
// Use a comparator function to figure out the smallest index at which
|
||||
// an object should be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = function(array, obj, iterator) {
|
||||
iterator || (iterator = _.identity);
|
||||
var value = iterator(obj);
|
||||
_.sortedIndex = function(array, obj, iterator, context) {
|
||||
iterator = iterator == null ? _.identity : lookupIterator(iterator);
|
||||
var value = iterator.call(context, obj);
|
||||
var low = 0, high = array.length;
|
||||
while (low < high) {
|
||||
var mid = (low + high) >> 1;
|
||||
iterator(array[mid]) < value ? low = mid + 1 : high = mid;
|
||||
var mid = (low + high) >>> 1;
|
||||
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
|
||||
}
|
||||
return low;
|
||||
};
|
||||
|
||||
// Safely convert anything iterable into a real, live array.
|
||||
_.toArray = function(obj) {
|
||||
if (!obj) return [];
|
||||
if (_.isArray(obj) || _.isArguments(obj)) return slice.call(obj);
|
||||
if (_.isFunction(obj.toArray)) return obj.toArray();
|
||||
if (!obj) return [];
|
||||
if (obj.length === +obj.length) return slice.call(obj);
|
||||
return _.values(obj);
|
||||
};
|
||||
|
||||
// Return the number of elements in an object.
|
||||
_.size = function(obj) {
|
||||
if (obj == null) return 0;
|
||||
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
|
||||
};
|
||||
|
||||
@@ -353,6 +380,7 @@
|
||||
// values in the array. Aliased as `head` and `take`. The **guard** check
|
||||
// allows it to work with `_.map`.
|
||||
_.first = _.head = _.take = function(array, n, guard) {
|
||||
if (array == null) return void 0;
|
||||
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
||||
};
|
||||
|
||||
@@ -367,6 +395,7 @@
|
||||
// Get the last element of an array. Passing **n** will return the last N
|
||||
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||
_.last = function(array, n, guard) {
|
||||
if (array == null) return void 0;
|
||||
if ((n != null) && !guard) {
|
||||
return slice.call(array, Math.max(array.length - n, 0));
|
||||
} else {
|
||||
@@ -412,23 +441,23 @@
|
||||
// Produce a duplicate-free version of the array. If the array has already
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
// Aliased as `unique`.
|
||||
_.uniq = _.unique = function(array, isSorted, iterator) {
|
||||
var initial = iterator ? _.map(array, iterator) : array;
|
||||
_.uniq = _.unique = function(array, isSorted, iterator, context) {
|
||||
var initial = iterator ? _.map(array, iterator, context) : array;
|
||||
var results = [];
|
||||
_.reduce(initial, function(memo, value, index) {
|
||||
if (isSorted ? (_.last(memo) !== value || !memo.length) : !_.include(memo, value)) {
|
||||
memo.push(value);
|
||||
var seen = [];
|
||||
each(initial, function(value, index) {
|
||||
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
|
||||
seen.push(value);
|
||||
results.push(array[index]);
|
||||
}
|
||||
return memo;
|
||||
}, []);
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Produce an array that contains the union: each distinct element from all of
|
||||
// the passed-in arrays.
|
||||
_.union = function() {
|
||||
return _.uniq(flatten(arguments, true, []));
|
||||
return _.uniq(concat.apply(ArrayProto, arguments));
|
||||
};
|
||||
|
||||
// Produce an array that contains every item shared between all the
|
||||
@@ -445,8 +474,8 @@
|
||||
// Take the difference between one array and a number of other arrays.
|
||||
// Only the elements present in just the first array will remain.
|
||||
_.difference = function(array) {
|
||||
var rest = flatten(slice.call(arguments, 1), true, []);
|
||||
return _.filter(array, function(value){ return !_.include(rest, value); });
|
||||
var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
|
||||
return _.filter(array, function(value){ return !_.contains(rest, value); });
|
||||
};
|
||||
|
||||
// Zip together multiple lists into a single array -- elements that share
|
||||
@@ -465,6 +494,7 @@
|
||||
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
||||
// the corresponding values.
|
||||
_.object = function(list, values) {
|
||||
if (list == null) return {};
|
||||
var result = {};
|
||||
for (var i = 0, l = list.length; i < l; i++) {
|
||||
if (values) {
|
||||
@@ -484,21 +514,28 @@
|
||||
// for **isSorted** to use binary search.
|
||||
_.indexOf = function(array, item, isSorted) {
|
||||
if (array == null) return -1;
|
||||
var i, l;
|
||||
var i = 0, l = array.length;
|
||||
if (isSorted) {
|
||||
i = _.sortedIndex(array, item);
|
||||
return array[i] === item ? i : -1;
|
||||
if (typeof isSorted == 'number') {
|
||||
i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
|
||||
} else {
|
||||
i = _.sortedIndex(array, item);
|
||||
return array[i] === item ? i : -1;
|
||||
}
|
||||
}
|
||||
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||
for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
|
||||
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
|
||||
for (; i < l; i++) if (array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||
_.lastIndexOf = function(array, item) {
|
||||
_.lastIndexOf = function(array, item, from) {
|
||||
if (array == null) return -1;
|
||||
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||
var i = array.length;
|
||||
var hasIndex = from != null;
|
||||
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
|
||||
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
|
||||
}
|
||||
var i = (hasIndex ? from : array.length);
|
||||
while (i--) if (array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
@@ -585,25 +622,25 @@
|
||||
// Returns a function, that, when invoked, will only be triggered at most once
|
||||
// during a given window of time.
|
||||
_.throttle = function(func, wait) {
|
||||
var context, args, timeout, throttling, more, result;
|
||||
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
||||
var context, args, timeout, result;
|
||||
var previous = 0;
|
||||
var later = function() {
|
||||
previous = new Date;
|
||||
timeout = null;
|
||||
result = func.apply(context, args);
|
||||
};
|
||||
return function() {
|
||||
context = this; args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (more) {
|
||||
result = func.apply(context, args);
|
||||
}
|
||||
whenDone();
|
||||
};
|
||||
if (!timeout) timeout = setTimeout(later, wait);
|
||||
if (throttling) {
|
||||
more = true;
|
||||
} else {
|
||||
throttling = true;
|
||||
var now = new Date;
|
||||
var remaining = wait - (now - previous);
|
||||
context = this;
|
||||
args = arguments;
|
||||
if (remaining <= 0) {
|
||||
clearTimeout(timeout);
|
||||
previous = now;
|
||||
result = func.apply(context, args);
|
||||
} else if (!timeout) {
|
||||
timeout = setTimeout(later, remaining);
|
||||
}
|
||||
whenDone();
|
||||
return result;
|
||||
};
|
||||
};
|
||||
@@ -613,17 +650,18 @@
|
||||
// N milliseconds. If `immediate` is passed, trigger the function on the
|
||||
// leading edge, instead of the trailing.
|
||||
_.debounce = function(func, wait, immediate) {
|
||||
var timeout;
|
||||
var timeout, result;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (!immediate) func.apply(context, args);
|
||||
if (!immediate) result = func.apply(context, args);
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) func.apply(context, args);
|
||||
if (callNow) result = func.apply(context, args);
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -645,7 +683,8 @@
|
||||
// conditionally execute the original function.
|
||||
_.wrap = function(func, wrapper) {
|
||||
return function() {
|
||||
var args = [func].concat(slice.call(arguments, 0));
|
||||
var args = [func];
|
||||
push.apply(args, arguments);
|
||||
return wrapper.apply(this, args);
|
||||
};
|
||||
};
|
||||
@@ -687,22 +726,23 @@
|
||||
|
||||
// Retrieve the values of an object's properties.
|
||||
_.values = function(obj) {
|
||||
return _.map(obj, _.identity);
|
||||
var values = [];
|
||||
for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
|
||||
return values;
|
||||
};
|
||||
|
||||
// Convert an object into a list of `[key, value]` pairs.
|
||||
_.pairs = function(obj) {
|
||||
return _.map(obj, function(value, key) {
|
||||
return [key, value];
|
||||
});
|
||||
var pairs = [];
|
||||
for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
|
||||
return pairs;
|
||||
};
|
||||
|
||||
// Invert the keys and values of an object. The values must be serializable.
|
||||
_.invert = function(obj) {
|
||||
return _.reduce(obj, function(memo, value, key) {
|
||||
memo[value] = key;
|
||||
return memo;
|
||||
}, {});
|
||||
var result = {};
|
||||
for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
|
||||
return result;
|
||||
};
|
||||
|
||||
// Return a sorted list of the function names available on the object.
|
||||
@@ -728,7 +768,7 @@
|
||||
// Return a copy of the object only containing the whitelisted properties.
|
||||
_.pick = function(obj) {
|
||||
var copy = {};
|
||||
var keys = _.flatten(slice.call(arguments, 1));
|
||||
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
||||
each(keys, function(key) {
|
||||
if (key in obj) copy[key] = obj[key];
|
||||
});
|
||||
@@ -738,9 +778,9 @@
|
||||
// Return a copy of the object without the blacklisted properties.
|
||||
_.omit = function(obj) {
|
||||
var copy = {};
|
||||
var keys = _.flatten(slice.call(arguments, 1));
|
||||
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
||||
for (var key in obj) {
|
||||
if (!_.include(keys, key)) copy[key] = obj[key];
|
||||
if (!_.contains(keys, key)) copy[key] = obj[key];
|
||||
}
|
||||
return copy;
|
||||
};
|
||||
@@ -779,9 +819,6 @@
|
||||
// Unwrap any wrapped objects.
|
||||
if (a instanceof _) a = a._wrapped;
|
||||
if (b instanceof _) b = b._wrapped;
|
||||
// Invoke a custom `isEqual` method if one is provided.
|
||||
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
||||
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
||||
// Compare `[[Class]]` names.
|
||||
var className = toString.call(a);
|
||||
if (className != toString.call(b)) return false;
|
||||
@@ -829,13 +866,17 @@
|
||||
if (result) {
|
||||
// Deep compare the contents, ignoring non-numeric properties.
|
||||
while (size--) {
|
||||
// Ensure commutative equality for sparse arrays.
|
||||
if (!(result = size in a == size in b && eq(a[size], b[size], aStack, bStack))) break;
|
||||
if (!(result = eq(a[size], b[size], aStack, bStack))) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Objects with different constructors are not equivalent.
|
||||
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
|
||||
// Objects with different constructors are not equivalent, but `Object`s
|
||||
// from different frames are.
|
||||
var aCtor = a.constructor, bCtor = b.constructor;
|
||||
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
|
||||
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
|
||||
return false;
|
||||
}
|
||||
// Deep compare objects.
|
||||
for (var key in a) {
|
||||
if (_.has(a, key)) {
|
||||
@@ -875,7 +916,7 @@
|
||||
|
||||
// Is a given value a DOM element?
|
||||
_.isElement = function(obj) {
|
||||
return !!(obj && obj.nodeType == 1);
|
||||
return !!(obj && obj.nodeType === 1);
|
||||
};
|
||||
|
||||
// Is a given value an array?
|
||||
@@ -904,15 +945,21 @@
|
||||
};
|
||||
}
|
||||
|
||||
// Optimize `isFunction` if appropriate.
|
||||
if (typeof (/./) !== 'function') {
|
||||
_.isFunction = function(obj) {
|
||||
return typeof obj === 'function';
|
||||
};
|
||||
}
|
||||
|
||||
// Is a given object a finite number?
|
||||
_.isFinite = function(obj) {
|
||||
return _.isNumber(obj) && isFinite(obj);
|
||||
};
|
||||
|
||||
// Is the given value `NaN`?
|
||||
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
||||
_.isNaN = function(obj) {
|
||||
// `NaN` is the only value for which `===` is not reflexive.
|
||||
return obj !== obj;
|
||||
return _.isNumber(obj) && obj != +obj;
|
||||
};
|
||||
|
||||
// Is a given value a boolean?
|
||||
@@ -958,6 +1005,10 @@
|
||||
|
||||
// Return a random integer between min and max (inclusive).
|
||||
_.random = function(min, max) {
|
||||
if (max == null) {
|
||||
max = min;
|
||||
min = 0;
|
||||
}
|
||||
return min + (0 | Math.random() * (max - min + 1));
|
||||
};
|
||||
|
||||
@@ -1003,8 +1054,8 @@
|
||||
each(_.functions(obj), function(name){
|
||||
var func = _[name] = obj[name];
|
||||
_.prototype[name] = function() {
|
||||
var args = slice.call(arguments);
|
||||
args.unshift(this._wrapped);
|
||||
var args = [this._wrapped];
|
||||
push.apply(args, arguments);
|
||||
return result.call(this, func.apply(_, args));
|
||||
};
|
||||
});
|
||||
@@ -1029,31 +1080,21 @@
|
||||
// When customizing `templateSettings`, if you don't want to define an
|
||||
// interpolation, evaluation or escaping regex, we need one that is
|
||||
// guaranteed not to match.
|
||||
var noMatch = /.^/;
|
||||
var noMatch = /(.)^/;
|
||||
|
||||
// Certain characters need to be escaped so that they can be put into a
|
||||
// string literal.
|
||||
var escapes = {
|
||||
'\\': '\\',
|
||||
"'": "'",
|
||||
r: '\r',
|
||||
n: '\n',
|
||||
t: '\t',
|
||||
u2028: '\u2028',
|
||||
u2029: '\u2029'
|
||||
"'": "'",
|
||||
'\\': '\\',
|
||||
'\r': 'r',
|
||||
'\n': 'n',
|
||||
'\t': 't',
|
||||
'\u2028': 'u2028',
|
||||
'\u2029': 'u2029'
|
||||
};
|
||||
|
||||
for (var key in escapes) escapes[escapes[key]] = key;
|
||||
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
|
||||
var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
|
||||
|
||||
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
||||
// that had been previously added.
|
||||
var unescape = function(code) {
|
||||
return code.replace(unescaper, function(match, escape) {
|
||||
return escapes[escape];
|
||||
});
|
||||
};
|
||||
|
||||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||
@@ -1061,22 +1102,26 @@
|
||||
_.template = function(text, data, settings) {
|
||||
settings = _.defaults({}, settings, _.templateSettings);
|
||||
|
||||
// Compile the template source, taking care to escape characters that
|
||||
// cannot be included in a string literal and then unescape them in code
|
||||
// blocks.
|
||||
var source = "__p+='" + text
|
||||
.replace(escaper, function(match) {
|
||||
return '\\' + escapes[match];
|
||||
})
|
||||
.replace(settings.escape || noMatch, function(match, code) {
|
||||
return "'+\n((__t=(" + unescape(code) + "))==null?'':_.escape(__t))+\n'";
|
||||
})
|
||||
.replace(settings.interpolate || noMatch, function(match, code) {
|
||||
return "'+\n((__t=(" + unescape(code) + "))==null?'':__t)+\n'";
|
||||
})
|
||||
.replace(settings.evaluate || noMatch, function(match, code) {
|
||||
return "';\n" + unescape(code) + "\n__p+='";
|
||||
}) + "';\n";
|
||||
// Combine delimiters into one regular expression via alternation.
|
||||
var matcher = new RegExp([
|
||||
(settings.escape || noMatch).source,
|
||||
(settings.interpolate || noMatch).source,
|
||||
(settings.evaluate || noMatch).source
|
||||
].join('|') + '|$', 'g');
|
||||
|
||||
// Compile the template source, escaping string literals appropriately.
|
||||
var index = 0;
|
||||
var source = "__p+='";
|
||||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||||
source += text.slice(index, offset)
|
||||
.replace(escaper, function(match) { return '\\' + escapes[match]; });
|
||||
source +=
|
||||
escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
|
||||
interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
|
||||
evaluate ? "';\n" + evaluate + "\n__p+='" : '';
|
||||
index = offset + match.length;
|
||||
});
|
||||
source += "';\n";
|
||||
|
||||
// If a variable is not specified, place data values in local scope.
|
||||
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
||||
|
||||
Reference in New Issue
Block a user